Executing a batch file during installation [duplicate] - batch-file

Currently my batch file is in [Run] section. I need my batch file to execute before the [Files] section. Is there a way to do this in Inno Setup? Currently the [Run] section always execute after [Files] section.
[Run]
Filename: "C:\Users\Scripts\Install\Install.bat"; Parameters: {code:GetDatabaseName}
[Files]
Source: "C:\Users\MyApp\*"; DestDir: "\\MyServer\MyApp"; Flags: recursesubdirs createallsubdirs

If it needs to be done at the beginning of the setup, use Exec() in the PrepareToInstall() or CurStepChanged(ssInstall) event functions.
These are both after the user has said "go ahead, install" but before anything else.
PrepareToInstall() also allows you to cancel the install with a nice warning.
If the file needs to be extracted from the setup first, then you can preceed it with ExtractTemporaryFile()

Continuing Deanna's great answer, code example:
[code]
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
ResultCode: integer;
begin
Exec(ExpandConstant('{app}\serviceDeployment\unInstallService.bat'), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode)
end;
this code always returns an empty string, which tells the setup to continue.
In case you want to stop setup (in some error cases) you need to return a non empty string and it will be displayed to the user (and setup will be stopped).
In order to return an error string add this line in PrepareToInstall's:
Result := 'Your Error Description';

