[英]How to get the logon SID in C#
How does one retrieve the Windows Logon SID in C# .net?如何在 C# .net 中检索 Windows 登录 SID? (not the user SID, but the unique new one for each session)
(不是用户 SID,而是每个会话的唯一新 SID)
I'm afraid you have to resort to using P/Invoke.恐怕您不得不求助于使用 P/Invoke。 There's an example how to do it at pinvoke.net (please see the bottom of the page):
在pinvoke.net 上有一个示例(请参阅页面底部):
Result = GetTokenInformation(WindowsIdentity.GetCurrent().Token, TOKEN_INFORMATION_CLASS.TokenSessionId , TokenInformation , TokenInfLength , out TokenInfLength );
Please note that I changed the example by altering just one line, I replaced TOKEN_INFORMATION_CLASS.TokenUser
with TOKEN_INFORMATION_CLASS.TokenSessionId
which is exactly what you need.请注意,我通过改变只有一条线路改变的例子,我换成
TOKEN_INFORMATION_CLASS.TokenUser
与TOKEN_INFORMATION_CLASS.TokenSessionId
这正是你需要的。
Hope this helps.希望这可以帮助。
Update: Here's the working (at least on my machine) code:更新:这是工作(至少在我的机器上)代码:
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;
}
}
}
NB I tested it on my x64 machine, so please pay close attention on TokenInformation.ToInt64()
piece of code, maybe you should replace it with TokenInformation.ToInt32()
注意我在我的 x64 机器上测试过,所以请密切关注
TokenInformation.ToInt64()
这段代码,也许你应该用TokenInformation.ToInt32()
替换它
System.Security.Principal.WindowsIdentity.GetCurrent().User.AccountDomainSid - 可能有用吗?
I know this is an old post.我知道这是一个旧帖子。 Just ran into this problem as I had to get the ICA session ID and the RDP session ID to have a program collect the correct variables for each type of remote connection.
刚遇到这个问题,因为我必须获得 ICA 会话 ID 和 RDP 会话 ID,才能让程序为每种类型的远程连接收集正确的变量。 The current session ID is located in Regedit HKEY_CURRENT_USER\\Remote*.
当前会话 ID 位于 Regedit HKEY_CURRENT_USER\\Remote*。 As I could not find any alternatives to WTS, I am posting my solution here.
由于我找不到 WTS 的任何替代方案,因此我在此处发布了我的解决方案。
// 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();
}
}
}
I just spent a long time getting the SID using TOKEN_USER and so forth, then discovered a shortcut in C#.我只是花了很长时间使用 TOKEN_USER 等获取 SID,然后在 C# 中发现了一个快捷方式。 You still need to get the Process Handle (eg https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.handle?view=netcore-3.1 ) and then the token with P/invoke:
您仍然需要获取进程句柄(例如https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.handle?view=netcore-3.1 ),然后是带有 P/invoke 的令牌:
OpenProcessToken(hProcess, TOKEN_READ, out IntPtr hToken))
But once you have the token, you don't need to do any of the nasty GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenUser...
stuff you just use:但是一旦你有了令牌,你就不需要做任何令人讨厌的
GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenUser...
你只需要使用的东西:
var winId = System.Security.Principal.WindowsIdentity(hToken);
... and BOOM you can get all the info you want (inc SID) for the user out of winId. ...和 BOOM,您可以从 winId 中获取用户所需的所有信息(包括 SID)。
Don't forget to CloseHandle(hToken)
and on hProcess afterwards!之后不要忘记
CloseHandle(hToken)
和 hProcess !
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.