从运行PowerShell v5 April预览的计算机上运行:
Test-Connection
向所有人提出并注意到总体响应Get-Printers
cmdlet,该cmdlet将无法在PowerShell v2上运行,并输出到与本地计算机上下载结果相同的文件夹中的文件我有一个工作脚本 - 它非常慢,我想学习和改进它,使它更快,更优雅。我发现很难写出来并解释哈哈。如果你试图解决这个问题,你会用什么方式解决它?
开始制定更好的方法:
获取服务器列表并存储在变量中即可。
$2003s = Get-ADComputer -Filter {OperatingSystem -eq "Windows server 2003"} -Properties OperatingSystem
获得总数是可以的。
$Total2003s = $2003s.count
现在可能有一些不再存在的2003服务器没有从AD中删除,所以让它们全部ping。
$Responsive2003s = Test-Connection $2003s.dnshostname -Delay 1 -Count 1 -ErrorAction SilentlyContinue
如果$ 2003s中有300个对象而一半没有响应,则需要永久。
Measure-Command {Test-Connection $2003s.dnshostname -Delay 1 -Count 1 -ErrorAction SilentlyContinue}
7分钟......
所以我想,嘿,让我们制作一个Powershell工作流程,以便我可以使用foreach -parallel
。如果我编写一个快速工作流程来从AD和foreach Test-Connection
获取服务器:
Measure-Command {Workflow-Testconnection}
27秒....
仅仅让这部分单独工作可以节省时间,但是我无法确定构建我的脚本/功能/工作流程的方式或者哪种方法最适合。
我想出了两个障碍。
在ping服务器的小工作流程中,我无法(计算出如何)将结果存储在变量中以查看总数(使用$variable = Test-Connection ...
或Test-Connection | New-Variable
,因此,如果我看不到广告中的服务器与响应的服务器之间存在差异,那么ping它们是没有意义的。我可以使用
$2003sDnsHostname | foreach {
Get-Printer -ThrottleLimit 500 -ErrorAction SilentlyContinue -ComputerName $_ |
Sort-Object -Property Portname |
FT -AutoSize | Out-File -FilePath "D:\$($_) - Printers.txt"
}
但速度很慢,如果我使用更快的工作流程,我就无法在Format-Table
的输出上使用Get-Printers
。
我尝试使用foreach -parallel
在所需位置使整个工作流成为工作流程,但因为我有一个$creds = Get-Crendential
与我的Invoke-Command -Credential $Creds
一起工作,所以工作流程赢了“甚至加载。
似乎对于我的脚本的每一步我想要的每一个好处,都有一个使得它不值得做的交易破坏者,但我确信有一种方法:)
整个工作但很慢的事情,编辑删除敏感的东西等只是为了得到这个概念。它可以被制作成具有参数和详细输出等的函数,但这也是一个待办事项。我想看看它是否可以先加速。
$SVRAcctCreds = Get-Credential
#Enable the ActiveDirectory module as first time users might not have it already on their computer, and it doesn't hurt to enable it again if it's already there
Enable-WindowsOptionalFeature -Online -FeatureName RemoteServerAdministrationTools-Roles-AD-Powershell -NoRestart
$2003s = Get-ADComputer -Filter {OperatingSystem -eq "Windows server 2003"} -Properties operatingsystem
$2003sDnsHostname = $2003s.dnshostname
$Total = $2003s.count
$Responsive2003s = Test-Connection $2003s.dnshostname -Delay 1 -Count 1 -ErrorAction SilentlyContinue
$TotalResponsive2003s = $Responsive2003s.count
Invoke-Command -ComputerName ($2003s.dnshostname) -Credential $SVRAcctCreds -ThrottleLimit 100 -ErrorAction SilentlyContinue -ScriptBlock {
#Make folder for output
mkdir Z:\2003Migration | Out-Null
#Serial number, model number, output to file
Get-WmiObject win32_computersystem |
Select-Object Manufacturer, Model | Format-List |
Out-File -Append -FilePath Z:\2003Migration\"$env:SiteCode $env:SiteName"_MigrationData.txt
Get-WmiObject win32_bios | Select-Object SerialNumber |
Out-File -Append -FilePath Z:\2003Migration\"$env:SiteCode $env:SiteName"_MigrationData.txt
Systeminfo | Select-String "Install Date:" |
Out-File -Append -FilePath Z:\2003Migration\"$env:SiteCode $env:SiteName"_MigrationData.txt
}
##### Download Gathered data from servers
$2003s | ForEach-Object {
New-PSDrive -ErrorAction SilentlyContinue -PSProvider FileSystem -Name $_.name -Credential $SVRAcctCreds -Root "\\$($_.dnshostname)\z$\2003Migration"
} | Out-Null
Get-PSDrive | where name -Like "SVR*" | foreach {
Copy-Item "$($_.Name):" -Recurse -Destination d:\ -ErrorAction SilentlyContinue
}
$TotalPSDrives = (Get-PSDrive | where name -Like "SVR*").count
# Report other information
"Total number of servers on Windows Server 2003 in AD, matching by OperatingSystem " | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"
"$Total" | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"
"Total Number of servers that responded to a ping command" | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"
"$TotalResponsive2003s" | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"
"Total Number of servers that ran the commands and returned data" | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"
"Total Number of servers that ran the commands and returned data downloaded to D:\2003Migration"
"$TotalPSDrives " | Out-File -Append -FilePath "d:\2003Migration\_Total Server counts.txt"
"$TotalPSDrives "
"Mismatch means server could be pinged but could not run a powershell session to invoke commands, possible hard drive full? Powershell remoting not enabled?"
####Printers
# Didn't have enough time to work out how to only ask responsive servers the printers, so ask all, takes longer, then clean up empty files
$2003sDnsHostname | foreach {
Get-Printer -ThrottleLimit 500 -ErrorAction SilentlyContinue -ComputerName $_ |
Sort-Object -Property Portname | FT -AutoSize |
Out-File -FilePath "D:\2003Migration\$($_) - Printers.txt"
}
Get-ChildItem D:\2003Migration | where Length -EQ 0 | Remove-Item
#clean up text files left on server
Invoke-Command -ComputerName ($2003s.dnshostname) -Credential $SVRAcctCreds -ThrottleLimit 100 -ErrorAction SilentlyContinue -ScriptBlock {
Remove-Item "Z:\2003migration" -Recurse -ErrorAction SilentlyContinue
}
答案 0 :(得分:2)
我总是发现工作流程有点棘手,因为它们与“常规”PowerShell略有不同。您可以使用jobs来减少困难。这样的事情会给你一个列表,其中只包含那些响应$Responsive2003s = $2003s | % {
Start-Job -ScriptBlock {
Param($name, $address)
if (Test-Connection $address -Delay 1 -Count 1 -EA SilentlyContinue) {
$name
}
} -ArgumentList $_.Name, $_.IPv4Address
} | Wait-Job | Receive-Job
的服务器的名称:
{{1}}