通过ADSI查询远程Windows计算机管理员组成员的PowerShell脚本

通过ADSI查询远程Windows计算机管理员组成员的PowerShell脚本

doubao_generated_image_4_20250911_202621.png

阅读原文

建议阅读原文,始终查看最新文档版本,获得最佳阅读体验:《通过ADSI查询远程Windows计算机管理员组成员的PowerShell脚本》

引言

企业环境中,有时候我们希望能利用远程管理协议直接查询到远程Windows计算机中某个本地组(例如Administrators)的成员列表,很多时候我们希望将其集成到脚本中。我在编程时发现了一个问题,如果直接利用get-wmiobject命令查询,会占用大量时间,这是因为命令会遍历整个active directory,如果AD中对象数量很多,有可能要几个小时命令才会执行完成,而且会包含大量无用信息。为了解决此问题,我创建了一个Powershell脚本,此脚本利用的是ADSI(底层使用的DCOM协议),完美实现需求。

当然了,因为我所在的企业对于Windows PC,并没有启用WinRM,如果启用了WinRM,那我的需求就很容易满足了,根本无需特地编写一个脚本。如果企业中的PC,启用了DCOM和wmi,则可以使用本文中的脚本。

github网址

iamtornado/common_powershell_scripts: 超级实用Powershell脚本集合

完整脚本

建议始终查看github上的源代码,始终是最新版本的。网址为:https://github.com/iamtornado/common_powershell_scripts/tree/main/%E9%80%9A%E8%BF%87ADSI%E6%9F%A5%E8%AF%A2%E8%BF%9C%E7%A8%8BWindows%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%AE%A1%E7%90%86%E5%91%98%E7%BB%84%E6%88%90%E5%91%98

通过ADSI查询远程Windows计算机管理员组成员的PowerShell脚本:

# PowerShell 脚本:通过 ADSI 查询远程 Windows 计算机中本地 Administrators 组的所有成员

<#
.SYNOPSIS
    通过 ADSI 查询远程 Windows 计算机中本地 Administrators 组的所有成员。

.DESCRIPTION
    此脚本使用 ADSI (Active Directory Service Interfaces) 连接到指定的远程计算机,
    并列出该计算机上本地 Administrators 组的所有成员。
    它会尝试处理常见的错误,例如远程计算机无法访问或权限不足。

.PARAMETER ComputerName
    要查询的远程 Windows 计算机的名称或 IP 地址。

.EXAMPLE
    .\Get-RemoteAdminMembers_ADSI.ps1 -ComputerName "RemotePC01"
    这将查询名为 "RemotePC01" 的计算机上的 Administrators 组成员。

.EXAMPLE
    .\Get-RemoteAdminMembers_ADSI.ps1 -ComputerName "192.168.1.100"
    这将查询 IP 地址为 "192.168.1.100" 的计算机上的 Administrators 组成员。

.NOTES
    - 运行此脚本的用户需要具备访问远程计算机的权限。
    - ADSI 访问通常通过 DCOM (Distributed Component Object Model) 进行,
      可能需要确保防火墙允许相关流量 (通常是 TCP 135 和动态端口)。
    - 如果遇到 "访问被拒绝" 错误,请确保当前用户具有足够的权限,
      或者尝试使用具有管理员权限的凭据运行 PowerShell。
    - 此方法对于非域环境或工作组环境中的本地组查询同样有效。
#>

param (
    [Parameter(Mandatory=$true, HelpMessage="请输入要查询的远程计算机的名称或 IP 地址。")]
    [string]$ComputerName
)

Write-Host "正在通过 ADSI 查询远程计算机 '$ComputerName' 上的本地 Administrators 组成员..." -ForegroundColor Cyan

try {
    # 检查远程计算机是否可达 (ping)
    if (-not (Test-Connection -ComputerName $ComputerName -Count 1 -ErrorAction SilentlyContinue)) {
        Write-Error "错误:无法连接到远程计算机 '$ComputerName'。请检查网络连接或计算机名称/IP地址是否正确。"
        exit 1
    }

    # 构建 ADSI 路径以连接到远程计算机的本地 Administrators 组
    # "WinNT://" 是 ADSI 提供程序,用于访问本地用户和组,以及域用户和组
    # "$ComputerName/Administrators,group" 指定了目标计算机上的 Administrators 组
    $group = [ADSI]"WinNT://$ComputerName/Administrators,group"

    Write-Host "成功连接到远程计算机 '$ComputerName' 上的 Administrators 组对象。" -ForegroundColor Green

    $members = @()
    foreach ($member in $group.Members()) {
        $memberType = $member.GetType().InvokeMember("Class", 'GetProperty', $null, $member, $null)
        $memberName = $member.GetType().InvokeMember("Name", 'GetProperty', $null, $member, $null)
        $memberPath = $member.GetType().InvokeMember("ADsPath", 'GetProperty', $null, $member, $null)

        # 尝试从 ADsPath 解析 PrincipalSource
        $principalSource = "Unknown"
        if ($memberPath -like "*WinNT://*/") {
            if ($memberPath -like "*WinNT://$ComputerName/*") {
                $principalSource = "Local"
            } else {
                # 尝试提取域或计算机名
                $match = [regex]::Match($memberPath, 'WinNT://([^/]+)/')
                if ($match.Success) {
                    $sourceName = $match.Groups[1].Value
                    if ($sourceName -ne $ComputerName) {
                        $principalSource = "Domain ($sourceName)"
                    } else {
                        $principalSource = "Local" # 再次确认是本地,以防万一
                    }
                }
            }
        }

        $members += [PSCustomObject]@{
            Name          = $memberName
            Type          = $memberType # 例如:User, Group
            PrincipalSource = $principalSource # 尝试判断来源:Local, Domain
            ADsPath       = $memberPath
        }
    }

    if ($members.Count -gt 0) {
        Write-Host "`n远程计算机 '$ComputerName' 上的 Administrators 组成员:" -ForegroundColor Green
        $members | Format-Table -AutoSize
    }
    else {
        Write-Warning "未在远程计算机 '$ComputerName' 上找到 Administrators 组成员,或者无法获取成员列表。"
    }
}
catch [System.UnauthorizedAccessException] {
    Write-Error "错误:访问远程计算机 '$ComputerName' 被拒绝。请确保您有足够的权限。"
    Write-Error "提示:尝试以管理员身份运行 PowerShell,或检查远程计算机上的用户权限。"
}
catch [System.Management.Automation.RuntimeException] {
    Write-Error "错误:无法通过 ADSI 连接到远程计算机 '$ComputerName' 或获取组信息。"
    Write-Error "详细错误信息:$($_.Exception.Message)"
    Write-Error "提示:请确保远程计算机可达,并且当前用户具有远程访问权限。检查防火墙是否阻止 DCOM 流量。"
}
catch {
    Write-Error "发生未知错误:$($_.Exception.Message)"
    Write-Error "详细错误信息:$($_.Exception | Format-List -Force)"
}

Write-Host "`n脚本执行完毕。" -ForegroundColor DarkGreen

关于作者和DreamAI

https://docs.dingtalk.com/i/nodes/Amq4vjg890AlRbA6Td9ZvlpDJ3kdP0wQ?iframeQuery=utm_source=portal&utm_medium=portal_recent

关注微信公众号“AI发烧友”,获取更多IT开发运维实用工具与技巧,还有很多AI技术文档!

梦幻智能logo-01(无水印).png

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值