【发布时间】:2010-09-29 14:21:41
【问题描述】:
我希望能够检索本地机器的 SID,例如 PSGetSID 来自 Sysinternals 但使用 C# 的实用程序。 这可能吗?
编辑: 我正在寻找一种适用于可能是也可能不是域成员的计算机的解决方案。
【问题讨论】:
-
你可以看看以下主题:stackoverflow.com/questions/14113558/…
标签: c#
我希望能够检索本地机器的 SID,例如 PSGetSID 来自 Sysinternals 但使用 C# 的实用程序。 这可能吗?
编辑: 我正在寻找一种适用于可能是也可能不是域成员的计算机的解决方案。
【问题讨论】:
标签: c#
这有很好的帮助类来使用lookupaccountname win32 api调用。
get machine SID (including primary domain controller)
我没有找到使用原生 C# 的方法
【讨论】:
您可以通过 pinvoke 来完成,然后从 Win32 API 获取它。
http://www.pinvoke.net/default.aspx/advapi32.lookupaccountname
还有一种方法可以在“纯”.NET 中获取它。
【讨论】:
来自用户 ewall 的另一篇 SO 帖子有一个纯 .NET 解决方案,其中包含 C# 和 PowerShell 中的示例。它使用 DirectoryEntry 和 SecurityDescriptor 对象。看: How can I retrieve a Windows Computer's SID using WMI?
【讨论】:
本地用户帐户 SID 形式:S-1-5-21-xxxxxxxxx-xxxxxxxxx-xxxxxxxxxx-yyyy
系统特定部分:xxx...xxx
用户帐户特定部分:yyyy
因此,您只需从用户帐户 SID 中删除最后一组数字即可获得系统 SID。
如果您的代码是Windows 应用程序,您可以通过以下方式获取系统 SID:
using System.Security.Principal;
string systemSid;
using (WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent())
{
systemSid = windowsIdentity.User.Value.Substring(0, windowsIdentity.User.Value.LastIndexOf('-'));
}
如果您的代码是 Web 应用程序,它通常在应用程序池标识的上下文中运行,如果您的代码是 Windows 服务,它通常在系统帐户(系统、本地服务、网络服务)。这些身份都不是用户帐户。所以你不能使用上面的代码。您需要知道用户帐户名称,或列出用户帐户。
如果您知道用户帐户名,则可以通过以下方式获取系统 SID:
using System.Security.Principal;
NTAccount ntAccount = new NTAccount("MACHINE_NAME\\UserAccountName");
SecurityIdentifier sid = (SecurityIdentifier)ntAccount.Translate(typeof(SecurityIdentifier));
string systemSid = sid.Value.Substring(0, sid.Value.LastIndexOf('-'));
但是您不能假设像“guest”这样的标准用户的名称,因为标准本地用户帐户名称已本地化,因为此标准用户帐户可能已被删除,而且标准用户帐户可能在未来的 Windows 版本中被禁止。
所以大多数时候,从 Web 应用程序或 Windows 服务,您需要通过 WMI 列出用户帐户:
// your project must reference System.Management.dll
using System.Management;
SelectQuery selectQuery = new SelectQuery("SELECT * FROM Win32_UserAccount");
ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher(selectQuery);
string systemSid;
foreach (ManagementObject managementObject in managementObjectSearcher.Get())
{
if (1 == (byte)managementObject["SIDType"])
{
systemSid = managementObject["SID"] as string;
break;
}
}
systemSid = systemSid.Substring(0, systemSid.Value.LastIndexOf('-'));
Win32_UserAccount 类文档:
https://msdn.microsoft.com/en-us/library/aa394507(v=vs.85).aspx
更新
大约快 100 倍:
using Microsoft.Win32;
RegistryKey key = null;
string sid = null;
try
{
foreach (string subKeyName in Registry.Users.GetSubKeyNames())
{
if(subKeyName.StartsWith("S-1-5-21-"))
{
sid = subKeyName.Substring(0, subKeyName.LastIndexOf('-'));
break;
}
}
}
catch (Exception ex)
{
// ...
}
finally
{
if (key != null)
key.Close();
}
【讨论】: