我有一个带并行循环的简单工作流程,但在写出结果时遇到错误。因为写输出是并行的。我收到错误:
The process cannot access the file because it is being used by another process.
这是我的剧本:
workflow Get-ServerServices
{
$srvlst = Get-Content C:\TEMP\srvlst.txt
foreach -parallel ($srv in $srvlst)
{
Get-Service -PSComputerName $srv | Out-File c:\temp\test.txt -Append
}
}
任何想法?
答案 0 :(得分:4)
我建议写出临时文件。您可以执行以下代码:
workflow Get-ServerServices
{
#Get the temp path of the context user
$TempPath = Join-Path -Path $([System.IO.Path]::GetTempPath()) -ChildPath "ServerServices"
New-Item -Path $TempPath -ItemType Directory # and create a new sub directory
$srvlst = Get-Content C:\TEMP\srvlst.txt
foreach -parallel ($srv in $srvlst)
{
$TempFileName = [System.Guid]::NewGuid().Guid + ".txt" #GUID.txt will ensure randomness
$FullTempFilePath = Join-Path -Path $TempPath -ChildPath $TempFileName
Get-Service -PSComputerName $srv | Out-File -Path $FullTempFilePath -Force #Write out to the random file
}
$TempFiles = Get-ChildItem -Path $TempPath
foreach ($TempFile in $TempFiles) {
Get-Content -Path $TempFile.FullName | Out-File C:\temp.txt -Append #concatenate all the files
}
Remove-Item -Path $TempPath -Force -Recurse #clean up
}
基本上你得到临时目录,附加一个新目录,在你的输出中添加一堆名为GUID的文本文件,将它们连成一个,然后删除所有这些文件
答案 1 :(得分:0)
根据变量创建test.txt文件名 - 那么你就没有冲突了。
在流程结束时收集所有单个文件并创建一个包含所有结果的文件 - 然后删除单个文件作为清理的一部分'
答案 2 :(得分:0)
答案 3 :(得分:0)
从 Powershell 6 开始,不再使用带有 Foreach-object 的工作流,参数传递也已更改,请参考下面的示例,看看是否有帮助。
# Default directory variable
$DefaultDir = "C:\temp\sample"
# Log file.
$LogFile = "$($DefaultDir)\Log\Log_$([DateTime]::Now.ToString("yyyyMMdd-HHmmss")).txt"
# Directory where all computers are listed.
$AllComputerFolder = "$($DefaultDir)\ListToCheck\pcs.txt"
# Scan the file that lists all machines to be scanned.
Get-Content $AllComputerFolder | ForEach-Object -Parallel {
# It will only scan for machines that are connected to the network.
$TurnedOn = Test-Connection -BufferSize 8 -Count 1 -ComputerName $($_ -replace "\\", "") -Quiet
# Will scan only for machines that are connected
IF($TurnedOn -eq $True){
# Run your script, notice the new way of passing parameters within Foreach-object: $using:DefaultDir
$Return = ."$using:DefaultDir\Script\script.ps1" $_
# Writes in file the return of the processing of each machine.
Add-Content -Path "$using:LogFile" -Value $Return
}ELSE{
# Writes the return of machines with error to file
Add-Content -Path "$using:LogFile" -Value "$($_) : $([DateTime]::Now.ToString("yyyyMMdd-HHmmss")) : Machine turned-off or out of the network"
}
# Number of simultaneous threads
} -ThrottleLimit 20