PowerShell小技巧:通过Powershell定期自动将加域的客户端从 Computers 按规则移动至相应 OU并发送通知至机器人

Posted 微风ATBJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PowerShell小技巧:通过Powershell定期自动将加域的客户端从 Computers 按规则移动至相应 OU并发送通知至机器人相关的知识,希望对你有一定的参考价值。

前言

前面我有写过一个场景:定期检查域环境中新加入域客户端,然后告知管理员将其从Computers移至相应的客户端OU

本篇将继续引用该场景,并实现:获取新加入域的客户端按指定计算机命名规则,自动移动至相应 OU 中


环境介绍

这里有个前提条件,就是你所在的环境,必须是有这标准化的计算机命名规则,在此基础之上,才能按固定的规则去实现自动匹配对应 OU 并移动。

我先介绍下我的环境:

  • 用户计算机命名规则:城市简称+固定资产系统的资产编号(如:BJ2022034234,SH2021042034,GZ2020053751....);
  • 计算机 OU 命名规则:我的客户端 OU 结构类似于: Managed Clients\\xxCompurers


脚本编写

我将脚本分为几个部分:

  1. 获取默认Computers里的所有计算机名单;
  2. 基于计算机名,将其移动到对应的 OU;(如:BJ2022034234BJComputers;SH2021042034SHComputers
    注:这里也有特例,如我的环境中服务器、以及未按计算机命名规则命名的客户端,不能或者不需要自动移动的,需要列出并提示
  3. 完成执行后,通过企业微信机器人发送执行结果;

脚本一、获取 Computers 计算机成员

#OU List
$HashTable = @
    BJ = "BJComputers"
    CD = "CDComputers"
    CQ = "CQComputers"
    GZ = "GZComputers"
    HZ = "HZComputers"
    NJ = "NJComputers"
    QD = "QDComputers"
    SH = "SHComputers"
    SZ = "SZComputers"
    WH = "WHComputers"


Import-Module ActiveDirectory
#Filter
$FilterString = New-Object System.Collections.ArrayList
$Filter = $HashTable.keys | Foreach-Object 
    $FilterString.Add(("Name -Like 0*" -f $_))

$Filter = "(0) -and Enabled -eq true" -f ($FilterString -join " -or ")

#Computers
$Computersbef = Get-ADComputer -SearchBase "CN=Computers,DC=ITPro,DC=cc" -Filter Name -ne "YHDMFILE03" -and Enabled -eq "True" #执行之前的所有 Computers 成员
$PCCountbef = ($Computersbef.Name).count 

$Computers = Get-ADComputer -SearchBase "CN=Computers,DC=ITPro,DC=cc" -Filter $Filter #只符合客户端命名规则的计算机
$PCCount = ($Computers.Name).count

脚本二、将计算机移动至对应 OU

#数组用于保存日志信息
$Logs = New-Object System.Collections.ArrayList
#Move
$Computers | ForEach-Object 
    $Computer = $_
    #echo $Computer.Name
    $TargetOUName = "OU=0" -f $HashTable[$($Computer.Name.Substring(0, 2))]
    $Targetou = "OU=0,OU=Managed Clients,DC=ITPro,DC=cc" -f $HashTable[$($Computer.Name.Substring(0, 2))]
    Move-ADObject -Identity $Computer.ObjectGUID -TargetPath $Targetou -ErrorAction SilentlyContinue -ErrorVariable MoveToOU

    #Log
    $Log = "Moved 0 to 1 `n" -f $Computer.Name, $TargetOUName
    [void]$Logs.Add($Log)

$Computersaft = Get-ADComputer -SearchBase "CN=Computers,DC=ITPro,DC=cc" -Filter Name -ne "YHDMFILE03" -and Enabled -eq "True" #处理完标准命名的计算机后,再次检查Computers的计算机成员
$PCCountaft = ($Computersaft.Name).count # 完成自动移动之后的数量
$SPPCNames = $Computersaft.Name

脚本三、将操作记录通过企业微信机器人发送

$body = "
    `"msgtype`":`"markdown`",
    `"markdown`":
    `"content`":`"$content`",
    `"mentioned_list`":[`"jasonhuang`"]  #@成员只能在 text格式下生效,对 MarkDown 不生效。
    
"

$chinese = [System.Text.Encoding]::UTF8.GetBytes($body) #这里是解决中文编码问题的即发送中文消息时候使用。

if ($PCCountbef -gt 0) 

    Invoke-RestMethod https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=x -ContentType "application/jsonxxxxxxxxx" -Method Post -Body $chinese

else 
    exit

逻辑关系

这里由于环境复杂我做了几个判断语句,以便于实现:

  1. 假如有4 台新加域计算机,2 台自动移动完成,2 台移动失败。得告知管理员自动完成的计算机信息,以及未能自动完成的成员信息,并提示相关人员及时处理。并且通过MarkDown的格式将成功失败的操作以不同字体颜色体现;
  2. 假如4 台新加域计算机均自动移动完成,则通过MarkDown的格式告知正常完成,并列出计算机清单;
  3. 假如 4 台均执行失败,则通过MarkDown的格式发送提醒格式的消息,并列出计算机清单;
  4. 假如计划任务执行失败,则将执行该脚本时的报错首行发送给管理员;

最终版

#OU List
Import-Module ActiveDirectory
$HashTable = @
    BJ = "BJComputers"
    CD = "CDComputers"
    CQ = "CQComputers"
    GZ = "GZComputers"
    HZ = "HZComputers"
    NJ = "NJComputers"
    QD = "QDComputers"
    SH = "SHComputers"
    SZ = "SZComputers"
    WH = "WHComputers"


#Filter
$FilterString = New-Object System.Collections.ArrayList
$Filter = $HashTable.keys | Foreach-Object 
    $FilterString.Add(("Name -Like 0*" -f $_))

$Filter = "(0) -and Enabled -eq true" -f ($FilterString -join " -or ")

#Computers
$Computersbef = Get-ADComputer -SearchBase "CN=Computers,DC=ITPro,DC=cc" -Filter Name -ne "WinSRV-FILE03" -and Enabled -eq "True" #执行之前的所有 Computers 成员,并且排除掉指定的 Server
$PCCountbef = ($Computersbef.Name).count 

$Computers = Get-ADComputer -SearchBase "CN=Computers,DC=ITPro,DC=cc" -Filter $Filter #只符合客户端命名规则的计算机
$PCCount = ($Computers.Name).count

#数组用于保存日志信息
$Logs = New-Object System.Collections.ArrayList
#Move
$Computers | ForEach-Object 
    $Computer = $_
    #echo $Computer.Name
    $TargetOUName = "OU=0" -f $HashTable[$($Computer.Name.Substring(0, 2))]
    $Targetou = "OU=0,OU=Managed Clients,DC=ITPro,DC=cc" -f $HashTable[$($Computer.Name.Substring(0, 2))]
    Move-ADObject -Identity $Computer.ObjectGUID -TargetPath $Targetou -ErrorAction SilentlyContinue -ErrorVariable MoveToOU

    #Log
    $Log = "Moved 0 to 1 `n" -f $Computer.Name, $TargetOUName
    [void]$Logs.Add($Log)

#$content = echo "一共有"$PCCount"台计算机加入域,并已自动完成移动至相关OU,清单如下:`n "$Logs""
$Computersaft = Get-ADComputer -SearchBase "CN=Computers,DC=ITPro,DC=cc" -Filter Name -ne "YHDMFILE03" -and Enabled -eq "True" #处理完标准命名的计算机后,再次检查Computers的计算机成员
$PCCountaft = ($Computersaft.Name).count # 完成自动移动之后的数量
$SPPCNames = $Computersaft.Name
# $TotalCount = $PCCountaft + $PCCount

if (($PCCountaft -gt 0) -and ($PCCountbef -gt $PCCountaft)) 
    $content = @"
新增域计算机<font color=\\"warning\\"> $PCCountbef 台</font>,需手动处理:
        >需手动处理数量:<font color=\\"warning\\"> $PCCountaft 台</font>
        >未自动处理原因:<font color=\\"warning\\">非标准计算机命名或为服务器</font>
        >需手动处理计算机名:<font color=\\"comment\\"> $SPPCNames </font>
        >脚本完成自动处理:<font color=\\"info\\"> $PCCount 台</font>,记录如下:
        >$logs
"@

elseif (($PCCountaft -gt 0) -and ($PCCount -eq 0)) 
    $content = @"
新增域计算机<font color=\\"warning\\"> $PCCountaft 台</font>,需要手动处理:
        >需手动处理数量:<font color=\\"warning\\"> $PCCountaft 台</font>
        >未自动处理原因:<font color=\\"warning\\">非标准计算机命名或为服务器</font>
        >需手动处理计算机名:<font color=\\"warning\\"> $SPPCNames </font>
"@

elseif ($PCCountaft -eq 0 -and ($PCCountbef -gt 0)) 
    $content = @"
新增域计算机<font color=\\"info\\"> $PCCount 台</font>,已自动完成移动至相关OU。
        >处理记录如下:<font color=\\"comment\\"> </font>
        >$logs
"@


if ($MovetoOU) 
    $MovetoOULogs = ($MovetoOU.Message -split \\n)[0]
    $content = @"
## <font color=\\"warning\\">计划任务执行失败</font>
        >失败原因:<font color=\\"warning\\"> $MovetoOULogs </font>
"@


$body = "
    `"msgtype`":`"markdown`",
    `"markdown`":
    `"content`":`"$content`",
    `"mentioned_list`":[`"jasonhuang`"]
    
"

$chinese = [System.Text.Encoding]::UTF8.GetBytes($body) #这里是解决中文编码问题的即发送中文消息时候使用。

if ($PCCountbef -gt 0) 

    Invoke-RestMethod https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxx -ContentType "application/json" -Method Post -Body $chinese

else 
    exit

效果截图:

特别鸣谢: 九叔、彪哥、Summpot 三位大佬的热心帮助(排名不分先后)


以上是关于PowerShell小技巧:通过Powershell定期自动将加域的客户端从 Computers 按规则移动至相应 OU并发送通知至机器人的主要内容,如果未能解决你的问题,请参考以下文章

如何在不卸载powershell的情况下,有效禁用/启用powershel

PowerShell小技巧:通过 PowerShell实现日志关键字分析

PowerShell小技巧:通过Powershell 发送消息给企业微信机器人

内网渗透之Windows反弹shell

PowerShell小技巧:通过Powershell定期自动将加域的客户端从 Computers 按规则移动至相应 OU并发送通知至机器人

Win10小技巧:如何将在此处打开命令改为CMD或Powershell?