Wix: Schedule a custom action to run after next reboot - wix

Is it possible to schedule a custom action after a reboot? Here's my predicament.
I have a product to uninstall and reinstall but some of the files are in use by another application at the time of reinstall. This causes problems for the uninstall because the files are in use so I use a custom action which runs a batch file to rename the files in use. This is a bit of a hack but makes the uninstall and reinstall not complain about the files being in use and replaces the files I want.
The reason for doing this is that I'm not allowed to force a reboot on the machine during the installation process but I need to make sure that the files get replaced. So far so good.
This has the side effect of a bunch of files hanging around that I've renamed with a prefix toDelete_fileX.dll along with the new fileX.dll in the folder.
I have another custom action to delete these files which works fine but I can't run it at the end of the installation because the other application still has a handle to these renamed "toDelete_" prefixed files.
At some point in the future the system will be rebooted and this is where I would like the custom action to run to delete the "toDelete_" prefixed files.
Thanks. Neil

Take a look at this property MSIRESTARTMANAGERCONTROL, you can use this to prevent the files in use dialog, combining this with /qn for msiexec will allow you to do it silently.
When it comes to installers, if you start running batch files during the install transaction you are really on your own as Windows Installer cannot track this. Unless there's a really good reason to roll your own CA I would steer clear.
I think in your case Windows Installer will be able to take care of the renames, when you do eventually reboot. If I've understood correctly you don't mind the reboot, its just you would like to schedule this at a later date/time.

You can schedule actions after a reboot by using RunOnce registry key:
http://msdn.microsoft.com/en-us/library/aa376977(VS.85).aspx?ppud=4
http://support.microsoft.com/kb/137367
However, I think your going the wrong way with this. If you can offer more details about what you need to do (the design or concept), perhaps I can suggest a better alternative.

Related

How to change the default directory of msi log file?

