I wanted to run custom action code during the Commit phase of the Setup Project.
I created an installer class and override the Commit method. I also added that installer as a custom action to the Commit phase (View->Custom Actions).
During the installation process I got an exception saying “Could not find C:\Program Files\MyApp\MyAction.Installstate”
The problem is that the MSI infrastructure is looking for the installation state file which is usually created during the Install phase. If the custom action does not participate in the Install phase, no file is created.
The solution is to add the custom action to both the Install and the Commit phases, although it does nothing during the install phase.
If you want to add a system environment variable with the installer project, you can do by adding the key to direct location in the registry.
You should create a registry value under the key HKEY_LOCAL_Machine\System\CurrentControlSet\Control\Session Manager\Environment .
The value's name is the variables name.
Pay attention that after doing this the Windows Explorer does not read the new system environment value until you logoff. This means that your application will not get that system variable if it is executed just after the installation process.
To propagate the environment variables changes to the system you can add a Custom Action to your installer project and call the attached code. Pay attention that you need to call it during the Commit process – to make sure the installer already added the key to the registry.
public const int HWND_BROADCAST = 0xffff;
public const int WM_SETTINGCHANGE = 0x001A;
public const int SMTO_NORMAL = 0x0000;
public const int SMTO_BLOCK = 0x0001;
public const int SMTO_ABORTIFHUNG = 0x0002;
public const int SMTO_NOTIMEOUTIFNOTHUNG = 0x0008;
[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
[return:MarshalAs(UnmanagedType.Bool)]
public static extern bool
SendMessageTimeout(
IntPtr hWnd,
int Msg,
int wParam,
string lParam,
int fuFlags,
int uTimeout,
out int lpdwResult
);
private void BroadCast()
{
try
{
const int SomeTimeoutValue = 1000;
int result;
SendMessageTimeout( (System.IntPtr)HWND_BROADCAST,
WM_SETTINGCHANGE,0,"Environment",SMTO_BLOCK | SMTO_ABORTIFHUNG |
SMTO_NOTIMEOUTIFNOTHUNG, SomeTimeoutValue, out result);
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine ("Could not broadcast");
Throw;
}
}