C# 如何获取当前用户的唯一ID';windows-c中的s登录会话#
我需要获取唯一标识当前windows用户登录会话的值。这适用于winforms应用程序,而不是ASP.NET。我将从多个进程中检索此文件,因此在同一登录会话中检索时需要返回相同的值。它只需要在所有用户会话期间(例如,直到下次重新启动机器)在当前机器上是唯一的 我认为这是正确的事情,但似乎有点难以挽回。有没有其他更简单的方法C# 如何获取当前用户的唯一ID';windows-c中的s登录会话#,c#,.net,windows,C#,.net,Windows,我需要获取唯一标识当前windows用户登录会话的值。这适用于winforms应用程序,而不是ASP.NET。我将从多个进程中检索此文件,因此在同一登录会话中检索时需要返回相同的值。它只需要在所有用户会话期间(例如,直到下次重新启动机器)在当前机器上是唯一的 我认为这是正确的事情,但似乎有点难以挽回。有没有其他更简单的方法 我将使用ID包含在命名管道服务的地址中,以便在计算机上运行的两个进程之间进行通信。我希望包含登录Id,以避免多个用户登录时发生冲突,可能包括同一用户的多个会话。如果我理解正确
我将使用ID包含在命名管道服务的地址中,以便在计算机上运行的两个进程之间进行通信。我希望包含登录Id,以避免多个用户登录时发生冲突,可能包括同一用户的多个会话。如果我理解正确,您可以生成一个
要确保每个用户会话都有一个唯一的id,我想您必须使用您提到的痛苦方法-。获取会话id的最简单方法是查看属性:
System.Diagnostics.Process.GetCurrentProcess().SessionId
该值与GetTokenInformation(…,TokenSessionId,…)返回的值相同
注意:您应该记住的一点是,会话Id不是。
例如,在Win7上,在同一会话中由同一用户启动的提升进程将具有不同的LogonId(从copmaring到非提升的LogonId),但将具有相同的SessionId。
即使runniung非提升进程使用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();
}
}
}
}
据我所知,您需要的是: SID:S-1-5-5-X-Y 名称:登录会话 描述:登录会话。对于每个会话,这些SID的X和Y值都不同 Windows操作系统中的已知安全标识符 有人在这里要求类似的东西: 他们有一个很好的答案,但我想补充我自己的 这是我的解决方案:
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;
}
}
}
使用系统;
使用System.Windows.Forms;
使用System.Runtime.InteropServices;
命名空间TestLogonSid
{
公共部分类Form1:Form
{
私有委托bool EnumDesktopProc(字符串lpszDesktop,IntPtr lpram);
公共表格1()
{
初始化组件();
}
私有无效按钮1\u单击\u 1(对象发送者,事件参数e)
{
this.textBox1.Text=GetLogonSid.GetLogonSid();
}
}
公共类GetLogonSid
{
//标识当前与指定对象关联的用户的SID结构。
//如果没有用户与对象关联,则lpnLengthNeeded指向的缓冲区中返回的值为零。
//请注意,SID是一个可变长度的结构。
//在检索SID的值之前,通常会调用GetUserObjectInformation来确定SID的长度。
私有常量int UOI\U USER\U SID=4;
//GetUserObjectInformation函数
//检索有关指定窗口站或桌面对象的信息。
[DllImport(“user32.dll”)]
静态外部bool GetUserObjectInformation(IntPtr hObj,int nIndex,[marshallas(UnmanagedType.LPArray)]字节[]pvInfo,int nLength,out uint lpnlength needed);
//GetThreadDesktop函数
//检索分配给指定线程的桌面句柄。
[DllImport(“user32.dll”)]
私有静态外部IntPtr GetThreadDesktop(intdwthreadid);
//GetCurrentThreadId函数
//检索调用线程的线程标识符。
[DllImport(“kernel32.dll”)]
public static extern int GetCurrentThreadId();
//ConvertSidToStringSid函数
//ConvertSidToStringSid函数将安全标识符(SID)转换为适合显示、存储或传输的字符串格式。
//要将字符串格式SID转换回有效的功能SID,请调用ConvertStringSidToSid函数。
[DllImport(“advapi32”,CharSet=CharSet.Auto,SetLastError=true)]
静态外部布尔转换器SIDTOSTRINGSID(
[Marshallas(UnmanagedType.LPArray)]字节[]pSID,
out IntPtr ptrSid);
///
///getLogonSid函数返回登录会话字符串
///
///
公共静态字符串getLogonSid()
{
字符串sidString=“”;
IntPtr hdesk=GetThreadDesktop(GetCurrentThreadId());
字节[]buf=新字节[100];
需要的单位长度;
GetUserObjectInformation(hdesk、UOI_用户_SID、buf、100、需要的输出长度);
IntPtr-ptrSid;
如果(!ConvertSidToStringSid(buf,out ptrSid))
抛出新的System.ComponentModel.Win32Exception();
尝试
{
sidString=Marshal.PtrToStringAuto(ptrSid);
}
抓住
{
}
返回字符串;
}
}
}
如果用户登录两次怎么办?同一用户是否可以使用相同的凭据登录计算机两次?我一直认为你会被重定向回你现有的会话。我想需要测试。:)@扎克:是的,我想你可以。虽然使用rdp,但它会将您踢到原始帐户。但是,一个使用用户凭据运行的服务,以及一个登录到计算机的用户如何。@YetAnotherUser我想我不会以实际用户的身份运行服务,而是以一个服务帐户(域或本地)运行服务。:)想知道你能不能从温斯顿得到这个?大概是e