获取机器SID(包括主域控制器)
我需要在 C# 中获取计算机 SID(不是计算机帐户的 SID)。计算机指定为主机名,不一定是本地计算机,可以是域计算机或工作组计算机。我使用这个帮助程序类来调用 LookupAccountName API 函数:
private static class Helper
{
internal enum SID_NAME_USE
{
SidTypeUser = 1,
SidTypeGroup,
SidTypeDomain,
SidTypeAlias,
SidTypeWellKnownGroup,
SidTypeDeletedAccount,
SidTypeInvalid,
SidTypeUnknown,
SidTypeComputer
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool LookupAccountName(
string systemName,
string accountName,
byte[] sid,
ref int sidLen,
System.Text.StringBuilder domainName,
ref int domainNameLen,
out SID_NAME_USE peUse);
public static SecurityIdentifier LookupAccountName(
string systemName,
string accountName,
out string strDomainName,
out SID_NAME_USE accountType)
{
const int ERROR_INSUFFICIENT_BUFFER = 122;
int lSidSize = 0;
int lDomainNameSize = 0;
//First get the required buffer sizes for SID and domain name.
LookupAccountName(systemName,
accountName,
null,
ref lSidSize,
null,
ref lDomainNameSize,
out accountType);
if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
{
//Allocate the buffers with actual sizes that are required
//for SID and domain name.
byte[] sid = new byte[lSidSize];
var sbDomainName = new System.Text.StringBuilder(lDomainNameSize);
if (LookupAccountName(systemName,
accountName,
sid,
ref lSidSize,
sbDomainName,
ref lDomainNameSize,
out accountType))
{
strDomainName = sbDomainName.ToString();
return new SecurityIdentifier(sid, 0);
}
}
throw new Win32Exception();
}
}
并像这样使用它:
Helper.SID_NAME_USE accountType;
string refDomain;
SecurityIdentifier sid = Helper.LookupAccountName("falcon.mydomain.local", "falcon", out refDomain, out accountType); //Domain computer
SecurityIdentifier sid = Helper.LookupAccountName("rat", "rat", out refDomain, out accountType); //Workgroup computer
我唯一的问题是,如果计算机是主域控制器,则这不起作用(在这种情况下我需要获取域 SID)。
I need to get machine SID (not computer account's SID) in C#. Computer is specified be host name, it is't necessarily local computer and it can be domain computer or workgroup computer. I using this helper class to call LookupAccountName API function:
private static class Helper
{
internal enum SID_NAME_USE
{
SidTypeUser = 1,
SidTypeGroup,
SidTypeDomain,
SidTypeAlias,
SidTypeWellKnownGroup,
SidTypeDeletedAccount,
SidTypeInvalid,
SidTypeUnknown,
SidTypeComputer
}
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool LookupAccountName(
string systemName,
string accountName,
byte[] sid,
ref int sidLen,
System.Text.StringBuilder domainName,
ref int domainNameLen,
out SID_NAME_USE peUse);
public static SecurityIdentifier LookupAccountName(
string systemName,
string accountName,
out string strDomainName,
out SID_NAME_USE accountType)
{
const int ERROR_INSUFFICIENT_BUFFER = 122;
int lSidSize = 0;
int lDomainNameSize = 0;
//First get the required buffer sizes for SID and domain name.
LookupAccountName(systemName,
accountName,
null,
ref lSidSize,
null,
ref lDomainNameSize,
out accountType);
if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
{
//Allocate the buffers with actual sizes that are required
//for SID and domain name.
byte[] sid = new byte[lSidSize];
var sbDomainName = new System.Text.StringBuilder(lDomainNameSize);
if (LookupAccountName(systemName,
accountName,
sid,
ref lSidSize,
sbDomainName,
ref lDomainNameSize,
out accountType))
{
strDomainName = sbDomainName.ToString();
return new SecurityIdentifier(sid, 0);
}
}
throw new Win32Exception();
}
}
and using it like this:
Helper.SID_NAME_USE accountType;
string refDomain;
SecurityIdentifier sid = Helper.LookupAccountName("falcon.mydomain.local", "falcon", out refDomain, out accountType); //Domain computer
SecurityIdentifier sid = Helper.LookupAccountName("rat", "rat", out refDomain, out accountType); //Workgroup computer
My only problem is, that this is not working if computer is primary domain controller (i need to obtain domain SID in that case).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对于大多数计算机来说,您似乎执行以下操作:
LookupAccountName("", "ComputerName", ...);
ConvertSidToStringSid(...)
但对于域控制器,您必须在计算机名称参数中添加美元符号,然后删除返回的 SID 中的最后一段。
It appears that for most computers you do the following:
LookupAccountName("", "ComputerName", ...);
ConvertSidToStringSid(...)
But for domain controllers you have to add a dollar sign to the computer name parameter, and then delete the last segment in the returned SID.
您可以通过
PolicyAccountDomainInformation
接收计算机 SID(与psgetsid
的输出匹配):如果您想要计算机帐户 sid,请将
LookupAccountName
与一起使用>MachineName$
(再次匹配 psgetsid):You can receive the machine SID (matching the output of
psgetsid
) viaPolicyAccountDomainInformation
:If you want the computer account sid, use
LookupAccountName
withMachineName$
(again matching psgetsid):