c# - 如何在本地机器上激活 session/user (Windows 10)

c# - How to get active session/user on local machine (Windows 10)

Windows 10 开始自动登录多个(本地)用户和程序。 所以我可能有一些 'ghost' 用户登录一次 只有 1 个用户是 'active' 此时

我需要在我的应用程序中识别用户是否真的处于活动状态(在会话中工作),而不仅仅是被 Windows 在后台记录。

在 .NET 中有什么方法可以做到这一点吗? (来自非管理员帐户) 用谷歌搜索了很多,但找到了可靠的东西

PS。我发现 cmd 行命令 (qwinsta) 似乎在做我需要的事情-但我不知道如何从 C# 代码 运行 它并读取输出 (我收到的 qwinsta 未找到)

请指教...

* 编辑 *

澄清:我不需要找到活动用户名(这很容易) 我希望获取有关本地计算机上所有会话的信息并检查当前处于活动状态的会话(请参阅下面的 qwinsta.exe 命令行输出)。

假设所有本地用户都在启动我的应用程序 - 应用程序需要做一些事情,但只有当用户锁定会话时才会在计算机前做一些事情(不会自动登录 Windows-10机制我个人很讨厌...)

qwinsta.exe 会帮我完成工作,但如果我从 .NET 开始这个过程,它总是说 qwinsta.exe 找不到。即使我给出完整路径: c:\Windows\system32\qwinsta.exe

 SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
 services                                    0  Disc
>console           carl                    1  Active
 rdp-tcp                                 65536  Listen

用这个。几年前我做过一次,效果很好。

string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

这里是原文post

在 c# 中我使用这个

private string MyUser = System.Environment.UserName;

这是我的最终可用的代码示例(感谢 @Eryk Sun)- 也许有人会发现它很有用。 PS。它被正确地指出了——我可能应该提到我的应用程序是 x86 但 W10 是 x64 ...

public static bool IsUserActive(string userName) {
    Process p = new Process();
    p.StartInfo.UseShellExecute         = false;
    p.StartInfo.RedirectStandardOutput  = true;
    p.StartInfo.FileName                =  "c:\Windows\SysNative\qwinsta.exe";
    p.StartInfo.Arguments               = userName;
    p.Start();
    string output = p.StandardOutput.ReadToEnd();
    p.WaitForExit();

    return output.Contains("  Active");
}

有一个更好的解决方案,它使用 winapi,这可能是 qwinsta 所做的。
我不能将实施归功于此 - 这是 github link:
https://github.com/murrayju/CreateProcessAsUser

它所做的是,使用 winapi,枚举机器中的所有会话。对于每个会话,它都会调用另一个 winapi 来获取有关此会话的详细信息,如果此会话处于活动状态,这就是您获取指示的方式。

看看我 link 编辑的那个项目,这是一个比解析不同应用程序的输出更好的解决方案

这是我的有效代码示例。我正在编写代码以使用 x86 进程而不是 x64,因为 W10 是 x64。

IntPtr ptr = new IntPtr();
Wow64DisableWow64FsRedirection(ref ptr);
var p = Process.Start(
         new ProcessStartInfo("qwinsta", $"/server:")
         {
             CreateNoWindow = true,
             UseShellExecute = false,
             RedirectStandardError = true,
             RedirectStandardOutput = true,
             WorkingDirectory = Environment.CurrentDirectory
         }
     );

p.WaitForExit();
string output = p.StandardOutput.ReadToEnd().TrimEnd();
string errorInfoIfAny = p.StandardError.ReadToEnd().TrimEnd();

Wow64RevertWow64FsRedirection(ptr);

添加这两种导入方式。

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);

对于系统级应用程序

    [DllImport("Wtsapi32.dll")]
    public static extern bool WTSQuerySessionInformationW(
          IntPtr hServer,
          int SessionId,
          int WTSInfoClass,
          out IntPtr ppBuffer,
          out IntPtr pBytesReturned);

public static void AddArray<xArray>(ref xArray[] array, dynamic deger)
    {
        try
        {
            int diziboyu;
            if (array == null)
            {
                diziboyu = 0;
            }
            else
                diziboyu = array.Length;
            diziboyu++;
            System.Array.Resize(ref array, diziboyu);
            array[diziboyu - 1] = deger;
        }
        catch (Exception)
        {

        }
    }

public static string[] Online_userNames = null;

Process[] pname = Process.GetProcessesByName("explorer");
foreach (Process proc in pname)
            {
                IntPtr AnswerBytes;
                IntPtr AnswerCount;
                WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE,
                                                    proc.SessionId,
                                                    WTS_UserName,
                                                    out AnswerBytes,
                                                    out AnswerCount);

                AddArray(ref Online_userNames, Marshal.PtrToStringUni(AnswerBytes));
            }

            pname = null;