I am having no success in modifying a Windows Installer MSI to run a batch file after the primary output has been installed. I have searched for this and found many suggestions, but nothing that works.
- Add a Custom Action
- Custom actions can only be executable files. A batch file is not executable.
- Create a Windows Scripting Host executable that runs the batch file
- Many people have tried to do this, including on SO, and no one has been able to get this to work.
- Use WIX or InstallShield
- I do not have the time or authority to change company installer technology.
- Edit the .msi with Orca and add a custom property, then a custom action, then edit the InstallExecuteSequence, ...
- I have been trying this for hours and have only created installers that throw a system error when I run them.
What you said above is incorrect:
Custom actions can only be executable
files. A batch file is not executable.
Custom Actions (even without tools like InstallShield) can be .EXE, VBScript, JScript, or DLL based. If you write a DLL, you can write whatever code you want to call a batch file or make any changes you want to the system -- there is no limit.
Update: an example that worked for me: (entry in CustomAction table)
Action Test
Type 34
Source SystemFolder
Target cmd.exe /c c:\test.bat
ExtendedType <blank>
I was able to solve this by creating an EXE consisting essentially of:
System.Diagnostics.Process.Start(pathToBatchFile);
Adding the EXE to the MSI file then running it as a custom action.
While the answer suggested by "William Leara" is a very good start, I found a better solution here worth mentioning.
Another advantage this method has is that you can put your batch file in the application install folder rather than root C folder, but we use special flags to defer the execution to after FileCopy action, we also use noImpersonate to have higher privilege needed to run from Program Files
A few notes:
- Use TARGETDIR instead of INSTALLDIR
- Make sure to quote the paths.
These are my two custom actions. In my case I want to force native command processor to fix a few registry entries thus I do not use COMSPEC.
First action (type 50) performs command in Source with input arguments of Target, because Type is 50+1024+2048 to it is deferred action with noImpersonate flag.
- Action: FinalAction
- Type: 3122
- Source: NCOM
- Target: /c "[TARGETDIR]Fixup.bat"
Second action defines NCOM property immediately:
- Action: FinalNativeSys
- Type: 51
- Source: NCOM
- Target: [WindowsFolder]System32\cmd.exe
Then you should add these actions to InstallExecuteSequence:
- Action: FinalAction
- Condition: NOT Installed
- Sequence: 5002
And this one:
- Action: FinalNativeSys
- Condition:
- Sequence: 5001
Note that in my case I could easily tweak the actions to call reg.exe import Fixup.reg too.
Finally one can use msitran as suggested here in a post build to automate the procedure.
Make an EXE that makes a temporary .bat file to change to the whatever directory you want and CALL
another bat file that does what you need.
Tell the custom action to use that exe.
The first argument to a CPP exe is the path to the exe itself. This can be used to orient yourself, and that information could be used in the making of the temporary .bat
In my case, I added "Custom Actions".
On folder "Install" choose "Add custom action"
Choose cmd.exe (c:\windows\system32\cmd.exe)
Then in properties of cmd.exe edit "Arguments" to
"/Install /c C:\myApp.exe --exec-some-action"