{"id":103,"date":"2011-04-23T16:58:45","date_gmt":"2011-04-23T08:58:45","guid":{"rendered":"https:\/\/www.techcoil.com\/blog\/?p=103"},"modified":"2018-09-02T22:44:25","modified_gmt":"2018-09-02T14:44:25","slug":"how-to-retrieve-the-username-of-the-user-who-logged-onto-windows-from-windows-service","status":"publish","type":"post","link":"https:\/\/www.techcoil.com\/blog\/how-to-retrieve-the-username-of-the-user-who-logged-onto-windows-from-windows-service\/","title":{"rendered":"How to retrieve the username of the user who logged onto Windows from windows service"},"content":{"rendered":"<p>Recently, I have been tasked to write a .NET application that will prepare the operating system environment for a user who had logged on a Windows 7 machine. As a first step, the application should grab some settings from the network by providing the username of the user to a server application. The application will then prepare the operating system environment based on the settings received.<\/p>\n<p>Writing the application as a windows service is a favorable option. This is because a windows service application can be configured to run automatically and will run before any user logs into the operating system. Furthermore, a windows service can run as <code><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms684190(v=vs.85).aspx\" target=\"_blank\">Local System<\/a><\/code>, which mean that it can execute most operating system facilities without facing permission issues.<\/p>\n<h3>Detecting user login event<\/h3>\n<p>Detecting user login event from a windows service is easy. By overriding the <code>OnSessionChange<\/code> method from the <code><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.serviceprocess.servicebase.aspx\" target=\"_blank\">ServiceBase<\/a><\/code> class, we can detect when a user log onto windows.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.ComponentModel;\r\nusing System.Data;\r\nusing System.Diagnostics;\r\nusing System.ServiceProcess;\r\nusing System.Text;\r\n\r\nnamespace MyWindowsService\r\n{\r\n    public partial class MyWindowsService : ServiceBase\r\n    {\r\n        public MyWindowsService()\r\n        {\r\n            \/\/ Generated by Visual Studios\r\n            InitializeComponent();\r\n\r\n            \/\/ This is needed for this window service to detect session changes\r\n           base.CanHandleSessionChangeEvent = true;\r\n        }\r\n\r\n        protected override void OnStart(string&#x5B;] args)\r\n        {\r\n            \/\/ Code to execute when windows service starts\r\n        }\r\n\r\n        protected override void OnStop()\r\n        {\r\n            \/\/ Code to execute when windows service stops\r\n        }\r\n\r\n        protected override void OnSessionChange(SessionChangeDescription\r\n            changeDescription)\r\n        {\r\n            \/\/ Use a switch block to segment the actions to perform for\r\n            \/\/ different session changes\r\n            switch (changeDescription.Reason)\r\n            {\r\n                case SessionChangeReason.SessionLogon:\r\n                    \/\/ Retrieve the username of the user who had just logged on\r\n                    string username = Machine.getInstance().getUsername();\r\n                break;\r\n\r\n                case SessionChangeReason.SessionLogoff:\r\n                    \/\/ Could perform any restoration of the operating system\r\n                    \/\/ environment here.\r\n                break;\r\n\r\n                case SessionChangeReason.ConsoleLogon:\r\n                    \/\/ Triggered whenever a user logs in after\r\n                    \/\/ switching user accounts\r\n                    \/\/ Triggered once by the windows service\r\n                    \/\/ account whenever a user logs in\r\n                break;\r\n            }\r\n\r\n            \/\/ Inform the base class of the change as well\r\n            base.OnSessionChange(changeDescription);\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>As long as the windows service is started automatically, the <code>OnSessionChange<\/code> method block will be called whenever there are changes in the user session. This includes the case when a user logs on to windows, in which <code>Machine.getInstance().getUsername()<\/code> will be called. Note that besides log on and log off events, there are several other events defined in the <code><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.serviceprocess.sessionchangereason.aspx\" target=\"_blank\">SessionChangeReason<\/a><\/code> enumeration that you can handle from your windows service.<\/p>\n<h3>Attempts made to retrieve the username<\/h3>\n<p>It makes sense for me to implement the <code>Machine<\/code> class as a <a href=\"http:\/\/www.techcoil.com\/blog\/2010\/11\/21\/implementing-the-singleton-pattern-in-visual-basic-dot-net\/\" target=\"_blank\">Singleton<\/a>. <code>Machine.getInstance()<\/code> will return me the <code>Machine<\/code> Singleton. The <code>getUsername<\/code> instance method will return the username of the user who is currently logged on to windows.<\/p>\n<h4>Environment.UserName and WindowsIdentity.GetCurrent().Name does not work<\/h4>\n<p>My first intuition to implementing the <code>getUsername()<\/code> method is to utilitise facilities from the .NET framework, namely the <code>UserName<\/code> property from the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.environment.aspx\" target=\"_blank\"><code>Environment<\/code><\/a> class or the  <code>Name<\/code> property of the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.security.principal.windowsidentity.aspx\"><code>WindowsIdentity<\/code><\/a> class. &nbsp;However, since the windows service is running as <code><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms684190(v=vs.85).aspx\" target=\"_blank\">Local System<\/a><\/code> , which belongs to a separate environment from the logged on user, the string \"SYSTEM\" was returned instead.<\/p>\n<h4>Looking for the right username with WMI<\/h4>\n<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa384642(v=vs.85).aspx\" target=\"_blank\">Windows Management Instrumentation<\/a> (WMI) was my next hope. A couple of google searches brought me two methods for retrieving the right username.<\/p>\n<h4>Using the Win32_Process WMI class<\/h4>\n<p>The first method utilises the Win32_Process WMI class to inspect the owners of the explorer.exe process. Although I could get the list of usernames who are logged onto the machine, I felt that too much work is required to get the user who is currently active.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nManagementScope ms = new ManagementScope(&quot;\\\\\\\\.\\\\root\\\\cimv2&quot;);\r\nObjectQuery query = new ObjectQuery\r\n    (&quot;select * from Win32_Process where name = 'explorer.exe'&quot;);\r\nManagementObjectSearcher searcher = new ManagementObjectSearcher(ms, query);\r\nManagementObjectCollection returnCollection = searcher.Get();\r\n\r\nforeach (ManagementObject mo in returnCollection)\r\n{\r\n    string&#x5B;] argList = new string&#x5B;] { string.Empty };\r\n    int returnVal = Convert.ToInt32( mo.InvokeMethod(&quot;GetOwner&quot;, argList));\r\n    if (returnVal == 0)\r\n    {\r\n        Console.WriteLine(&quot;User name:&quot;);\r\n        Console.WriteLine(argList&#x5B;0].ToString());\r\n    }\r\n}\r\n<\/pre>\n<h4>Using the Win32_ComputerSystem WMI class<\/h4>\n<p>The second method utilises the Win32_ComputerSystem WMI class:<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nManagementScope ms = new ManagementScope(&quot;\\\\\\\\.\\\\root\\\\cimv2&quot;);\r\nObjectQuery query = new ObjectQuery(&quot;SELECT * FROM Win32_ComputerSystem&quot;);\r\nManagementObjectSearcher searcher = new ManagementObjectSearcher(ms, query);\r\nforeach(ManagementObject mo in searcher.Get())\r\n{\r\n    Console.WriteLine(mo&#x5B;&quot;UserName&quot;].ToString());\r\n}\r\n<\/pre>\n<p>This method is much better than the previous one in that there is only at most one instance of the <code>Win32_ComputerSystem<\/code> WMI class. Whenever a user logged onto windows, the <code>Username<\/code> attribute will contain the username of the user. In the case when there are no users in the windows system, there will be no instances of the <code>Win32_ComputerSystem<\/code> class. These properties make <code>Win32_ComputerSystem<\/code> my ideal choice in implementing the <code>getUsername<\/code> method for my <code>Machine<\/code> class.<\/p>\n<h3>Implementing the Machine class<\/h3>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class Machine\r\n{\r\n    private static Object _classLocker = new Object();\r\n    private static Machine _machine; \r\n\r\n    private Machine()\r\n    {\r\n    } \/\/ end private Machine()\r\n\r\n    public static Machine getInstance()\r\n    {\r\n        if (_machine == null)\r\n        {\r\n            lock (_classLocker)\r\n            {\r\n                if (_machine == null)\r\n                {\r\n                    _machine = new Machine();\r\n                }\r\n            }\r\n        }\r\n        return _machine;\r\n    } \/\/ end public static Machine getInstance()\r\n\r\n    public String getUsername()\r\n    {\r\n        string username = null;\r\n        try\r\n        {\r\n            \/\/ Define WMI scope to look for the Win32_ComputerSystem object\r\n            ManagementScope ms = new ManagementScope(&quot;\\\\\\\\.\\\\root\\\\cimv2&quot;);\r\n            ms.Connect();\r\n\r\n            ObjectQuery query = new ObjectQuery\r\n                    (&quot;SELECT * FROM Win32_ComputerSystem&quot;);\r\n            ManagementObjectSearcher searcher =\r\n                    new ManagementObjectSearcher(ms, query);\r\n\r\n            \/\/ This loop will only run at most once.\r\n            foreach (ManagementObject mo in searcher.Get())\r\n            {\r\n                \/\/ Extract the username\r\n                username = mo&#x5B;&quot;UserName&quot;].ToString();\r\n            }\r\n            \/\/ Remove the domain part from the username\r\n            string&#x5B;] usernameParts = username.Split('\\\\');\r\n            \/\/ The username is contained in the last string portion.\r\n            username = usernameParts&#x5B;usernameParts.Length - 1];\r\n        }\r\n        catch (Exception)\r\n        {\r\n            \/\/ The system currently has no users who are logged on\r\n            \/\/ Set the username to &quot;SYSTEM&quot; to denote that\r\n            username = &quot;SYSTEM&quot;;\r\n        }\r\n        return username;\r\n    } \/\/ end String getUsername()\r\n} \/\/ end class Machine\r\n<\/pre>\n<h3>Some posts that may interest you<\/h3>\n<ul>\n<li><a href=\"http:\/\/www.techcoil.com\/blog\/quick-references\/how-to-execute-codes-periodically-in-c\/\" title=\"How to execute codes periodically in C#\" target=\"_blank\">How to execute codes periodically in C#<\/a><\/li>\n<li><a href=\"http:\/\/www.techcoil.com\/blog\/quick-references\/how-to-interact-with-applications-via-command-line-in-c\/\" title=\"How to interact with applications via command line in C#\" target=\"_blank\">How to interact with applications via command line in C#<\/a><\/li>\n<li><a href=\"http:\/\/www.techcoil.com\/blog\/quick-references\/how-to-monitor-a-folder-for-new-files-from-your-c-application\/\" title=\"How to monitor a folder for new files from your C# application\" target=\"_blank\">How to monitor a folder for new files from your C# application<\/a><\/li>\n<li><a href=\"http:\/\/www.techcoil.com\/blog\/quick-references\/how-to-save-and-load-objects-to-and-from-file-in-c\/\" title=\"How to save and load objects to and from file in C#\" target=\"_blank\">How to save and load objects to and from file in C#<\/a><\/li>\n<li><a href=\"http:\/\/www.techcoil.com\/blog\/quick-references\/how-to-build-a-web-based-user-interaction-layer-in-c\/\" title=\"How to build a web based user interaction layer in C#\" target=\"_blank\">How to build a web based user interaction layer in C#<\/a><\/li>\n<\/ul>\n\n      <ul id=\"social-sharing-buttons-list\">\n        <li class=\"facebook\">\n          <a href=\"https:\/\/www.facebook.com\/sharer\/sharer.php?u=https%3A%2F%2Fwp.me%2Fp245TQ-1F\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n            <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Facebook.png\" alt=\"Facebook icon\"> Share\n          <\/a>\n        <\/li>\n        <li class=\"twitter\">\n          <a href=\"https:\/\/twitter.com\/intent\/tweet?text=&url=https%3A%2F%2Fwp.me%2Fp245TQ-1F&via=Techcoil_com\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Twitter.png\" alt=\"Twitter icon\"> Tweet\n          <\/a>\n        <\/li>\n        <li class=\"linkedin\">\n          <a href=\"https:\/\/www.linkedin.com\/shareArticle?mini=1&title=&url=https%3A%2F%2Fwp.me%2Fp245TQ-1F&source=https:\/\/www.techcoil.com\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/linkedin.png\" alt=\"Linkedin icon\"> Share\n          <\/a>\n        <\/li>\n        <li class=\"pinterest\">\n          <a href=\"https:\/\/pinterest.com\/pin\/create\/button\/?url=https%3A%2F%2Fwww.techcoil.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F103&description=\" class=\"pin-it-button\" target=\"_blank\" role=\"button\" rel=\"nofollow\" count-layout=\"horizontal\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Pinterest.png\" alt=\"Pinterest icon\"> Save\n          <\/a>\n        <\/li>\n      <\/ul>\n    ","protected":false},"excerpt":{"rendered":"<p>Recently, I have been tasked to write a .NET application that will prepare the operating system environment for a user who had logged on a Windows 7 machine. As a first step, the application should grab some settings from the network by providing the username of the user to a server application. The application will then prepare the operating system environment based on the settings received.<\/p>\n","protected":false},"author":1,"featured_media":1188,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"footnotes":""},"categories":[375],"tags":[20,21,22],"jetpack_featured_media_url":"https:\/\/www.techcoil.com\/blog\/wp-content\/uploads\/Windows-Logo-in-2011.gif","jetpack_shortlink":"https:\/\/wp.me\/p245TQ-1F","jetpack-related-posts":[],"jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts\/103"}],"collection":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/comments?post=103"}],"version-history":[{"count":0,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts\/103\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/media\/1188"}],"wp:attachment":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/media?parent=103"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/categories?post=103"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/tags?post=103"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}