Windows服务:当用户登录时获取用户名

本文关键字:用户 获取 登录 Windows 服务 | 更新日期: 2023-09-27 17:54:51

我的Windows服务应该保存当前登录/注销的用户名。下面的代码为我工作,但没有保存用户名:

protected override void OnSessionChange(SessionChangeDescription changeDescription)
    {
        try
        {
            string user = "";
            foreach (ManagementObject currentObject in _wmiComputerSystem.GetInstances())
            {
                user += currentObject.Properties["UserName"].Value.ToString().Trim();
            }
            switch (changeDescription.Reason)
            {
                case SessionChangeReason.SessionLogon:
                    WriteLog(Constants.LogType.CONTINUE, "Logon - Program continues: " + user);
                    OnContinue();
                    break;
                case SessionChangeReason.SessionLogoff:
                    WriteLog(Constants.LogType.PAUSE, "Logoff - Program is paused: " + user);
                    OnPause();
                    break;
            }
            base.OnSessionChange(changeDescription);
        }
        catch (Exception exp)
        {
            WriteLog(Constants.LogType.ERROR, "Error");
        }
    }
编辑:

foreach循环给了我一个错误:

消息:Access is denied。HRESULT异常:0x80070005(E_ACCESSDENIED))类型:System。UnauthorizedAccessException

但是在我看来,这段代码不是解决方案,因为它保存了所有登录到服务器的用户。

Windows服务:当用户登录时获取用户名

我在构建Windows Service时遇到了类似的问题。就像您一样,我有会话ID,需要获得相应的用户名。在几个不成功的解决方案之后,我遇到了这个特殊的答案,它激发了我的解决方案:

这是我的代码(它们都在一个类中;在我的例子中,继承了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;
    }
有了上面的代码在你的类中,你可以简单地通过调用 在你重写的方法中获得用户名
string username = GetUsername(changeDescription.SessionId);

终于有办法了。在windows服务方法中,提供了会话id。因此,有了这个会话id,我们可以执行powershell命令'quser'并获取当前登录/注销服务器的用户。如何在多用户环境下使用。net从windows服务中获取当前windows用户名

这就是我们要创建的函数:

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";
        } 

这是windows服务功能:

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);
                        //.....

你可以试试:

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

另一个选项,参见:从服务获取登录用户名