如何获取当前用户在Windowslogin会话的唯一ID –

我需要得到一个唯一标识当前Windows用户的login会话的值。 这是一个winforms应用程序,而不是ASP.NET。 我将从多个进程中检索它,因此在同一个login会话中检索时需要返回相同的值。 在所有用户会话期间,只需在当前机器上保持唯一性 – 例如直到下一次重新启动机器。

我认为WindowsloginID是正确的,但似乎有点痛苦检索。 还有什么或更简单的方法来得到这个?

我将使用该ID来包含在一个命名pipe道服务的地址中,以在机器上运行的两个进程之间进行通信。 我想包括loginID,以避免有多个用户login时发生冲突,包括可能是同一用户的多个会话。

据我所知,你需要的是这样的:

SID:S-1-5-5-XY名称:登录会话描述:登录会话。 这些SID的X和Y值对于每个会话都是不同的。

Windows操作系统中众所周知的安全标识符http://support.microsoft.com/kb/243330

有人问这里有类似的东西:

如何在C#中登录SID

他们在那里有一个很好的答案,但我想补充我自己的

这是我的解决方案:

using System; using System.Windows.Forms; using System.Runtime.InteropServices; namespace TestLogonSid { public partial class Form1 : Form { private delegate bool EnumDesktopProc(string lpszDesktop, IntPtr lParam); public Form1() { InitializeComponent(); } private void button1_Click_1(object sender, EventArgs e) { this.textBox1.Text = GetLogonSid.getLogonSid(); } } public class GetLogonSid { //The SID structure that identifies the user that is currently associated with the specified object. //If no user is associated with the object, the value returned in the buffer pointed to by lpnLengthNeeded is zero. //Note that SID is a variable length structure. //You will usually make a call to GetUserObjectInformation to determine the length of the SID before retrieving its value. private const int UOI_USER_SID = 4; //GetUserObjectInformation function //Retrieves information about the specified window station or desktop object. [DllImport("user32.dll")] static extern bool GetUserObjectInformation(IntPtr hObj, int nIndex, [MarshalAs(UnmanagedType.LPArray)] byte[] pvInfo, int nLength, out uint lpnLengthNeeded); //GetThreadDesktop function //Retrieves a handle to the desktop assigned to the specified thread. [DllImport("user32.dll")] private static extern IntPtr GetThreadDesktop(int dwThreadId); //GetCurrentThreadId function //Retrieves the thread identifier of the calling thread. [DllImport("kernel32.dll")] public static extern int GetCurrentThreadId(); //ConvertSidToStringSid function //The ConvertSidToStringSid function converts a security identifier (SID) to a string format suitable for display, storage, or transmission. //To convert the string-format SID back to a valid, functional SID, call the ConvertStringSidToSid function. [DllImport("advapi32", CharSet = CharSet.Auto, SetLastError = true)] static extern bool ConvertSidToStringSid( [MarshalAs(UnmanagedType.LPArray)] byte[] pSID, out IntPtr ptrSid); /// <summary> /// The getLogonSid function returns the Logon Session string /// </summary> /// <returns></returns> public static string getLogonSid() { string sidString = ""; IntPtr hdesk = GetThreadDesktop(GetCurrentThreadId()); byte[] buf = new byte[100]; uint lengthNeeded; GetUserObjectInformation(hdesk, UOI_USER_SID, buf, 100, out lengthNeeded); IntPtr ptrSid; if (!ConvertSidToStringSid(buf, out ptrSid)) throw new System.ComponentModel.Win32Exception(); try { sidString = Marshal.PtrToStringAuto(ptrSid); } catch { } return sidString; } } } 

获取Session ID最简单的方法是查看Process.SessionId属性:

 System.Diagnostics.Process.GetCurrentProcess().SessionId 

该值与GetTokenInformation(…,TokenSessionId,…)返回的值相同。

注意:您应该记住的一件事是会话Id不是登录ID 。 例如,在同一个会话中,在同一用户下启动的Win7提升进程将具有不同的LogonId(共享到非提升的),但会具有相同的SessionId。 即使Runnung非升级过程与RunAs显式指定相同用户的凭据将创建新的登录Sesison Id。 例如,当您映射网络驱动器时,此类行为具有意义。 自Vista以来,即使进程在同一个会话和同一用户下运行,使用一个令牌LogonId的进程也不会看到与另一个LogonId映射的网络目录。

以下是您可以在不同会话/信誉上启动以查看其差异的示例应用程序:

 using System; using System.Runtime.InteropServices; namespace GetCurrentSessionId { class Program { enum TokenInformationClass { TokenUser = 1, TokenGroups, TokenPrivileges, TokenOwner, TokenPrimaryGroup, TokenDefaultDacl, TokenSource, TokenType, TokenImpersonationLevel, TokenStatistics, TokenRestrictedSids, TokenSessionId, TokenGroupsAndPrivileges, TokenSessionReference, TokenSandBoxInert, TokenAuditPolicy, TokenOrigin } enum TokenType { TokenPrimary = 1, TokenImpersonation } enum SecurityImpersonationLevel { SecurityAnonymous, SecurityIdentification, SecurityImpersonation, SecurityDelegation } [StructLayout(LayoutKind.Sequential)] struct TokenStatistics { public Int64 TokenId; public Int64 AuthenticationId; public Int64 ExpirationTime; public TokenType TokenType; public SecurityImpersonationLevel ImpersonationLevel; public Int32 DynamicCharged; public Int32 DynamicAvailable; public Int32 GroupCount; public Int32 PrivilegeCount; public Int64 ModifiedId; } struct TokenOrigin { public Int64 OriginatingLogonSession; } [DllImport("advapi32.dll", EntryPoint = "GetTokenInformation", SetLastError = true)] static extern bool GetTokenInformation( IntPtr tokenHandle, TokenInformationClass tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int ReturnLength); public const int ERROR_INSUFFICIENT_BUFFER = 0x7a; static void Main(string[] args) { try { Console.WriteLine("Session Id: {0}", System.Diagnostics.Process.GetCurrentProcess().SessionId); IntPtr tokenInfo; bool result; int infoSize; IntPtr hToken = System.Security.Principal.WindowsIdentity.GetCurrent().Token; result = GetTokenInformation(hToken, TokenInformationClass.TokenStatistics, IntPtr.Zero, 0, out infoSize); if (!result && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER) { tokenInfo = Marshal.AllocHGlobal(infoSize); result = GetTokenInformation(hToken, TokenInformationClass.TokenStatistics, tokenInfo, infoSize, out infoSize); if (result) { TokenStatistics tokenStats = (TokenStatistics)Marshal.PtrToStructure(tokenInfo, typeof(TokenStatistics)); Console.WriteLine("LogonId: 0x{0:X16}", tokenStats.AuthenticationId); } else { Console.Error.WriteLine("LogonId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error()); } Marshal.FreeHGlobal(tokenInfo); } else { Console.Error.WriteLine("LogonId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error()); } tokenInfo = Marshal.AllocHGlobal(sizeof (Int32)); result = GetTokenInformation(hToken, TokenInformationClass.TokenSessionId, tokenInfo, sizeof (Int32), out infoSize); if (result) { int tokenSessionId = Marshal.ReadInt32(tokenInfo); Console.WriteLine("TokenSessionId: {0}", tokenSessionId); } else { Console.Error.WriteLine("TokenSessionId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error()); } Marshal.FreeHGlobal(tokenInfo); result = GetTokenInformation(hToken, TokenInformationClass.TokenOrigin, IntPtr.Zero, 0, out infoSize); if (!result && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER) { tokenInfo = Marshal.AllocHGlobal(infoSize); result = GetTokenInformation(hToken, TokenInformationClass.TokenOrigin, tokenInfo, infoSize, out infoSize); if (result) { TokenOrigin tokenOrigin = (TokenOrigin) Marshal.PtrToStructure(tokenInfo, typeof (TokenOrigin)); Console.WriteLine("OriginatingSessionId: 0x{0:X16}", tokenOrigin.OriginatingLogonSession); } else { Console.WriteLine("OriginatingSessionId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error()); } Marshal.FreeHGlobal(tokenInfo); } else { Console.WriteLine("OriginatingSessionId: FAILED with 0x{0:X08}", Marshal.GetLastWin32Error()); } Console.WriteLine("Press any key..."); Console.ReadKey(); } catch (Exception ex) { Console.Error.WriteLine("Unexpected error: {0}", ex); Console.ReadKey(); } } } } 

您可以尝试Environment.UserDomainNameEnvironment.UserName

为了确保每个用户会话唯一ID我想你将不得不使用你提到的痛苦的方法 – 如何获得在C#登录SID 。

如果我正确理解你,你可以生成一个GUID