I am creating a Visual Studio 2008 Setup Wizard for my program
http://support.microsoft.com/kb/307353
I see that it is possible to add registry entries, etc..
Is there a possibility to register windows environment variable without writing a custom action?
And if I must write a custom action, what is the least painful way to do so?
With REG_EXPAND_SZ string values, you can use environment variables for paths that are stored in the registry. These entries require special formatting in order to be recognized by the operating system as environment variables. The format for a REG_EXPAND_SZ value as it appears in the registry is %TEMP%.
The Setup Wizard will help automate the creation of one of the project types shown in the dialog. The Setup Project option creates an installer for a Windows-based application.
Warning:
Please do not use this approach
. It is dangerous. Use built-in MSI features for environment variable update.Example: Writing straight to
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
-Path
will wipe out whatever is already there. Very serious.Solution: MSI features the Environment table to facilitate merging and updating of environment variables in a reliable fashion. Note that this table is also known to be complex enough to trigger unexpected results. Please test well. Uninstall scenarios especially.
Using Visual Studio 2008, you can easily do it by setting the appropriate variable in the Windows registry:
If you want the Value to reference the installation directory, you can do it like this using property variables: [TARGETDIR]SomeFile.ext (see http://msdn.microsoft.com/en-us/library/aa370905%28v=vs.85%29.aspx for more property variables)
Windows Installer does support environment variables through Environment table, but Visual Studio setup projects do not allow you to use it.
A solution is to use a different setup authoring tool which supports environment variables: http://en.wikipedia.org/wiki/List_of_installation_software
Another solution is to manually add it in Environment table by editing the MSI with Orca.
There's also the custom action approach you mentioned.
The top answer explains how to do it without a custom action but those looking for a custom action can use the following code as a template:
[RunInstaller(true)]
public partial class GRInstallCustomAction : System.Configuration.Install.Installer
{
string environmentKey = @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment";
string pathUrl = "C:\\Program Files (86)\\TargetFolder";
public GRInstallCustomAction()
{
InitializeComponent();
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Commit(IDictionary savedState)
{
base.Commit(savedState);
string environmentVar = Environment.GetEnvironmentVariable("PATH");
//get non-expanded PATH environment variable
string oldPath = (string)Registry.LocalMachine.CreateSubKey(environmentKey).GetValue("Path", "", RegistryValueOptions.DoNotExpandEnvironmentNames);
var index = oldPath.IndexOf(pathUrl);
if (index < 0)
{
//set the path as an an expandable string
Registry.LocalMachine.CreateSubKey(environmentKey).SetValue("Path", oldPath + ";" + pathUrl, RegistryValueKind.ExpandString);
}
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Rollback(IDictionary savedState)
{
base.Rollback(savedState);
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
//get non-expanded PATH environment variable
string oldPath = (string)Registry.LocalMachine.CreateSubKey(environmentKey).GetValue("Path", "", RegistryValueOptions.DoNotExpandEnvironmentNames);
string removeString = pathUrl + ";";
var index = oldPath.IndexOf(removeString);
if (index < 0)
{
removeString = pathUrl;
index = oldPath.IndexOf(removeString);
}
if (index > -1)
{
oldPath = oldPath.Remove(index, pathUrl.Length);
//set the path as an an expandable string
Registry.LocalMachine.CreateSubKey(environmentKey).SetValue("Path", oldPath, RegistryValueKind.ExpandString);
}
}
}
This walk-through shows you how to create and apply the custom action: https://msdn.microsoft.com/en-us/library/d9k65z2d(v=vs.100).aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With