简体   繁体   English

如何获取本地用户所属的所有本地组

[英]How to get all local groups that a local user is a member of

I want to list all the local groups that a local user is a member of without querying the domain. 我想列出本地用户所属的所有本地组而不查询域。 This has proven especially difficult as all the WMI variants query the domain regardless of any filters you apply. 事实证明,这非常困难,因为所有WMI变体都将查询域,而不管您应用了什么过滤器。 (That is why they take forever and generate hundreds if not thousands of security audit events on the domain.) Obviously all Active Directory commands will also query the domain as they were designed to to exactly that. (这就是为什么它们要花很多时间并在域上生成数百个(即使不是成千上万个)安全审核事件的原因。)显然,所有Active Directory命令也将查询域,因为它们是专门为实现该目的而设计的。

Many thanks to all the people at Pinvoke 非常感谢Pinvoke的所有人

$TypeDefinition=@"
using System;
using System.Runtime.InteropServices;
using System.Collections;

//LG_INCLUDE_INDIRECT=1
namespace Netapi32Wrapper {

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    internal struct LOCALGROUP_USERS_INFO_0 {
        [MarshalAs(UnmanagedType.LPWStr)]
        internal string name;
    }

    public static class api {

        [DllImport("Netapi32.dll", SetLastError = true)]
        public extern static Int64 NetUserGetLocalGroups(
            [MarshalAs(UnmanagedType.LPWStr)] string servername,
            [MarshalAs(UnmanagedType.LPWStr)] string username,
            Int64 level,
            Int64 flags,
            out IntPtr bufptr,
            Int64 prefmaxlen,
            out Int64 entriesread,
            out Int64 totalentries);

        [DllImport("Netapi32.dll", SetLastError = true)]
        public static extern Int64 NetApiBufferFree(IntPtr Buffer);
    }

    public class NetUtilWrapper : IDisposable {

        // Creates a new wrapper for the local machine
        public NetUtilWrapper() { }

        // Disposes of this wrapper
        public void Dispose() { GC.SuppressFinalize(this); }

        public ArrayList GetUserLocalGroups(string ServerName, string Username, Int64 Flags) {

            ArrayList myList = new ArrayList();
            Int64 EntriesRead;
            Int64 TotalEntries;
            IntPtr bufPtr;
            //int ErrorCode;
            //string _ErrorMessage;

            api.NetUserGetLocalGroups(ServerName, Username, 0, Flags, out bufPtr, 1024, out EntriesRead, out TotalEntries);
            //ErrorCode = api.NetUserGetLocalGroups(ServerName,Username,0,Flags,out bufPtr,1024,out EntriesRead, out TotalEntries);
            //if (ErrorCode==0) { _ErrorMessage="Successful"; }
            //else { _ErrorMessage="Username or computer not found"; }

            //if (Flags>1) _ErrorMessage="Flags can only be 0 or 1";

            if (EntriesRead > 0) {
                LOCALGROUP_USERS_INFO_0[] RetGroups = new LOCALGROUP_USERS_INFO_0[EntriesRead];
                IntPtr iter = bufPtr;
                for (Int64 i = 0; i < EntriesRead; i++) {
                    RetGroups[i] = (LOCALGROUP_USERS_INFO_0)Marshal.PtrToStructure(iter, typeof(LOCALGROUP_USERS_INFO_0));
                    iter = (IntPtr)((Int64)iter + (Int64)Marshal.SizeOf(typeof(LOCALGROUP_USERS_INFO_0)));
                    myList.Add(RetGroups[i].name);
                }

                api.NetApiBufferFree(bufPtr);
            }

            return myList;
        } //GetUserLocalGroups

        // Occurs on destruction of the Wrapper
        ~NetUtilWrapper() { Dispose(); }

    } // wrapper class
} // namespace
"@
#Failing to perform the line below will result in "arithmetic overflow" on x64 systems
#Failing to perform the line below will result in a total failure on x86 systems
if ([IntPtr]::Size -eq 4) { $TypeDefinition=$TypeDefinition.Replace("Int64","Int32") }
Add-Type -TypeDefinition $TypeDefinition

function Get-LocalGroupsForLocalUser {
  [CmdletBinding(SupportsShouldProcess=$true)]
  Param([Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [string]$Name)

  Process {
    $User=[ADSI]"WinNT://$env:COMPUTERNAME/$Name,user"
    if ($User.Name -ne $null) {
      $Netapi=new-object Netapi32Wrapper.NetUtilWrapper
      $Netapi.GetUserLocalGroups($null,$Name,0)
    }
    else { Write-Error "ERROR:  User $Name does not exist." }
  }
}

Get-LocalGroupsForLocalUser -Name "admin-person"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM