3

I have console application, which is working to delete registry value. But when I am trying to do the same in service, it's not working.

The log to txt file is working fine, so I see log every 5 secs. But exception from DeleteValue method says:

Value doesn't exist

Console application (working):

class Program
    {
        static void Main(string[] args)
        {
            while (true)
            {
                KillProxy();
                Console.ReadLine();
            }
        }

        private static void KillProxy()
        {
            string keyName = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings";
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true))
            {
                try
                {
                    key.DeleteValue("AutoConfigURL");
                    key.Close();
                }
                catch { }
            }
        }
    }

Service application (not working):

public partial class Service1 : ServiceBase
    {
        private Timer t1;

        /// <summary>
        /// Init
        /// </summary>
        public Service1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Service start event
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {
            t1 = new Timer();
            t1.Interval = 5000;
            t1.Elapsed += new ElapsedEventHandler(t1_tick);
            t1.Enabled = true;
        }

        /// <summary>
        /// Service stop event
        /// </summary>
        protected override void OnStop()
        {
            t1.Enabled = false;
        }

        /// <summary>
        /// Timer tick event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void t1_tick(object sender, ElapsedEventArgs e)
        {
            KillProxy();
        }

        /// <summary>
        /// If key AutoConfigURL exists, delete it
        /// </summary>
        private void KillProxy()
        {
            string keyName = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings";
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true))
            {
                try
                {
                    WriteLog("start deleting ");
                    key.DeleteValue("AutoConfigURL");
                    key.Close();
                }
                catch (Exception ex)
                {
                    WriteLog(ex.Message.ToString());
                }
            }
        }


        private void WriteLog(string msg)
        {
            StreamWriter sw = null;

            try
            {
                sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\\logfile.txt", true);
                sw.WriteLine(DateTime.Now.ToString() + " " + msg);
                sw.Flush();
                sw.Close();
            }
            catch
            {
                //nothing
            }
        }
    }
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
Ondřej Michejda
  • 138
  • 1
  • 12

1 Answers1

2

The reason for this is that you are accessing the CurrentUser registry subtree which as its name says is specific to the user,

when you run the code in console mode you run it with your user and the content of the CurrentUser registry section retrieved is one, yours, with the keys and sub-keys you know of,

when you run the code as service the default account used to run is Local Service or System and in that context the CurrentUser registry subtree is definitely not yours as the one loaded in console mode.

you should either set the service to run using your own credentials ( you will have to type in username and password ) or keep the app running in console mode, or revisit your application logic, depends on what exactly you need to do.

Davide Piras
  • 43,984
  • 10
  • 98
  • 147
  • Or impersonate the user in the service, which seems like a smell – TheGeneral Feb 21 '18 at 09:27
  • @MichaelRandall, in WinAPI code we have to ensure the impersonated user's profile is loaded and call `RegOpenCurrentUser` to get a handle. The `HKEY_CURRENT_USER` pseudo-handle can't be used because the real handle for the "\Registry\User\\[SID String]" user profile key gets cached on first use. What does `Registry.CurrentUser` use in .NET? I would assume it's based on `HKEY_CURRENT_USER`. – Eryk Sun Feb 21 '18 at 09:52
  • @eryksun the same id say – TheGeneral Feb 21 '18 at 09:56
  • @MichaelRandall, so I assume impersonating and getting a handle for the profile key would actually be rather cumbersome in .NET, since you'd have to call the native `RegOpenCurrentUser` function and wrap the handle, right? – Eryk Sun Feb 21 '18 at 09:58
  • hrm im not sure, this should just work. though id be interested in the results https://stackoverflow.com/questions/33777618/c-sharp-access-registry-of-another-user – TheGeneral Feb 21 '18 at 10:01