Is it possible to register environment variables i

2020-02-13 08:32发布

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?

4条回答
贪生不怕死
2楼-- · 2020-02-13 09:19

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:

  1. In the Solution Explorer, right-click on your project (not solution), and select View->Registry
  2. Create the registry key(folder):
    1. For a User variable: Right-click on HKEY_CURRENT_USER, select "New Key", and name it "Environment".
    2. For a System variable: Right-Click on HKEY_LOCAL_MACHINE, select "New Key", and name it "SYSTEM". Continue doing this to create the path "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" .
  3. Right-click on the Environment key(folder), select New->String, and give it the name you want.
  4. With the string selected, find the Properties window (Alt+Enter will bring it up)
  5. In the Properties window, fill in the Value you want.

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)

查看更多
SAY GOODBYE
3楼-- · 2020-02-13 09:19

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.

查看更多
Viruses.
4楼-- · 2020-02-13 09:33

Ickydime (see answers above) custom action sample shows how to add an environment variable by expanding the PATH env variable. I'm sharing below how to create a new environment variable using Environment.SetEnvironmentVariable

    string environmentKey = "MY_VAR";
    string pathUrl = "%ProgramFiles%\\...";
    public Installer1()
    {
        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);
        Environment.SetEnvironmentVariable(environmentKey, pathUrl, EnvironmentVariableTarget.Machine);
    }

    [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);
        Environment.SetEnvironmentVariable(environmentKey, null, EnvironmentVariableTarget.Machine);
    }
查看更多
ゆ 、 Hurt°
5楼-- · 2020-02-13 09:34

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

查看更多
登录 后发表回答