Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何知道Windows会话是否为交互式会话?_C#_Windows_Windows Services - Fatal编程技术网

C# 如何知道Windows会话是否为交互式会话?

C# 如何知道Windows会话是否为交互式会话?,c#,windows,windows-services,C#,Windows,Windows Services,我正在创建一个服务,它将在用户交互会话上运行进程。我发现了如何从服务中的会话0启动进程,我发现了如何捕获用户登录的时间 但是我需要知道Windows会话是交互式会话还是交互式Windows会话列表。使用Environment.UserInteractive。它返回布尔值。在当前版本的Windows中,会话0是唯一的非交互式会话。所有其他会话都是交互式的,尽管它们可能在任何给定时刻连接到交互式用户,也可能不连接到交互式用户 您可以使用来确定存在哪些会话以及它们处于什么状态。首先设置互操作声明。这是

我正在创建一个服务,它将在用户交互会话上运行进程。我发现了如何从服务中的会话0启动进程,我发现了如何捕获用户登录的时间


但是我需要知道Windows会话是交互式会话还是交互式Windows会话列表。

使用
Environment.UserInteractive
。它返回布尔值。

在当前版本的Windows中,会话0是唯一的非交互式会话。所有其他会话都是交互式的,尽管它们可能在任何给定时刻连接到交互式用户,也可能不连接到交互式用户


您可以使用来确定存在哪些会话以及它们处于什么状态。

首先设置互操作声明。这是最难的部分

DllImport("secur32.dll", SetLastError = false)]
private static extern uint LsaFreeReturnBuffer(IntPtr buffer);

[DllImport("Secur32.dll", SetLastError = false)]
private static extern uint LsaEnumerateLogonSessions
        (out UInt64 LogonSessionCount, out IntPtr LogonSessionList);

[DllImport("Secur32.dll", SetLastError = false)]
private static extern uint LsaGetLogonSessionData(IntPtr luid, 
    out IntPtr ppLogonSessionData);

[StructLayout(LayoutKind.Sequential)]
private struct LSA_UNICODE_STRING
{
    public UInt16 Length;
    public UInt16 MaximumLength;
    public IntPtr buffer;
}

[StructLayout(LayoutKind.Sequential)]
private struct LUID
{
    public UInt32 LowPart;
    public UInt32 HighPart;
}

[StructLayout(LayoutKind.Sequential)]
private struct SECURITY_LOGON_SESSION_DATA
{
    public UInt32 Size;
    public LUID LoginID;
    public LSA_UNICODE_STRING Username;
    public LSA_UNICODE_STRING LoginDomain;
    public LSA_UNICODE_STRING AuthenticationPackage;
    public UInt32 LogonType;
    public UInt32 Session;
    public IntPtr PSiD;
    public UInt64 LoginTime;
    public LSA_UNICODE_STRING LogonServer;
    public LSA_UNICODE_STRING DnsDomainName;
    public LSA_UNICODE_STRING Upn;
}

private enum SECURITY_LOGON_TYPE : uint
{
    Interactive = 2,        //The security principal is logging on 
                            //interactively.
    Network,                //The security principal is logging using a 
                            //network.
    Batch,                  //The logon is for a batch process.
    Service,                //The logon is for a service account.
    Proxy,                  //Not supported.
    Unlock,                 //The logon is an attempt to unlock a workstation.
    NetworkCleartext,       //The logon is a network logon with cleartext 
                            //credentials.
    NewCredentials,         //Allows the caller to clone its current token and
                            //specify new credentials for outbound connections.
    RemoteInteractive,      //A terminal server session that is both remote 
                            //and interactive.
    CachedInteractive,      //Attempt to use the cached credentials without 
                            //going out across the network.
    CachedRemoteInteractive,// Same as RemoteInteractive, except used 
                            // internally for auditing purposes.
    CachedUnlock            // The logon is an attempt to unlock a workstation.
}
下一步枚举并提取信息

  UInt64 count;
  IntPtr luidPtr = IntPtr.Zero;
  LsaEnumerateLogonSessions(out count, out luidPtr);  //gets an array of 
                                                      //pointers to LUIDs

  IntPtr iter = luidPtr;                              //set the pointer to the
                                                      //start of the array

  for (ulong i = 0; i < count; i++)                   //for each pointer in the
                                                      //array
  {
      IntPtr sessionData;

      LsaGetLogonSessionData(iter, out sessionData);
      SECURITY_LOGON_SESSION_DATA data =(
          SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure
                (sessionData, typeof(SECURITY_LOGON_SESSION_DATA));

      //if we have a valid logon
      if (data.PSiD != IntPtr.Zero)
      {
          //get the security identifier for further use
          System.Security.Principal.SecurityIdentifier sid = 
          new System.Security.Principal.SecurityIdentifier(data.PSiD);

          SECURITY_LOGON_TYPE secType = (SECURITY_LOGON_TYPE)data.LogonType;

          //Look at sectype to see if interactive or remote interactive
          Console.WriteLine(secType.ToString())
          If (secType == SECURITY_LOGON_TYPE.Interactive || secType ==    SECURITY_LOGON_TYPE.RemoteInteractive)
          {
            //do something
          }

       }

       iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LUID))); 
       //move the pointer forward
       LsaFreeReturnBuffer(sessionData);
       //free the SECURITY_LOGON_SESSION_DATA memory in the struct
  }
  LsaFreeReturnBuffer(luidPtr);       //free the array of LUIDs
UInt64计数;
IntPtr luidPtr=IntPtr.0;
LsaEnumerateLogonSessions(out计数,out luidPtr)//获取一个
//指向路易斯的指针
IntPtr iter=luidPtr//将指针设置为
//数组的开始
for(ulong i=0;i
让服务尝试在其他会话中启动流程几乎总是一个失败的计划。最好让其他程序在每次会话启动时启动,然后在服务想要在任何特定会话中启动另一个进程时与服务进行通信和协调。我非常确信这是一个糟糕的想法,但仅限于我。您是否试图检测您在交互会话中的时间,或者如果您的服务设置为与用户交互?首先,考虑任何会话!0为交互式;第二,检查服务的设置。当前会话可以,但我的程序在服务上运行,我需要列出所有交互式Windows会话。您需要使用的调用是GetUserObjectInformation。它返回USEROBJECTFLAGS标志结构。如果设置了WSF_VISIBLE,则流程是交互式的。诀窍在于获得您想要了解的进程的windows工作站句柄。由于您不是调用进程,因此必须跳过一些安全环才能获取信息。如果您是父进程,请调用GetProcessWindowsStation以获取要在GetUserObjectInformation中使用的句柄GetUserObjectInformation有关窗口站和桌面,而不是会话。您也不能在其他会话中使用它获取有关窗口站或桌面的信息。是的,您是正确的。我误解了这个问题。我将重新发布答案