views:

387

answers:

2

I have a class that modifies the ProxyEnable and ProxyServer registry keys of Internet Settings.

If I use this class in a Console App and run it the value are changed and I can see the changes using regedit.

Now the part that doesn't work is I am trying to use this class in an Installer class so that the registry keys are changed during installation of my application.

Here is the code for the class:

public class ProxySettings {
    [DllImport("wininet.dll")]
    public static extern bool InternetSetOption(IntPtr hInternet, int dwOption,
        IntPtr lpBuffer, int dwBufferLength);
    public const int INTERNET_OPTION_SETTINGS_CHANGED = 39;
    public const int INTERNET_OPTION_REFRESH = 37;
    static bool settingsReturn, refreshReturn;

    public void EnableProxy(string proxy) {
        RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
        registry.SetValue("ProxyEnable", 1);
        registry.SetValue("ProxyServer", proxy);

        settingsReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED,
            IntPtr.Zero, 0);
        refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
    }

    public void DisableProxy() {
        RegistryKey registry = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true);
        registry.SetValue("ProxyEnable", 0);
        registry.DeleteValue("ProxyServer", false);

        settingsReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED,
            IntPtr.Zero, 0);
        refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
    }
}

Here is my Installer class:

[RunInstaller(true)]
public class WindowsServiceInstaller : Installer {
    public WindowsServiceInstaller() {
        ServiceProcessInstaller serviceProcessInstaller =
                           new ServiceProcessInstaller();
        ServiceInstaller serviceInstaller = new ServiceInstaller();

        //# Service Account Information
        serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
        serviceProcessInstaller.Username = null;
        serviceProcessInstaller.Password = null;

        //# Service Information
        serviceInstaller.DisplayName = "Client Service";
        serviceInstaller.StartType = ServiceStartMode.Automatic;

        //# This must be identical to the WindowsService.ServiceBase name
        //# set in the constructor of WindowsService.cs
        serviceInstaller.ServiceName = "Client Service";

        this.Installers.Add(serviceProcessInstaller);
        this.Installers.Add(serviceInstaller);
    }

    public override void Commit(System.Collections.IDictionary savedState) {
        base.Commit(savedState);

        ServiceController controller = new ServiceController("Client Service");
        if(controller.Status != ServiceControllerStatus.Running) {
            controller.Start();
        }

        ProxySettings proxy = new ProxySettings();
        proxy.EnableProxy("127.0.0.1:8889");
    }

    public override void Uninstall(System.Collections.IDictionary savedState) {
        base.Uninstall(savedState);

        ProxySettings proxy = new ProxySettings();
        proxy.DisableProxy();
    }
}

In the override of Commit I am starting the service which works fine but for some reason I don't see the changes to the registry.

Just too make sure the class was initializing and firing I added

System.Diagnostics.Process.Start("http://www.microsoft.com");

to both the EnableProxy and DisableProxy methods. During the install the website opened and also during uninstall but the registry remained unchanged.

What am I doing wrong? Why will it work running as a Console App but not in an Installer?

+2  A: 

I can't say for sure why it works in the Console app and not the installer, but I notice that you're neither disposing nor directly flushing the registry key.

Try replacing the code in your EnableProxy with this (and similarly with DisableProxy) and see what happens:

using (RegistryKey registry = Registry.CurrentUser.OpenSubKey(
    "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", true))
{
    registry.SetValue("ProxyEnable", 1);
    registry.SetValue("ProxyServer", proxy);
}

(This is one of many reasons why you should always dispose an IDisposable)

Aaronaught
Thanks for the suggestion. It, however, didn't make a difference.
modernzombie
A: 

Okay, I have figured out what was going on.

I had the installer set to install for Everyone. I tried installing and selecting Just Me and it worked.

I guess that makes sense since I was setting a registry key for the current user but was installing for everyone. Does this sound right?

Anyway, I now have some more testing to do to see if the software will function correctly if installed for Just Me. The application is a Windows Service.

modernzombie
This makes sense - when you install "For Everyone" it will be installing under the All Users profile and not the current user profile, so `Registry.CurrentUser` isn't going where you want it to.
Aaronaught