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

Zer*_*One 1 c# windows service visual-studio-2010

我的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");
        }
    }
Run Code Online (Sandbox Code Playgroud)

编辑: foreach 循环给我一个错误:

消息:访问被拒绝。(HRESULT 异常:0x80070005 (E_ACCESSDENIED))类型:System.UnauthorizedAccessException

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

Som*_*iwe 5

我在构建 Windows 服务时遇到了类似的问题。就像你一样,我有会话 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;
    }
Run Code Online (Sandbox Code Playgroud)

使用类中的上述代码,您可以通过调用来简单地在要重写的方法中获取用户名

string username = GetUsername(changeDescription.SessionId);
Run Code Online (Sandbox Code Playgroud)