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

时间:2014-11-13 13:47:55

标签: c# windows windows-services

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

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

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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