You can use the InitializeSetup event + some pascal scripting.
See; How to run a file before setup with Inno Setup
Not mentioned in that example; to get the file from the installer you would use ExtractTemporaryFile('your.bat') then Exec(ExpandConstant('{tmp}\your.bat ... to run it.

Related

Why does my program work fine by running it directly but not as a service? Linux C

Goodday guys,
I am trying to build and run program in linux (raspberry) as a service.
It is a sample application that uses the Cerence SDK C API that implements a wake-up-word (WUW) plus command utterance recognition.
I can execute it by ./name.exe or using the Makefile commands.
The problem is that when I execute the program by console it works fine, without any problem.
When I try to execute it as a service (using both systemd or crontab and also rc.local), an error occours.
This is the function that gives me error:
printf("Selecting audio configuration %s\n", audioScenarioName);
rc = nuance_audio_IAudioManager_activateScenario(audioMgr, audioScenarioName);
if (NUANCE_COMMON_OK != rc) {
printf("Audio scenario activation failed: %d\n", rc); <-- returns 1 (error, impossible to activate scenario)
return rc;
}
ActivateScenario it's a function that simply selects the correct mic (audioScenarioName) following a JSON file and the audio manager (audioMgr).
Unfortunately this function returns 1 if something goes wrong, closes the program and nothing else.
This is the JSON:
"type": "AudioInput",
"name": "mic_input",
"adapter_type": "CUSTOM_AUDIO",
"adapter_params": {
"device_name": "default"
},
"audio_format": { "uses": "16khz_1ch" }
The service should be running as root permissions (default).
I also tried by setting the whole folder as chmod -R 777 as a test, but same problem.
This is my service:
[Unit]
Description=My Service
[Service]
Type=simple
ExecStart=+/home/pi/.../nameexec
Restart=on-failure
RestartSec=5
KillMode=process
[Install]
WantedBy=multi-user.target
I've also set the absolute path of its lib directory that it needs into the ld.so.conf file.
The only libraries I put in it are the .so ones, but not .h.
I am now trying to understand what might be different about starting the same executable but in different ways.
Could it be a permissions issue? Or is it not detecting the microphone? Any library out of place?
I really don't know why it works with the classic command and not as a service.
Can someone please help me with this?
Thank you in advance!
I succeeded!
The problem was the microphone being used.
Using Raspbian ver. Desktop, I set the mic from the bottom right part of the taskbar and changed the defaults in/out.
But these settings seem to be not system-wide and not used by the services in background (even though the "User=" is set to "pi").
So I had to change alsa.conf file:
sudo nano /usr/share/alsa/alsa.conf
Then find and edit these lines:
defaults.ctl.card cardnumber
defaults.pcm.card cardnumber
You can find the card number by running arecord -l.

CopyFile function only works on xp

I have a delphi form with a button on it. At the click of this button, it allows user to browse for a file and copy the file to a directory.
My code for the function is this:
function TdmData.CopyAFile(Const Sourcefile, DestFile: string): boolean;
var Src, Dest : PChar;
begin
Src := StrAlloc(Length(SourceFile)+1);
Dest := StrAlloc(Length(DestFile)+1);
try
StrPCopy(Src,SourceFile);
StrPCopy(Dest,DestFile);
result := (CopyFile(Src,Dest,FALSE));
finally
StrDispose(Src);
StrDispose(Dest);
end;
end;
The click event for the button:
CopyAFile(fn, Path +'\'+ ExtractFileName(fn));
What I cant understand when I run this form and press the button on a win XP machine, it works fine, if I browse to the directory to where it is being copied to I can see the file in there.
However running this form on a later OS such as Win 8.1 it does not copy the file, again checking the directory I see no file in there.
I don't get any errors, I've stepped through the code which goes through fine.
Has anyone ever come across this or have an idea what the cause could be? If so any help would be great.
You are not doing any error checking.
If the CopyFile function fails, the return value is zero. To get extended error information call GetLastError (or raise an exception via RaiseLastOSError)
e.g.
if not CopyFile(A, B, False) then
RaiseLastOSError;
or equivalently
Win32Check(CopyFile(A, B, False));
BTW, correct usage is:
CopyFile(PChar(Sourcefile) , PChar(Destfile), False);
No need for the extra allocations.
If you do not include a UAC manifest, then your application is running in virtualized mode. And saving files to restricted areas e.g. Program Files will not raise any errors but actually save the file into a virtual store location e.g. [CSIDL_LOCAL_APPDATA]\VirtualStore\Program Files.

InstallShiled : Custom Action not able to read values from INI File

I am trying to read values from ".ini" file using install script Custom Action which will be installed at the target location. Below Install-script Code line doesn't read any values even the file is there at target location during installation.
Install Script Code :
GetProfString(TARGETDIR + "SampleSetup.ini","Main","AppTitle",szItemName);
Custom Action : Below is the major custom Action detail which was scheduled to be run "After InstallFinalize".
Function Name : AddDesktopShortCut (Custom Install Script Function)
Target : Synchonous(Check Exit Code)
In-Script Execution : Immediate Execution
Execution Scheduling : Always execute
Install UI Sequence :
Install Exec Sequence : After IntallFinalize
Install Exec Condition : Not Installed
Remaining Settings are the default ones.
Any help will be highly appreciated. Thanks for your Time.
If that's all of your code, how can you tell if it read the value?
I would suggest either using the debugger, or sprinkling some MessageBox calls in to see what values your program uses. In particular, ensure the ini file is where your code is looking (TARGETDIR + "SampleSetup.ini" should likely be TARGETDIR ^ "SampleSetup.ini" instead), check the return code from GetProfString, and see what szItemName is after the call.

C script running as cron giving permission denied error

I have a .c file compiled and would like to run via a cron job but I end up getting this error:
/bin/sh: /usr/local/bin/get1Receive.c: Permission denied.
What is causing this error and how do I fix it?
Should I be running the .c file in cron or a different compiled file?
Results from /tmp/myvars
GROUPS=()
HOME=/root
HOSTNAME=capture
HOSTTYPE=x86_64
IFS='
'
LOGNAME=root
MACHTYPE=x86_64-redhat-linux-gnu
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PATH=/usr/bin:/bin
POSIXLY_CORRECT=y
PPID=11086
PS4='+ '
PWD=/root
SHELL=/bin/sh
SHELLOPTS=braceexpand:hashall:interactive-comments:posix
SHLVL=1
TERM=dumb
UID=0
USER=root
_=/bin/sh
Results from file get1Receive.c
file get1Receive.c
get1Receive.c: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
Snippet of codes.
sprintf(queryBuf1,"SELECT ipDest, macDest,portDest, sum(totalBits) FROM dataReceive WHERE timeStampID between '%s' And '%s' GROUP BY ipDest, macDest, portDest ",buff1,buff2);
printf("\nQuery receive %s",queryBuf1);
if(mysql_query(localConn, queryBuf1))
{
//fprintf(stderr, "%s\n", mysql_error(localConn));
printf("Error in first query of select %s\n",mysql_error(localConn));
exit(1);
}
localRes1 = mysql_store_result(localConn);
int num_fields = mysql_num_fields(localRes1);
printf("\nNumf of fields : %d",num_fields);
printf("\nNof of row : %lu",mysql_num_rows(localRes1));
If the output of this command:
file get1Receive1.c
shows that file name to be a valid executable that part is very unusual, but okay.
Assuming you are using biz14 (or your real username's ) crontab try this:
use the command crontab -e to create this line in your crontab:
* * * * * set > /tmp/myvars
Wait a few minutes, go back into crontab -e and delete that entry.
Use the set command from the command line to see what variables and aliases exist.
Compare that with that you see in /tmp/myvars You have to change how your C code executes by changing the variables and aliases the cron job runs with.
If you are running the cron job in someone else's crontab, then you have a bigger problem. Check file permissions on get1Receive1.c. and the directory it lives in. That other user (the one who wons the crontab) has to have permissions set on your directory and get1Receive1.c so the job can run.
Example crontab entry:
0 10 * * 1-5 /path/to/get1Receive1.c > /tmp/outputfile
Read /tmp/outputfile to see what you got. You are using printf in your code. printf only writes to the controlling terminal. There is no controlling terminal, so redirect the printf stuff to a file.
Last effort on this problem:
Check return codes on EVERYTHING. All C functions like fread(), any db function, etc. If a return code gives a fail response ( these are different for different function calls) then report the error number the line number and function - gcc provides LINE and func. Example:
printf("error on line %d in my code %s, error message =%s\n", __LINE__, __func__, [string of error message]);
If you do not check return codes you are writing very poor C code.
CHECK return codes, please, now!
Permission wise you could have two issues.
1. The 'c' file's permissions don't allow who you are running it as to run it.
2. You are running the cron with a script which doesn't have permissions.
Here's a helpful post: How to give permission for the cron job file?
The fact that you are running a 'c' file and referring to it as a script makes me think you're using C shell and not writing it as a C language program which would need to be compiled and have the generated executable run by the cron. If you're not using gcc or have never called gcc on your 'C' script then it's not C and call it C shell to avoid confusion.

Inno Setup: copy file to multiple destinations defined by user

During installation process user has ability to install number of some service instances (Service1- ServiceN). All the differences between these services - content of configuration files(actually there is only one executable in /Product_Root/run wich is called with different command-line params).Configuration files situated in ProductRoot/ServiceX/conf.
Folders structure looks like :
/Product_Root
----/bin
----/doc
----/Service1
---------/conf
----/Service2
---------/conf
...
----/ServiceN
---------/conf
In ProductRoot/ServiceX/conf is situated, for example, service.properties file with these contents:
#...
ServiceRoot = <%ROOT_DIRECTORY%>
ListenPort = <%PORT%>
#...
Also in /Product_Root/bin scripts for each service startup should be present:
For example :
/Product_Root/bin/Service1.run.cmd
/Product_Root/bin/Service2.run.cmd
...
/Product_Root/bin/ServiceN.run.cmd
...
Script file structure is:
service.exe ../<%SERVICE_NAME%>/conf/service.properties
All values (like <%SERVICE_NAME%>,<%PORT%> etc.) are set by user during setup process for each Service.
Amount of services is also set by user and may vary between 1 (by default) and 20-30.
In case of single service - there is no problem.
Files being copied, directories created using
[Files]
Source: {#FilesPath}\bin\*.*; DestDir: {app}\{#FileLocationPrefix}\bin; Flags: ignoreversion restartreplace
Source: {#АilesPath}\conf\*.*; DestDir: {app}\{#FileLocationPrefix}\{code:GetServiceName}\conf; Flags: ignoreversion recursesubdirs createallsubdirs restartreplace;
[Dirs]
Name: {app}\{#FileLocationPrefix}{code:GetServiceName}\conf
After in ssPostInstall step wildcards replace performed in copied files.
Question.
is it possible using Inno Setup + ISTool to do the same in case of number of services?
E.g. something like that :
[Files]
#for (i = 0; i < ServiceCount(); ++i)
Source: {#АilesPath}\conf\*.*; DestDir: {app}\{#FileLocationPrefix}\{code:GetServiceName| i}\conf; Flags: ignoreversion recursesubdirs createallsubdirs
where i — is actually configuration number.
I.e. is it possible to use information received from user during installation process in [File], [Dirs] etc. sections for multiple copying of the same files in different directories?
For copying single file in number of files with different names set by user during install process?
Or I just going in the wrong direction?
So, currently I've done this in such way. Comments are welcome.
For creating and copying all files:
#define MaxFEInstances 20
...
#sub CreateConf
Source: {#FilesPath}\conf\*.*; DestDir: {app}\{#FileLocationPrefix}{code:GetServiceName|{#counter}}\conf; Flags: ignoreversion recursesubdirs createallsubdirs restartreplace; Check: InstanceSetupRequired({#counter}); Components: main
#endsub
#for {counter = 0; counter < MaxInstances; ++counter} CreateConf
enter code here
...
function InstanceSetupRequired(InstanceNum: Integer): Boolean;
begin
Result := InstanceNum < Instances;
end;
For separate files it looks pretty same.

Resources