Listing Windows users and groups in C#
April 16, 2010
This example is borrowed from a newsgroup post, apologies to whoever should take the credit but I lost the original url. It’s a basic console application that prints out access lists and groups lists using WMI for the windows directory.
If you’d rather use the System.DirectoryServices namespace then there is a good example in the roadkill source.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Management; | |
using System.Collections; | |
class Tester | |
{ | |
[Flags] | |
enum Mask : uint | |
{ | |
FILE_READ_DATA = 0x00000001, | |
FILE_WRITE_DATA = 0x00000002, | |
FILE_APPEND_DATA = 0x00000004, | |
FILE_READ_EA = 0x00000008, | |
FILE_WRITE_EA = 0x00000010, | |
FILE_EXECUTE = 0x00000020, | |
FILE_DELETE_CHILD = 0x00000040, | |
FILE_READ_ATTRIBUTES = 0x00000080, | |
FILE_WRITE_ATTRIBUTES = 0x00000100, | |
DELETE = 0x00010000, | |
READ_CONTROL = 0x00020000, | |
WRITE_DAC = 0x00040000, | |
WRITE_OWNER = 0x00080000, | |
SYNCHRONIZE = 0x00100000, | |
ACCESS_SYSTEM_SECURITY = 0x01000000, | |
MAXIMUM_ALLOWED = 0x02000000, | |
GENERIC_ALL = 0x10000000, | |
GENERIC_EXECUTE = 0x20000000, | |
GENERIC_WRITE = 0x40000000, | |
GENERIC_READ = 0x80000000 | |
} | |
public static void Main() | |
{ | |
try | |
{ | |
ManagementObject lfs = new ManagementObject(@"Win32_LogicalFileSecuritySetting.Path='c:\\windows'"); | |
// Dump all trustees (this includes owner) | |
foreach (ManagementBaseObject b in lfs.GetRelated()) | |
Console.WriteLine("Trustees {0} is {1}", b["AccountName"], b["SID"]); | |
// Get the security descriptor for this object | |
ManagementBaseObject outP = lfs.InvokeMethod("GetSecurityDescriptor", null, null); | |
if (((uint)(outP.Properties["ReturnValue"].Value)) == 0) | |
{ | |
ManagementBaseObject Descriptor = ((ManagementBaseObject)(outP.Properties["Descriptor"].Value)); | |
DumpDescriptor(Descriptor); | |
ManagementBaseObject[] DaclObject = ((ManagementBaseObject[])(Descriptor.Properties["Dacl"].Value)); | |
DumpACEs(DaclObject); | |
ManagementBaseObject OwnerObject = ((ManagementBaseObject)(Descriptor.Properties["Owner"].Value)); | |
DumpOwnerProperties(OwnerObject.Properties); // Show owner properies | |
ManagementBaseObject GroupObject = ((ManagementBaseObject)(Descriptor.Properties["Group"].Value)); | |
DumpGroup(GroupObject); | |
ManagementBaseObject[] SaclObject = ((ManagementBaseObject[])(Descriptor.Properties["SACL"].Value)); | |
DumpSacl(SaclObject); | |
} | |
} | |
catch (Exception e) | |
{ | |
Console.WriteLine(e); | |
} | |
Console.ReadLine(); | |
} | |
static void DumpDescriptor(ManagementBaseObject Descriptor) | |
{ | |
/* Win32_SecurityDescriptor | |
ControlFlags | |
DACL | |
Group | |
Owner | |
SACL | |
*/ | |
Console.WriteLine(Descriptor.ClassPath); | |
foreach (PropertyData pd in Descriptor.Properties) | |
Console.WriteLine(pd.Name); | |
} | |
static void DumpACEs(ManagementBaseObject[] DaclObject) | |
{ | |
// ACE masks see: winnt.h | |
string[] filedesc = | |
{ | |
"FILE_READ_DATA", "FILE_WRITE_DATA", "FILE_APPEND_DATA", "FILE_READ_EA", | |
"FILE_WRITE_EA", "FILE_EXECUTE", "FILE_DELETE_CHILD", "FILE_READ_ATTRIBUTES", | |
"FILE_WRITE_ATTRIBUTES", " ", " ", " ", | |
" ", " ", " ", " ", | |
"DELETE ", "READ_CONTROL", "WRITE_DAC", "WRITE_OWNER", | |
"SYNCHRONIZE ", " ", " "," ", | |
"ACCESS_SYSTEM_SECURITY", "MAXIMUM_ALLOWED", " "," ", | |
"GENERIC_ALL", "GENERIC_EXECUTE", "GENERIC_WRITE","GENERIC_READ" | |
}; | |
foreach (ManagementBaseObject mbo in DaclObject) | |
{ | |
Console.WriteLine("-------------------------------------------------"); | |
Console.WriteLine("{0:X} - {1} - {2}", mbo["AccessMask"], mbo["AceFlags"], mbo["AceType"]); | |
// Access allowed/denied ACE | |
if (mbo["AceType"].ToString() == "1") | |
Console.WriteLine("DENIED ACE TYPE"); | |
else | |
Console.WriteLine("ALLOWED ACE TYPE"); | |
// Dump trustees | |
ManagementBaseObject Trustee = ((ManagementBaseObject)(mbo["Trustee"])); | |
Console.WriteLine("Name: {0} - Domain: {1} - SID {2}\n", | |
Trustee.Properties["Name"].Value, | |
Trustee.Properties["Domain"].Value, | |
Trustee.Properties["SIDString"].Value); | |
// Dump ACE mask in readable form | |
UInt32 mask = (UInt32)mbo["AccessMask"]; | |
// using enum formatting (see emumerating the possibilities.doc) | |
Console.WriteLine(System.Enum.Format(typeof(Mask), mask, "g")); | |
} | |
} | |
static void DumpGroup(ManagementBaseObject Groups) | |
{ | |
if (Groups != null) | |
{ | |
Console.WriteLine("======================================="); | |
Console.WriteLine("Group property count : " + Groups.Properties.Count); | |
foreach (PropertyData gd in Groups.Properties) | |
Console.WriteLine(gd.Name + "\t\t " + gd.Value); | |
} | |
else | |
Console.WriteLine("NO GROUPS Properties "); | |
} | |
static void DumpSacl(ManagementBaseObject[] SaclObject) | |
{ | |
if (SaclObject == null) | |
Console.WriteLine("No SACLs"); | |
} | |
static void DumpOwnerProperties(PropertyDataCollection Owner) | |
{ | |
Console.WriteLine("=============== Owner Properties ========================"); | |
Console.WriteLine(); | |
Console.WriteLine("Domain {0} \tName {1}", Owner["Domain"].Value, Owner["Name"].Value); | |
Console.WriteLine("SID \t{0}", Owner["SidString"].Value); | |
} | |
} |
I'm Chris Small, a software engineer working in London. This is my tech blog. Find out more about me via Github, Stackoverflow, Resume