PowerShell错误地读取CSV中的数据

baubqpgj  于 2022-11-10  发布在  Shell
关注(0)|答案(2)|浏览(135)

我目前正在编写一个PowerShell脚本,用于从服务器列表上的本地管理员组中远程删除用户。CSV标头是Computer和Name。对于用户(名称)的每个条目,都与服务器(计算机)匹配。
前男友。

Computer,Name
Server1,User1
Server1,User2
Server2,User1

脚本:

$List = Import-CSV C:\temp\LocalAdmin.CSV

$user = $List.Name
$objGroup = $List.Computer

write-host "Removing user" $user "from server" $objGroup "local admin group:" -ForegroundColor Green

Invoke-Command -ComputerName $objGroup -ScriptBlock {Remove-LocalGroupMember -Group "Administrators" -Member $using:user }

write-host "Completed."

当脚本运行时,它在第一次运行时运行得非常好,但随后它逐行运行脚本,以确定有多少行导致它多次尝试删除用户。有人能帮我修正一下这个逻辑吗?这几乎就像是将CSV读取为数组而不是列表。我很感谢你的帮助!

xwbd5t1u

xwbd5t1u1#

我会说:

$List = Import-CSV C:\temp\LocalAdmin.CSV

ForEach ($Item in $list)
{

$user = $Item.Name
$objGroup = $Item.Computer

write-host "Removing user $user from server $objGroup local admin group:" -ForegroundColor Green

Invoke-Command -ComputerName $objGroup -ScriptBlock {Remove-LocalGroupMember -Group "Administrators" -Member $user }
}

write-host "Completed."

没有经过测试,但这应该是您的起点。

hfyxw5xn

hfyxw5xn2#

至于你尝试了什么
假设$List包含对象的数组,每个元素包含一个表示CSV文件行的对象,$List.Name$List.Computer类似地返回数组的属性(列)值,这由PowerShell的member-access enumeration提供
因此,$using:user指的是所有用户名的数组跨所有服务器
虽然Remove-LocalGroupMember-Member参数接受数组,但您的方法有两个问题

  • 至少假设您将冒着从某些服务器上删除不应该的用户的风险,或者您将遇到给定服务器上不存在的用户(尽管您可以使用-ErrorAction Ignore忽略这一点)。
    由于给定的服务器名称可能在CSV中出现*多次**,因此从第二次调用该服务器开始,目标用户就已经被删除了--这就是您看到的问题。

TheStingPilot's helpful answer提供了一个有效的解决方案:逐个循环表示CSV行的对象,并为每个目标服务器调用Invoke-Command,手边只有用户名。
这种方法的缺点是,当您将多个计算机名传递给Invoke-Command-Computer参数(默认情况下,一次最多可并行定位32台计算机;您可以使用以下命令修改该数字)时,您会放弃并行执行的好处,这取决于目标计算机的数量
-ThrottleLimit)。
避免对给定服务器的多次调用,同时保留并行执行的好处

  • 从将服务器名称Map到用户名的CSV输入构建hashtable
  • 像您尝试的那样,将该哈希表传递给单个Invoke-Command调用,并让每台远程计算机在其中查找相关用户名并对其执行操作。

# Read the CSV file and create a hashtable (map) that

# maps server (computer) names to usernames to remove.

$serverUserMap = [ordered] @{}
Import-CSV C:\temp\LocalAdmin.CSV | 
  ForEach-Object {
    [array] $serverUserMap[$_.Computer] = $serverUserMap[$_.Computer] + $_.Name
  }

# * $serverUserMap.Keys now contains all unique server names,

# which can be passed to -ComputerName

# * Inside the script block, accessing the hashtable with the local

# computer name as the key returns only the relevant user(s).

Invoke-Command -ComputerName $serverUserMap.Keys -ScriptBlock {
  Remove-LocalGroupMember -Group "Administrators" -Member ($using:serverUserMap)[$env:COMPUTERNAME]
}

相关问题