I am creating an installer using WiX Toolset. I would like to backup old configuration (files with .config extension) when the checkbox is checked and then install new ones with _new appended to a name.
I have created cmd scripts to achieve that and inserted them in custom actions.
<CustomAction Id="RenameNewConfigs" Directory="INSTALLFOLDER" ExeCommand='for /r %%a in (*.config) do ren "%%~a" "%%~na_new%%~xa"' Impersonate="no" Execute="deferred" Return="ignore" />
<CustomAction Id="MoveOldConfigs" Directory="INSTALLFOLDER" ExeCommand='xcopy /SYI "..\OldConfigs" "."' Impersonate="no" Execute="deferred" Return="ignore" />
<CustomAction Id="RemoveConfigsBackup" Directory="INSTALLFOLDER" ExeCommand='rd ..\OldConfigs /S /Q' Impersonate="no" Execute="deferred" Return="ignore" />
<InstallExecuteSequence>
<Custom Action="RenameNewConfigs" After="InstallFiles">KEEP_OLD_CONFIGURATION</Custom>
<Custom Action="MoveOldConfigs" After="RenameNewConfigs">KEEP_OLD_CONFIGURATION</Custom>
<Custom Action="RemoveConfigsBackup" After="MoveOldConfigs">INSTALLED AND (NOT REMOVE="ALL")</Custom>
</InstallExecuteSequence>
During the execution (according to logs) the first and third commands produce following output:
Info 1721. There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. Action: RenameNewConfigs, location: C:\Program Files\correct\path\, command: for /r %%a in (*.config) do ren "%%~a" "%%~na_new%%~xa"
What is wrong? Why cannot execute standard command?
There's an important difference between what can be run at the command prompt and what is actually a command. In this case, for and rd are built-in and only xcopy is it's own command. To determine this, you can run where for, where xcopy and where rd at a command prompt. In addition, Windows Installer often needs you to specify the full path to a command. This may take the form of something like [SystemFolder]xcopy.exe, but is impossible for a built-in. Instead you would need to specify something like [SystemFolder]cmd.exe /c rd ...
Note that this is not a great way to actually accomplish what you want to accomplish. Not only do command prompts popping up during an installation look bad, but the do not integrate well with logging, error reporting, or rollback. If possible, you're best off using true Windows Installer functionality (such as through the DuplicateFile and RemoveFile tables), as they are designed to handle rollback scenarios. If not, you can at least get much better integration if you write a C++ custom action dll and use it instead of exes.
You need to execute your command on executable application, in your case it will be cmd.exe.
ExeCommand='cmd.exe /c "for %a in (*.config) do ren "%~a" "%~na_new%~xa"""'
Change your code into this, and it should work :)
Related
I have been trying to do something like what is posted here about creating a symbolic link in a WiX installer. It explains how to make a add-on that will make a symbolic link. However that is not what I am looking for. I am trying to use somtething like this snipping
<CustomAction Id="MakeSymbolicLink"
Directory="TARGETDIR"
ExeCommand="cmd /c mklink .\linkToItem.lnk '%CommonProgramFiles(x86)%\Additional Folders\myexecutable.exe'" />
I have tried using cmd.exe instead of cmd for this and have not been successful.
I am then call the custom action like this:
<Custom Action="MakeSymbolicLink" After="InstallFinalize" />
I have tried calling this before InstallFinalize as well and I get the same behavior.
I am aiming to create the symbolic link through this setup.
The other solution I have is being able to create a shortcut however I have not been able to find much on how to do this option for places other than the start menu or the Desktop
When I run the installer after adding these lines it fails to execute them. Without the Symbolic link custom action being called I can get the installer to complete successfully.
End goal is to get a symbolic link from the common files executable to the install location of the application.
Update
I got the Symbolic link to work changed custom action now looks like:
<CustomAction Id="MakeSymbolicLink"
Directory="TARGETDIR"
ExeCommand='cmd /c mklink .\linkToItem.lnk "%CommonProgramFiles(x86)%\Additional Folders\myexecutable.exe"'
Execute="deferred"
Impersonate="no"/>
and the call to the custom action like this:
<Custom Action="MakeSymbolicLink" Before="InstallFinalize" />
But now the when I run uninstall I get the following error message: There is a problem with this windows installer package. a program run as part of the setup did not finish as expected contact your support personnel or package vendor.
If you use something like this as your Custome action:
<CustomAction Id="MakeSymbolicLink"
Directory="TARGETDIR"
ExeCommand='cmd /c mklink .\linkToItem.lnk "%CommonProgramFiles(x86)%\Additional Folders\myexecutable.exe"'
Execute="deferred"
Impersonate="no"/>
in your InstallExecuteSequence there needs to be:
<Custom Action="MakeSymbolicLink" Before="InstallFinalize">NOT Installed</Custom>
This makes sure that this is only executed on install of your application if you want to execute this on reinstall or other options you may need to look into how to do that further
If making sure to leave zero footprint behind after a user uninstalls the application you will need to delete the symbolic link afterwards.
I solved this by doing the following:
First I created another CustomAction
<CustomAction Id="RemoveSymbolicLink"
Directory="TARGETDIR"
ExeCommand='cmd /c DEL .\linkToItem.lnk '
Execute="deferred"
Impersonate="no"/>
Then I needed another InstallExecuteSequence to execute this. However I only needed to run this on uninstall so it needed a different conditional in to do that so this one looked like:
<Custom Action="RemoveSymbolicLink" After="InstallInitialize">Installed AND NOT REINSTALL</Custom>
I am using WIX Installer in which i have a custom action as below.
<CustomAction Id="ConfigureBiodentifyServer" FileKey="Biodentify.InstallUtil.exe" Execute="deferred" ExeCommand="/configurebiodentify /metadata="DefaultSetup.xml" /iskiosk="false"/databaseType="SQLServer" /sqlserver="[$(var.SqlServerName)]" /sqluser="" /sqlpw="" /domainName="[$(var.ComputerDomain)]" /domainPk="[$(var.DomainPk)]" " Impersonate="yes" Return="check" />
<InstallExecuteSequence><Custom Action="ConfigureBiodentifyServer" After="StartServices">NOT Installed And $(var.InstallType) = "SERVER" </Custom> </InstallExecuteSequence>
But the ExeCommand is giving error when i installed my Installer?
There are several levels of refactoring you should be considering. First, you are calling InstallUtil which means you are calling an Installer class custom action. This custom action should be refactored to WiX Deployment Tools Foundation (DTF) to take advantage of a better hosting pattern ( for example you can Get/Set Windows Installer properties instead of passing command line arguments ).
Also WiX has SQL extensions to handle SQL Scripts so you might be reinventing the wheel here.
I have following CostomAction
<Binary Id='ManualsBat' SourceFile='bin\Debug\test.bat' />
<CustomAction
Id="manuals"
BinaryKey="ManualsBat"
ExeCommand="[SourceDir]Manuals "[Agent]Manuals""
Execute="immediate"
Return="check" />
test.bat contains the following lines :
#echo off
echo Hello this a test batch file
pause
mkdir %2
copy %1 %2
What it is basically intended to do is, when the installer is run, the batch file needs to get executed. The batch file has to create a new directory "[Agent]Manuals" and it has to copy all the files from [SourceDir]Manuals to [Agent]Manuals.
When I builds .wxs it does not give any error bur when I run the .msi then it complains of the following in the log files
Error 1721. There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. Action: manuals, location: C:\Windows\Installer\MSI1F50.tmp, command: C:\dev\CD\Agent\pd\components\link\source\Link\Installer\WiX\WiX\bin\Debug\Manuals "D:\Cam\city\Agent\Manuals
Has anyone had experience with this kind of error. It will be great if someone can help me resolve this.
Most likely your custom action needs Administrator privileges. Try setting Execute attribute to deferred and Impersonate to no. Please note that these options require the action to be scheduled after InstallFinalize standard action.
Maybe problem in quotes. Change in ExeCommand quotes.
Try this:
<Binary Id='ManualsBat' SourceFile='bin\Debug\test.bat' />
<CustomAction
Id="manuals"
BinaryKey="ManualsBat"
ExeCommand='"[SourceDir]Manuals" "[Agent]Manuals"'
Execute="deferred"
Impersonate="no"
Return="check" />
<InstallExecuteSequence>
<Custom Action="manuals" Before="InstallFinalize">Not Installed</Custom>
</InstallExecuteSequence>
You generally need to call cmd /c foo.bat ( or command on Win9x ) to process .bat files.
However, I would never, ever do this in one of my installers. It violates the overall design on Windows Installer. MSI is a transactional, declarative programming language. Injecting out of process procedural code greatly increases the likelyhood of failure ( as you are experiencing ) and worse defeats the transactional benefits of MSI.
For example, if you create a folder and copy a file, that won't get undone during a rollback and it won't get removed during an uninstall. Instead, you should be using the built in Windows Installer features ( CreateFolder and CopyFile elements ) to achieve your goals.
On the occasion that custom actions are truely needed (in your example you are merely reinventing the wheel with an inferior solution) they should be designed using robust languages and maintaining a declarative (data driven) and transactional design while respecting the security model that MSI uses.
I would like to run an executable file with a quiet execution custom action during the InstallUISequence phase.
This executable has a text file as a parameter. I don't want that text file to be installed and I can't put it on the directory/file part as it is intented to use during the UI sequence.
How can I do that?
Here is a sample code to explain what I want:
<CustomAction Id="RunIsql_cmd" Property="RunIsql" Value=""[MYEXE]" -U [PARAM1] -i **myFileFromThePackage.txt** Execute="immediate"/>
<CustomAction Id="RunIsql" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="immediate" Return="check" Impersonate="no"/>
How can I define myFileFromThePackage.txt ?
I've tried to define the file like this:
<Binary Id="DummyFileForInstallOnly" SourceFile="myFile.txt" />
But I can't associate the id to the CA..
Adding it in Binary table is a good approach, but you also need to extract it during install in order to use it. This can be done through a custom action which uses the Windows Installer database API.
You will also need a custom action to delete the extracted file after it has been used.
Our product was installed via InstallShield Setup over the years. I changed the installation to MSI (WiX) this year. Now the MSI should clean up the directory, which remains the same.
One custom action in the MSI I implemented to start the uninstallation of the old product:
<CustomAction Id="UninstallIS" Property="QtExecCA" Value=""[WindowsFolder]IsUn0407.exe" -f "[ProgramFilesFolder]\company\product\Uninst.isu"" Execute="deferred" />
<CustomAction Id="QtExecCA" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no" />
After the removal of the old product there are temporary files and some subdirectories that are different from client to client and are unknown to the InstallShield Setup, so I would try to delete them via the MSI.
Keeping the UAC in mind, I think that I can't use command-line commands to do this also the 'Remove File Table' is not useful here (to much unknown files and many directories).
What is a possible way to do this?
Thank You for any help!
You can use a Deferred custom action which has Impersonate flag set to "no". This way it will run under the local system account with full privileges.
The custom action can use custom code (for example an EXE or DLL) or a command line.
Please note that deferred custom actions can be scheduled only after InstallInitialize action in InstallExecuteSequence.
As a side-note, make sure you thoroughly test it. Deleting files from the target machine is very dangerous. You never know what you may end up deleting.