【发布时间】:2021-12-09 04:16:06
【问题描述】:
最终,我正在尝试创建一个脚本,该脚本将从远程计算机列表中获取作为域服务帐户运行的所有 Windows 服务,并输出一个包含三列的 csv 文件:服务帐户名称、Windows 服务和主机名。我无法弄清楚如何使用两个数组创建哈希表。我使用 += 仅使用一个键和一个数组就取得了一些成功,但即使这样也有一些问题,我正在阅读这是低效的。
这是使所有 Win 服务在我的本地系统上作为系统运行的修改代码:
$server = $env:COMPUTERNAME
$tgtAcct = 'SYSTEM'
$reportCsv = Join-Path -Path ([Environment]::GetFolderPath("Desktop")) -ChildPath ("report.$(Get-Date -Format `"yyyMMdd_hhmmss`").csv")
$GetServiceAccounts = {
[CmdletBinding()]
param(
$hostname
)
$serviceList = @( Get-WmiObject -Class Win32_Service -ComputerName $hostname -Property Name, StartName, SystemName -ErrorAction Stop )
$serviceList
}
Function Process-CompletedJobs(){
$jobs = Get-Job -State Completed
ForEach ($job in $jobs) {
$data = Receive-Job $job
Remove-Job $job
If ($data.GetType() -eq [System.Object[]]) {
$serviceList = $data | Where-Object { $_.StartName -ne $null -and $_.StartName.ToUpper().Contains($tgtAcct) }
ForEach ($service in $serviceList) {
$account = $service.StartName
$winService = $service.Name
$occurance = $service.SystemName
}
}
}
}
Start-Job -ScriptBlock $GetServiceAccounts -Name "read_$($server)" -ArgumentList $server | Wait-Job > $null
Process-CompletedJobs
这是我尝试过但不起作用的方法:
$server = $env:COMPUTERNAME
$tgtAcct = 'SYSTEM'
$serviceAccounts = @{}
$accountTable = @()
$winSvcTable = @()
$occurTable = @()
$reportCsv = Join-Path -Path ([Environment]::GetFolderPath("Desktop")) -ChildPath ("report.$(Get-Date -Format `"yyyMMdd_hhmmss`").csv")
$GetServiceAccounts = {
[CmdletBinding()]
param(
$hostname
)
$serviceList = @( Get-WmiObject -Class Win32_Service -ComputerName $hostname -Property Name, StartName, SystemName -ErrorAction Stop )
$serviceList
}
Function Process-CompletedJobs(){
$jobs = Get-Job -State Completed
ForEach ($job in $jobs) {
$data = Receive-Job $job
Remove-Job $job
If ($data.GetType() -eq [System.Object[]]) {
$serviceList = $data | Where-Object { $_.StartName -ne $null -and $_.StartName.ToUpper().Contains($tgtAcct) }
ForEach ($service in $serviceList) {
$account = $service.StartName
$winService = $service.Name
$occurance = $service.SystemName
$script:serviceAccounts.Item($account) += $winService
$script:serviceAccounts.Item($account) += $occurance
}
}
}
}
Start-Job -ScriptBlock $GetServiceAccounts -Name "read_$($server)" -ArgumentList $server | Wait-Job > $null
Process-CompletedJobs
ForEach ($serviceAccount in $serviceAccounts.Keys) {
ForEach ($occurance in $serviceAccounts.Item($serviceAccount)) {
ForEach ($winService in $serviceAccounts.Item($serviceAccount)) {
$row = New-Object PSObject
Add-Member -InputObject $row -MemberType NoteProperty -Name "Account" -Value $serviceAccount
Add-Member -InputObject $row -MemberType NoteProperty -Name "Service" -Value $winService
Add-Member -InputObject $row -MemberType NoteProperty -Name "Hostname" -Value $occurance
$accountTable += $row
}
}
}
$accountTable | Export-Csv $reportCsv
我正在尝试修改 Andrea Fortuna 编写的代码,该代码几乎可以满足我的要求,但想将第二列分成两列。同样,如果可能,我也在寻找如何在不使用 += 添加到每个数组的情况下执行此操作。 https://www.andreafortuna.org/2020/03/25/windows-service-accounts-enumeration-using-powershell/
【问题讨论】:
-
我没有按照你期望的输出样子,是
$serviceList | Select-Object StartName,SystemName,Name吗?另外,如果你关心效率,Start-Job绝对不是办法。 -
@SantiagoSquarzon :我要查找的输出是一个包含帐户名、服务名和主机名的表。此外,我确实关心效率,并且一直在寻求学习更好更有效的做事方式。为什么 Start-Job 效率低下,您会怎么做?
标签: arrays powershell hashtable psobject