当机器不在活动目录中时如何获取本地机器组/用户列表?
How to get a list of local machine groups / users when machine is not in active directory?
当 windows 机器没有 AD 成员且无法使用 LDAP 搜索时,有没有办法在 C# 中获取本地组和用户的列表?
您可以使用 P/Invoke 调用 native network management API 来获取本地用户和组名:
static class NativeMethods {
[DllImport("netapi32.dll")]
public static extern void NetApiBufferFree(IntPtr bufptr);
[DllImport("netapi32.dll")]
public static extern UInt32 NetUserEnum([MarshalAs(UnmanagedType.LPWStr)] String servername, UInt32 level, UInt32 filter, ref IntPtr bufptr, UInt32 prefmaxlen, ref UInt32 entriesread, ref UInt32 totalentries, IntPtr resumehandle);
[DllImport("netapi32.dll")]
public static extern UInt32 NetLocalGroupEnum([MarshalAs(UnmanagedType.LPWStr)] String servername, UInt32 level, ref IntPtr bufptr, UInt32 prefmaxlen, ref UInt32 entriesread, ref UInt32 totalentries, IntPtr resumehandle);
[DllImport("Netapi32.dll")]
public extern static UInt32 NetLocalGroupGetMembers([MarshalAs(UnmanagedType.LPWStr)] String servername, [MarshalAs(UnmanagedType.LPWStr)] String localgroupname, UInt32 level, ref IntPtr bufptr, UInt32 prefmaxlen, ref UInt32 entriesread, ref UInt32 totalentries, IntPtr resumehandle);
}
API 允许您获取有关用户的各种信息。如果你只想要名字,你可以使用这个函数:
IEnumerable<String> GetUserNames() {
var buffer = IntPtr.Zero;
try {
UInt32 entriesRead = 0;
UInt32 totalEntries = 0;
var result = NativeMethods.NetUserEnum(null, 0, 0, ref buffer, UInt32.MaxValue, ref entriesRead, ref totalEntries, IntPtr.Zero);
if (result != 0)
throw new Win32Exception((Int32) result);
var userNames = Enumerable
.Range(0, (Int32) entriesRead)
.Select(
i => {
var userInfo = Marshal.ReadIntPtr(buffer, i*IntPtr.Size);
var userName = Marshal.PtrToStringAuto(userInfo);
return userName;
}
)
.ToList();
return userNames;
}
finally {
NativeMethods.NetApiBufferFree(buffer);
}
}
LINQ 语句用于"parse" 包含USER_INFO_0
结构的缓冲区。如果您要查询其他信息,则必须进行更详细的 "parsing".
同样可以获取本地组名:
IEnumerable<String> GetLocalGroupNames() {
var buffer = IntPtr.Zero;
try {
UInt32 entriesRead = 0;
UInt32 totalEntries = 0;
var result = NativeMethods.NetLocalGroupEnum(null, 0, ref buffer, UInt32.MaxValue, ref entriesRead, ref totalEntries, IntPtr.Zero);
if (result != 0)
throw new Win32Exception((Int32) result);
var localGroupNames = Enumerable
.Range(0, (Int32) entriesRead)
.Select(
i => {
var localGroupInfo = Marshal.ReadIntPtr(buffer, i*IntPtr.Size);
var groupName = Marshal.PtrToStringAuto(localGroupInfo);
return groupName;
}
)
.ToList();
return localGroupNames;
}
finally {
NativeMethods.NetApiBufferFree(buffer);
}
}
缓冲区中的结构 LOCALGROUP_INFO_0
与 USER_INFO_0
结构具有相同的布局,因此 "parsing" 代码相同。
最后,这里是如何使用 LOCALGROUP_MEMBERS_INFO_3
结构获取组成员资格:
IEnumerable<String> GetLocalGroupUsers(String localGroupName) {
var buffer = IntPtr.Zero;
try {
UInt32 entriesRead = 0;
UInt32 totalEntries = 0;
var result = NativeMethods.NetLocalGroupGetMembers(null, localGroupName, 3, ref buffer, UInt32.MaxValue, ref entriesRead, ref totalEntries, IntPtr.Zero);
if (result != 0)
throw new Win32Exception((Int32) result);
var userNames = Enumerable
.Range(0, (Int32) entriesRead)
.Select(
i => {
var membersInfo = Marshal.ReadIntPtr(buffer, i*IntPtr.Size);
var userName = Marshal.PtrToStringAuto(membersInfo );
return userName;
}
)
.ToList();
return userNames;
}
finally {
NativeMethods.NetApiBufferFree(buffer);
}
}
当 windows 机器没有 AD 成员且无法使用 LDAP 搜索时,有没有办法在 C# 中获取本地组和用户的列表?
您可以使用 P/Invoke 调用 native network management API 来获取本地用户和组名:
static class NativeMethods {
[DllImport("netapi32.dll")]
public static extern void NetApiBufferFree(IntPtr bufptr);
[DllImport("netapi32.dll")]
public static extern UInt32 NetUserEnum([MarshalAs(UnmanagedType.LPWStr)] String servername, UInt32 level, UInt32 filter, ref IntPtr bufptr, UInt32 prefmaxlen, ref UInt32 entriesread, ref UInt32 totalentries, IntPtr resumehandle);
[DllImport("netapi32.dll")]
public static extern UInt32 NetLocalGroupEnum([MarshalAs(UnmanagedType.LPWStr)] String servername, UInt32 level, ref IntPtr bufptr, UInt32 prefmaxlen, ref UInt32 entriesread, ref UInt32 totalentries, IntPtr resumehandle);
[DllImport("Netapi32.dll")]
public extern static UInt32 NetLocalGroupGetMembers([MarshalAs(UnmanagedType.LPWStr)] String servername, [MarshalAs(UnmanagedType.LPWStr)] String localgroupname, UInt32 level, ref IntPtr bufptr, UInt32 prefmaxlen, ref UInt32 entriesread, ref UInt32 totalentries, IntPtr resumehandle);
}
API 允许您获取有关用户的各种信息。如果你只想要名字,你可以使用这个函数:
IEnumerable<String> GetUserNames() {
var buffer = IntPtr.Zero;
try {
UInt32 entriesRead = 0;
UInt32 totalEntries = 0;
var result = NativeMethods.NetUserEnum(null, 0, 0, ref buffer, UInt32.MaxValue, ref entriesRead, ref totalEntries, IntPtr.Zero);
if (result != 0)
throw new Win32Exception((Int32) result);
var userNames = Enumerable
.Range(0, (Int32) entriesRead)
.Select(
i => {
var userInfo = Marshal.ReadIntPtr(buffer, i*IntPtr.Size);
var userName = Marshal.PtrToStringAuto(userInfo);
return userName;
}
)
.ToList();
return userNames;
}
finally {
NativeMethods.NetApiBufferFree(buffer);
}
}
LINQ 语句用于"parse" 包含USER_INFO_0
结构的缓冲区。如果您要查询其他信息,则必须进行更详细的 "parsing".
同样可以获取本地组名:
IEnumerable<String> GetLocalGroupNames() {
var buffer = IntPtr.Zero;
try {
UInt32 entriesRead = 0;
UInt32 totalEntries = 0;
var result = NativeMethods.NetLocalGroupEnum(null, 0, ref buffer, UInt32.MaxValue, ref entriesRead, ref totalEntries, IntPtr.Zero);
if (result != 0)
throw new Win32Exception((Int32) result);
var localGroupNames = Enumerable
.Range(0, (Int32) entriesRead)
.Select(
i => {
var localGroupInfo = Marshal.ReadIntPtr(buffer, i*IntPtr.Size);
var groupName = Marshal.PtrToStringAuto(localGroupInfo);
return groupName;
}
)
.ToList();
return localGroupNames;
}
finally {
NativeMethods.NetApiBufferFree(buffer);
}
}
缓冲区中的结构 LOCALGROUP_INFO_0
与 USER_INFO_0
结构具有相同的布局,因此 "parsing" 代码相同。
最后,这里是如何使用 LOCALGROUP_MEMBERS_INFO_3
结构获取组成员资格:
IEnumerable<String> GetLocalGroupUsers(String localGroupName) {
var buffer = IntPtr.Zero;
try {
UInt32 entriesRead = 0;
UInt32 totalEntries = 0;
var result = NativeMethods.NetLocalGroupGetMembers(null, localGroupName, 3, ref buffer, UInt32.MaxValue, ref entriesRead, ref totalEntries, IntPtr.Zero);
if (result != 0)
throw new Win32Exception((Int32) result);
var userNames = Enumerable
.Range(0, (Int32) entriesRead)
.Select(
i => {
var membersInfo = Marshal.ReadIntPtr(buffer, i*IntPtr.Size);
var userName = Marshal.PtrToStringAuto(membersInfo );
return userName;
}
)
.ToList();
return userNames;
}
finally {
NativeMethods.NetApiBufferFree(buffer);
}
}