Can I change the default directory (%Temp%) of msi log file?
I want to move the log directory to ProgramData folder.
Thanks
The problem here is, that the related property MsiLogFileLocation is read-only, i.e. you have no chance to change the location of the logfile within a Windows Installer package.
There are some alternatives though:
You can define the location of the logfile if you run the Windows Installer with the /L-parameter, e.g. msiexec.exe /i MyPackage.msi /l*v "C:\path\to\log\logfile.log"
To ensure that e.g. a customer will invoke this with the correct parameters you would have to create a bootstrapper around your MSI-file, using e.g. burn
Still another, more simple solution (that I used myself) would be: let the Windows Installer log the whole installation process to wherever it needs to. As you always have access to the complete path of the created logfile using the MsiLogFileLocation-property, simply copy the logfile as last step in your installation process to wherever you want to. The only drawback here: sometimes the last lines are missing as it is copied before the installation finished completely.
So if the very last lines are not always important (because you parse the logfile further etc.), the last solution would probably be the most simple one.
I scheduled it after InstallFinalize (and used the condition NOT (REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODE), btw, else it overwrote or copied too much or... (can't remember)).

Cannot overwrite files in ProgramData\myApp installed by MSI

I am about to create a MSI package.
During the installation (launched e.g. via double-click on the MSI) some files contained in the MSI are deposited deeper under c:\ProgramData (resp. the CommonAppDataFolder), e.g. c:\ProgramData\myCompany\myApplication.
Later when the installed application is run by the user the application may need to modify these file.
The problem is that neither the running application nor the user e.g. via Windows Explorer has the right to modify any files under c:\ProgramData\myCompany\myApplication created during installation.
The files do not have a readonly attribute set.
The strange thing for me now is: If I install the MSI via msiexec /q /i then I have write permissions on these files.
My MSI is created with WiX, my os is Win 7, the user is member of the administrator group.
Can anyone tell me why that is so, and how I can gain write permissions to these files w/o having to use /q /i?
Thanks
Jan
EDIT 2014-03-24: Damned. I missed to specify the InstallPrivileges attribute on my element, I just didn't know about it.
Setting it to "limited" does not show up a UAC prompt when installing to ProgramData! And now the user / my application is allowed to overwrite files in the destination folder :)
I don't know why that behavior would be different regarding access to that folder unless you have a custom action that does something that is only in the UI sequence. That's the only functional difference I can think of - the UI sequence is suppressed in a silent install.
However the common app data folder is not normally writeable to limited users. I'm not sure how much you know about UAC, but it doesn't matter if the user running the program is an admin or not because by default admins run with limited privileges. If the app needs admin privilege to run then it needs building with an elevation manifest so it asks for elevation to admin privilege. Either that or run it as administrator from a shortcut.
Windows access control is extremely complicated to deal with. In every version of Windows there is something new and changed to deal with, and it looks like the default write access in ProgramData now includes some sort of special ACL / DACL. If this is indeed the problem you can apply new permissions there and open up for regular users to write. Please note that I am not quite aware of exactly what newer versions of Windows apply as default. The tool I generally use to set permissioning is subinacl.exe. A real handful of a tool with a command line that can scare the most experienced system administrators. Some command line samples are here. You can also use the LockPermissions table in MSI, but somehow there are some issues with how these permissions are applied to the file system object. subinacl.exe is more complex, and more capable.
More on file and folder permissioning:
http://technet.microsoft.com/en-us/library/bb727008.aspx
http://support.microsoft.com/kb/308419
With regards to where you should put different types of files on the system, please check this thread.

Wix installer could not remove installation folder

I have a Wix installer which is designed to install (uninstall) a Windows service and another .exe file. When I uninstall the software using this installer, and enabling extra log, I see some error messages about unable to remove my installation folder, although it is indeed empty. The first message that appears on the log is like this:
DEBUG: Error 2911: Could not remove the folder MY_INSTALLATION_FOLDER.
The following errors are all about the same problem. My first guess is of course that there are some resources that were being used during the uninstallation. However, like I mentioned, all components in this folder were indeed removed and this is an empty folder by now. Also, this error is the first error in the log, meaning there was no error prior to removing this folder. For example, from the log I can see a series of FileRemove actions were taken right prior to the folder removal and they all succeeded. So it's gotta be that this folder itself was being used. But I really can't figure out why and what is holding this folder. By the way the software was indeed uninstalled since the final product removal returns 0 and every thing related to our software was removed (Windows service list, shortcuts, registries...) excepted this empty folder. It is not crucial but we definitely don't want to hear from our customer asking about this kind of error anyway(they are using auto-installation and the log is by default enabled and checked)
Please help. Thanks!
Possible causes:
Other process is locking that folder. Use Unlocker to
verify if that's the case.
Some folders have restricted permissions
by Windows (e.g. C:\Windows\system32). Generally, you should avoid creating files under Windows own folders (unless it's required, I.e.: your'e installing a device driver).
Did you properly set folder permissions?

WIX: Saving off user data files during major upgrade

My application runs as a Windows service. During normal execution, some data files are generated in a "data" directory that I create with my WIX install. During an upgrade, I would like to move/migrate those files to the same data dir in the upgraded installation. However, I am running into issues. I am using the "MajorUpgrade" tag as follows:
I tried scheduling later in the process(afterInstallFinalize), but that runs into issues with the service having locks on files during the upgrade. I have combed Stack Overflow and google, and it seems that no one else is describing my scenario. Others have default *.ini files, that the user can potentially edit. However, in my case, it should always be safe to migrate the files, as there are no defaults. They are simply data files that need to be migrated.
I thought I could possibly do this via a custom action, but was not sure how to do it.
Any suggestions would be very much appreciated.
Edit: Apparently using "afterInstallFinalize" works fine for me, i.e. data files are migrated, as long as the user does not change the path during upgrade. If I change the path during upgrade, I get warnings about files being locked, and asking to stop the app using the files. However, it ends up not migrating the files in that case.
Ultimately, I solved my own issue by simply overriding the default dialog behavior, and changing the flow such that on upgrade, I skip over the "InstallDirDlg".

Using WiX, how to install single file to (potentially) multiple sub-directories, based on what is available at install time?

I'm using WiX, and would like to know the .wxs necessary to take a file and install it to every available sub-directory of a particular location. This could mean 0 or more final installation locations, determined at install time based on the currently existing directory structure. For example, if I started the install with:
\target
\subdir-1
\subdir-2
Then at the end of the installation my file would be in \subdir-1 and \subdir-2. If on the other hand these directories did not exist on the system when the install was started, my file would not be installed at all and no sub directories would be created.
Afaik this is not possible with WiX (because it is basically against the nature of MSI to install a component into several locations).
You could either
create a different component for each subfolder, or
use a custom action to copy the component to all subfolders.
In the latter case you should also provide a corresponding CA for uninstallation which removes all the files from the subfolders again.
EDIT: Seems my above answer is not totally correct. MSI supports duplicating files using the DuplicateFile tables and WiX 3.0 also provides a mechanism called "smart cabbing". Both are mentioned in a blog post by Aaron Stebner.
Not without a custom action, you need to write a custom action that will do that.
The latest and greatest in custom actions is the DTF (and here) framework that comes with Wix3.
If you are targeting Vista (or Win2k8, not sure about Win2k3), you can use mklink.