Windows service: Get username when user log on

前端 未结 3 561
傲寒
傲寒 2021-01-28 02:02

my windows service should save the name of the user, which logon/logoff at the moment. The following code works for me but didn\'t save the username:

protected o         


        
相关标签:
3条回答
  • 2021-01-28 02:16

    Finally I got a solution. In the windows service method, there is the session id provided. So with this session id we can execute a powershell command 'quser' and get the current user, who login/logoff on the server. Seen here: How to get current windows username from windows service in multiuser environment using .NET

    So this is the function, which we need to create:

    private string GetUsername(int sessionID)
            {
                try
                {
                    Runspace runspace = RunspaceFactory.CreateRunspace();
                    runspace.Open();
    
                    Pipeline pipeline = runspace.CreatePipeline();
                    pipeline.Commands.AddScript("Quser");
                    pipeline.Commands.Add("Out-String");
    
                    Collection<PSObject> results = pipeline.Invoke();
    
                    runspace.Close();
    
                    StringBuilder stringBuilder = new StringBuilder();
                    foreach (PSObject obj in results)
                    {
                        stringBuilder.AppendLine(obj.ToString());
                    }
    
                    foreach (string User in stringBuilder.ToString().Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Skip(1))
                    {
                        string[] UserAttributes = User.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
    
                        if (UserAttributes.Length == 6)
                        {
                            if (int.Parse(UserAttributes[1].Trim()) == sessionID)
                            {
                                return UserAttributes[0].Replace(">", string.Empty).Trim();
                            }
                        }
                        else
                        {
                            if (int.Parse(UserAttributes[2].Trim()) == sessionID)
                            {
                                return UserAttributes[0].Replace(">", string.Empty).Trim();
                            }
                        }
                    }
    
                }
                catch (Exception exp)
                {
                    // Error handling
                }
    
                return "Undefined";
            } 
    

    And this is the windows service function:

    protected override void OnSessionChange(SessionChangeDescription changeDescription)
            {
                try
                {
                    switch (changeDescription.Reason)
                    {
                        case SessionChangeReason.SessionLogon:
                            string user = GetUsername(changeDescription.SessionId);
    
                            WriteLog("Logon - Program continue" + Environment.NewLine + 
                                "User: " + user + Environment.NewLine + "Sessionid: " + changeDescription.SessionId);
    
                            //.....
    
    0 讨论(0)
  • 2021-01-28 02:18

    You could try:

    System.Security.Principal.WindowsIdentity.GetCurrent();
    

    another option, see: Getting logged-on username from a service

    0 讨论(0)
  • 2021-01-28 02:20

    I ran into a similar problem while building a Windows Service. Just like you, I had the Session ID and needed to get the corresponding username. After several unsuccessful solution hereon SO, I ran into this particular answer and it inspired my solution:

    Here's my code (all of them residing inside a class; in my case, the class inheriting ServiceBase).

        [DllImport("Wtsapi32.dll")]
        private static extern bool WTSQuerySessionInformation(IntPtr hServer, int sessionId, WtsInfoClass wtsInfoClass, out IntPtr ppBuffer, out int pBytesReturned);
        [DllImport("Wtsapi32.dll")]
        private static extern void WTSFreeMemory(IntPtr pointer);
    
        private enum WtsInfoClass
        {
            WTSUserName = 5, 
            WTSDomainName = 7,
        }
    
        private static string GetUsername(int sessionId, bool prependDomain = true)
        {
            IntPtr buffer;
            int strLen;
            string username = "SYSTEM";
            if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WtsInfoClass.WTSUserName, out buffer, out strLen) && strLen > 1)
            {
                username = Marshal.PtrToStringAnsi(buffer);
                WTSFreeMemory(buffer);
                if (prependDomain)
                {
                    if (WTSQuerySessionInformation(IntPtr.Zero, sessionId, WtsInfoClass.WTSDomainName, out buffer, out strLen) && strLen > 1)
                    {
                        username = Marshal.PtrToStringAnsi(buffer) + "\\" + username;
                        WTSFreeMemory(buffer);
                    }
                }
            }
            return username;
        }
    

    With the above code in your class, you can simply get the username in the method you're overriding by calling

    string username = GetUsername(changeDescription.SessionId);
    
    0 讨论(0)
提交回复
热议问题