Im working on a script that cleanup old user account and some data from computers. I would like to run the script on 5 computers at one time from the attached list of PCs. Is it possible?
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string]$host_path = 'Host path'
)
$computer = Get-Content "$host_path"
foreach ($computer in $computer){
Invoke-Command -ComputerName $computer -ScriptBlock { Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-30))}| Remove-WmiObject }
Invoke-Command -ComputerName $computer -ScriptBlock { Remove-Item -Path C:\Windows\ccmcache\* -Confirm:$false -Force -Recurse -Debug }
Invoke-Command -ComputerName $computer -ScriptBlock { Remove-Item -Path C:\ProgramData\1E\NomadBranch\* -Confirm:$false -Force -Recurse -Debug }
}
```
CodePudding user response:
You can pass multiple computer names to Invoke-Command
at once to achieve this:
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string]$host_path = 'Host path'
)
$computerNames = Get-Content $host_path
Invoke-Command -ComputerName $computerNames -ScriptBlock {
Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-30))}| Remove-WmiObject
Remove-Item -Path C:\Windows\ccmcache\* -Confirm:$false -Force -Recurse -Debug
Remove-Item -Path C:\ProgramData\1E\NomadBranch\* -Confirm:$false -Force -Recurse -Debug
}
If you want to "chunk" the list of computer names into batches on N machines at a time, you can do it like this:
$computerNames = Get-Content $host_path
$batchSize = 5
while($computerNames.Count -gt 0){
# Pull the first N names from the list
$nextBatch = @($computerNames |Select -First $batchSize)
# Then overwrite the list with any elements _after_ the first N names
$computerNames = @($computerNames |Select -Skip $batchSize)
Write-Host "Executing remote command against $($nextBatch.Count) computers: [$($nextBatch.ForEach({"'$_'"}) -join ', ')]"
# Invoke remoting command against the batch of computer names
Invoke-Command -ComputerName $nextBatch -ScriptBlock {
Get-WMIObject -class Win32_UserProfile | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-30))}| Remove-WmiObject
Remove-Item -Path C:\Windows\ccmcache\* -Confirm:$false -Force -Recurse -Debug
Remove-Item -Path C:\ProgramData\1E\NomadBranch\* -Confirm:$false -Force -Recurse -Debug
}
}
CodePudding user response:
If you are using PowerShell 7.x, you can do the following.
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string]$host_path = 'Host path'
)
# The default value for ThrottleLimit is 5, but I put it here to show syntax.
# Throttle is the number of concurrent runspaces to use. (ex: do 5 objects at a time)
Get-Content $host_path | Foreach-Object -ThrottleLimit 5 -Parallel -ScriptBlock {
Invoke-Command -ComputerName $_ -ScriptBlock {
Get-WMIObject -class Win32_UserProfile | Where-Object {(!$_.Special) -and ($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-30))}| Remove-WmiObject
Remove-Item -Path C:\Windows\ccmcache\* -Confirm:$false -Force -Recurse -Debug
Remove-Item -Path C:\ProgramData\1E\NomadBranch\* -Confirm:$false -Force -Recurse -Debug
}
}
This will run X loops at a time, X being your -ThrottleLimit
value, which defaults to 5
.
Again, this is only available in PowerShell 7, and not backwards compatible with Windows PowerShell.