netuserenum (netapi32)
Last changed: -108.168.5.220

.
Summary
The NetUserEnum function provides information about all user accounts on a server.

C# Signature:

    [DllImport("Netapi32.dll")]
       extern static int NetUserEnum([MarshalAs(UnmanagedType.LPWStr)]
       string servername,
       int level,
       int filter,
       out IntPtr bufptr,
       int prefmaxlen,
       out int entriesread,
       out int totalentries,
       out int resume_handle);

VB Signature:

    Public Declare Function NetUserEnum Lib "Netapi32.dll" ( _
    <MarshalAs(UnmanagedType.LPWStr)> ByVal servername As String, _
    ByVal level As Integer, _
    ByVal filter As Integer, _
    ByRef bufptr As IntPtr, _
    ByVal prefmaxlen As Integer, _
    ByRef entriesread As Integer, _
    ByRef totalentries As Integer, _
    ByRef resume_handle As Integer) As Integer

User-Defined Types:

    // Passing -1 as prefmaxlen makes the system allocate the buffer.
    // LMCONS.h
    const int MAX_PREFERRED_LENGTH = -1;

    // You'll need these for the return values
    // LMERR.h
    const int NERR_Success = 0;       /* Success */
    const int NERR_BASE = 2100;
    const int NERR_InvalidComputer = (NERR_BASE+251); /* This computer name is invalid. */

    // WINERROR.h
    const int ERROR_ACCESS_DENIED = 5;
    const int ERROR_MORE_DATA = 234;    

    // Passing this for 'filter'
    // LMACCESS.h
    const int FILTER_TEMP_DUPLICATE_ACCOUNT = 0x0001;
    const int FILTER_NORMAL_ACCOUNT = 0x0002;
    const int FILTER_INTERDOMAIN_TRUST_ACCOUNT = 0x0008;
    const int FILTER_WORKSTATION_TRUST_ACCOUNT = 0x0010;
    const int FILTER_SERVER_TRUST_ACCOUNT = 0x0020;

Notes:

[2005-06-15] VB sample contributed by Graeme Grant

[2006-03-09] VB sample fixed by Jaime Smith (can't cast Int32 to IntPtr, users and Users cannot both be used in the same scope in VB)

[2009-05-20] C# sample fixed by IEBasara

Tips & Tricks:

Please add some!

Sample Code:

VB

    //Do not use this code it is severely broken
    //You must check for more data

    Dim _users As New ArrayList
    Dim EntriesRead As Integer
    Dim TotalEntries As Integer
    Dim [Resume] As Integer
    Dim bufPtr As IntPtr

    NetUserEnum(server, 0, 2, bufPtr, -1, EntriesRead, TotalEntries, [Resume])
    If EntriesRead > 0 Then
        Dim Users(EntriesRead) As USER_INFO_0
        Dim iter As IntPtr = bufPtr
        Dim i As Integer
        For i = 0 To EntriesRead - 1
        Users(i) = CType(Marshal.PtrToStructure(iter, GetType(USER_INFO_0)), USER_INFO_0)
        iter = New IntPtr(iter.ToInt32 + Marshal.SizeOf(GetType(USER_INFO_0)))

        _users.Add(Users(i).Username)
        Next i
        NetApiBufferFree(bufPtr)
    End If

[C#]

    //Do not use this code it is severely broken
    //You must check for more data even if you have MAX_PREFERRED_LENGTH

    ArrayList users = new ArrayList();
    int EntriesRead;
    int TotalEntries;
    int Resume;
    IntPtr bufPtr;

    NetUserEnum(server, 0, FILTER_NORMAL_ACCOUNT, out bufPtr, MAX_PREFERRED_LENGTH, out EntriesRead, out TotalEntries, out Resume);
    if(EntriesRead> 0)
    {
        IntPtr iter = bufPtr;
        for(int i=0; i < EntriesRead; i++)
        {
            USER_INFO_0 anUser = (USER_INFO_0)Marshal.PtrToStructure(iter, typeof(USER_INFO_0));
            iter = iter + Marshal.SizeOf(typeof(USER_INFO_0));

            users.Add(anUser.name);
        }
        NetApiBufferFree(bufPtr);
    }

Alternative Managed API:

Do you know one? Please contribute it!

using System.DirectoryServices; //System.DirectoryServices

        DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://" + Environment.MachineName);

        foreach (DirectoryEntry child in directoryEntry.Children) {
        if (child.SchemaClassName == "User") {
            PropertyCollection props = child.Properties;
            userNames += child.Name + "{" + child.Guid + "}" + Environment.NewLine;

        }
        }

Documentation
NetUserEnum on MSDN