2010-01-27 26 views
8

¿Cómo se puede recuperar el SID de inicio de sesión de Windows en C# .net? (No es el SID del usuario, sino el único nuevo para cada sesión)Cómo obtener el SID de inicio de sesión en C#

+0

En entorno Windwos SID significa Security Identifier, no Session Id. Para obtener Id. De sesión use 'System.Diagnostics.Process.GetCurrentProcess(). SessionId' Para obtener más detalles, vea [mi respuesta aquí] (http://stackoverflow.com/a/16942663/725903) – mistika

Respuesta

6

Me temo que tiene que recurrir al uso de P/Invoke. Hay un ejemplo de cómo hacerlo en pinvoke.net (consulte la parte inferior de la página):

Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenSessionId , TokenInformation , TokenInfLength , out TokenInfLength); 

Tenga en cuenta que he cambiado el ejemplo mediante la alteración de una sola línea, he sustituido TOKEN_INFORMATION_CLASS.TokenUser con TOKEN_INFORMATION_CLASS.TokenSessionId que es exactamente lo que necesita .

Espero que esto ayude.

Actualización: Aquí está el trabajo (al menos en mi máquina) Código:

using System; 
using System.Runtime.InteropServices; 
using System.Security.Principal; 

namespace LinqTest 
{ 
    public class ClsLookupAccountName 
    { 
     public const uint SE_GROUP_LOGON_ID = 0xC0000000; // from winnt.h 
     public const int TokenGroups = 2; // from TOKEN_INFORMATION_CLASS 

     enum TOKEN_INFORMATION_CLASS 
     { 
      TokenUser = 1, 
      TokenGroups, 
      TokenPrivileges, 
      TokenOwner, 
      TokenPrimaryGroup, 
      TokenDefaultDacl, 
      TokenSource, 
      TokenType, 
      TokenImpersonationLevel, 
      TokenStatistics, 
      TokenRestrictedSids, 
      TokenSessionId, 
      TokenGroupsAndPrivileges, 
      TokenSessionReference, 
      TokenSandBoxInert, 
      TokenAuditPolicy, 
      TokenOrigin 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct SID_AND_ATTRIBUTES 
     { 
      public IntPtr Sid; 
      public uint Attributes; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct TOKEN_GROUPS 
     { 
      public int GroupCount; 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] 
      public SID_AND_ATTRIBUTES[] Groups; 
     }; 

     // Using IntPtr for pSID instead of Byte[] 
     [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] 
     static extern bool ConvertSidToStringSid(IntPtr pSID, out IntPtr ptrSid); 

     [DllImport("kernel32.dll")] 
     static extern IntPtr LocalFree(IntPtr hMem); 

     [DllImport("advapi32.dll", SetLastError = true)] 
     static extern bool GetTokenInformation(
      IntPtr TokenHandle, 
      TOKEN_INFORMATION_CLASS TokenInformationClass, 
      IntPtr TokenInformation, 
      int TokenInformationLength, 
      out int ReturnLength); 

     public static string GetLogonId() 
     { 
      int TokenInfLength = 0; 
      // first call gets lenght of TokenInformation 
      bool Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenGroups, IntPtr.Zero, TokenInfLength, out TokenInfLength); 
      IntPtr TokenInformation = Marshal.AllocHGlobal(TokenInfLength); 
      Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenGroups, TokenInformation, TokenInfLength, out TokenInfLength); 

      if (!Result) 
      { 
       Marshal.FreeHGlobal(TokenInformation); 
       return string.Empty; 
      } 

      string retVal = string.Empty; 
      TOKEN_GROUPS groups = (TOKEN_GROUPS)Marshal.PtrToStructure(TokenInformation, typeof(TOKEN_GROUPS)); 
      int sidAndAttrSize = Marshal.SizeOf(new SID_AND_ATTRIBUTES()); 
      for (int i = 0; i < groups.GroupCount; i++) 
      { 
       SID_AND_ATTRIBUTES sidAndAttributes = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(
        new IntPtr(TokenInformation.ToInt64() + i * sidAndAttrSize + IntPtr.Size), typeof(SID_AND_ATTRIBUTES)); 
       if ((sidAndAttributes.Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID) 
       { 
        IntPtr pstr = IntPtr.Zero; 
        ConvertSidToStringSid(sidAndAttributes.Sid, out pstr); 
        retVal = Marshal.PtrToStringAuto(pstr); 
        LocalFree(pstr); 
        break; 
       } 
      } 

      Marshal.FreeHGlobal(TokenInformation); 
      return retVal; 
     } 
    } 
} 

N. B. Lo probé en mi máquina x64, así que preste mucha atención al código TokenInformation.ToInt64(), tal vez debería reemplazarlo por TokenInformation.ToInt32()

+0

Desafortunadamente no funciona. No devuelve nada. De acuerdo con esto (http://msdn.microsoft.com/en-us/library/aa379626%28VS.85%29.aspx), solo funciona en el servidor de terminal, por lo que podría no ser el ID de sesión que necesito. – Jos

+0

Agregué otra versión del código, funciona en mi máquina. Por favor, siéntase libre de preguntarme si algo no está claro. –

+0

Gracias! Este funciona a la perfección. Usé TokenLogonSid en lugar de TokenGroups, pero eso solo funciona para Windows Vista y 7. – Jos

1

System.Security.Principal.WindowsIdentity.GetCurrent(). User.AccountDomainSid - ¿podría hacer el truco?

+1

It is * not * el ID de la sesión de inicio de sesión SilverSkin preguntó acerca de –

+1

Creo que el SID del usuario permanece sin cambios entre las sesiones, pero para cada inicio de sesión se crea un token, debe ser posible acceder a esto a través de ... GetCurrent(). User.Token? – SilverSkin

+0

El token es de hecho lo que necesito, pero tengo que convertirlo a un SID utilizable. – Jos

1

Sé que esta es una publicación anterior. Acabo de toparme con este problema ya que tuve que obtener la ID de la sesión ICA y la ID de la sesión RDP para que un programa recolecte las variables correctas para cada tipo de conexión remota. El ID de sesión actual se encuentra en Regedit HKEY_CURRENT_USER \ Remote *. Como no pude encontrar ninguna alternativa a WTS, estoy publicando mi solución aquí.

// Prints out ICA or RDP session ID of current user 

using System; 
using Microsoft.Win32; 

namespace ViaRegedit 
{ 
    class Program03 
    { 
     static void Main(string[] args) 
     { 
      // Obtain an instance of RegistryKey for the CurrentUser registry 
      RegistryKey rkCurrentUser = Registry.CurrentUser; 
      // Obtain the test key (read-only) and display it. 
      RegistryKey rkTest = rkCurrentUser.OpenSubKey("Remote"); 
      foreach (string valueName in rkTest.GetSubKeyNames()) 
      { 
       //Getting path to RDP/Citrix session ID 
       string RDPICApath = ""; 
       if (rkTest.OpenSubKey(valueName) != null && rkTest.OpenSubKey(valueName) != null) { RDPICApath = rkTest.OpenSubKey(valueName).ToString(); } 
       Console.WriteLine("Getting CurrentUser ICA-RDP path from string = " + RDPICApath); 

       //Seperating RDPICApath to get session number 
       string RDPICAnumber = RDPICApath.Substring(RDPICApath.LastIndexOf('\\') + 1); 
       Console.WriteLine("Current User RDPICAnumber = " + RDPICAnumber); 
      } 
      rkTest.Close(); 
      rkCurrentUser.Close(); 
      Console.ReadLine(); 
     } 
    } 

} 
Cuestiones relacionadas