Powershell - run script on multiple computers simultaneously - powershell

I'm 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? If so, how can it be done?
[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 }
}

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
}
}

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.

Related

How to find PST files on remote computers using Powershell script

I need some help. I cant’t find what’s wrong with my PowerShell script.
The goal is quite simple. I have to find (.*pst)-files on the users profile on domain computers in the network. Location to search is “C:\Users\”.
List of the PC names where exported to listcomputer.txt. The trouble is the script run with no errors and no message at all.
$computers = Get-Content c:\temp\listcomputer.txt
$filePath = "C:\Users\"
foreach($computer in $computers)
{
if(Test-Connection -ComputerName $computer -Quiet)
{
Invoke-Command -ComputerName $computer -ScriptBlock
{Get-ChildItem -Path $filePath -Recurse -Include '*.pst, *.ost'} }}
First of all I’ve to check connectivity to hosts by Test-Connection cmdlet.
Separately each of the command run successfully. I've tried it.
For example: Test-Connection -ComputerName $computer
runs with “true” result and it’s OK.
Also
Invoke-Command -ComputerName $computer -ScriptBlock {Get-ChildItem -Path $filePath -Recurse -Include '*.pst'} The result is displayed data with information about files were find in folders.
But all together run with no visible result in the PowerShell console console view result
Regards!
.pst can be located anywhere, even other drives, or attached storage. You are only looking for C:\.
So maybe this refactor to hit all potential connected drives.:
Get-Content -Path 'c:\temp\listcomputer.txt' |
ForEach-Object {
if(Test-Connection -ComputerName $PSItem -Quiet)
{
Invoke-Command -ComputerName $PSItem -ScriptBlock {
(Get-CimInstance -ClassName Win32_LogicalDisk).DeviceID |
ForEach-Object {
If ($PSItem -eq 'C:')
{Get-ChildItem -Path "$PSItem\Users" -Recurse -Include '*.pst, *.ost'}
Else {Get-ChildItem -Path $PSItem -Recurse -Include '*.pst, *.ost'}
}
}
}
}

Check if process is running on multiple remote computers and copy a file if process is NOT running, keep list of those which succeeded

I need to copy a file to multiple computers, but can only do so if a particular app (process) is not running.
I know I can use Invoke-Command to run a script (scriptblock) on a list of machines.
But how can I check if process is running on the machine and then only copy file if it is not running.
So that at the end of running against a load of computers I can easily see those which succeeded e.g. process was not running and file was copied
Thanks
UPDATE:
I am assuming something like this will do the first bits of what I am asking, but how to visually show or log success or failure so I know which computers have been done - doesn't need to be anything fancy, even if simply a variable that holds computername of those where process wasn't running and file was copied okay
Invoke-Command -ComputerName PC1, PC2, PC3 -ScriptBlock {
If ((Get-process -Name notepad -ea SilentlyContinue) -eq $Null){
Copy-Item -Path "\\server01\c$\test\file.txt" -Destination "C:\test\file.txt" -Force
}
}
$Procs = invoke-command -ComputerName PC1 { get-process | Select Name }
If($Procs -notmatch "Notepad"){ Copy-Item -Path "\\server01\c$\test\file.txt" -Destination "\\$PC1\c$\test\" -Force}
edited:
$computers = #("PC1","PC2","PC3")
Foreach($computer in $computers){
$Procs = invoke-command -ComputerName $computer { Get-Process Notepad -ErrorAction SilentlyContinue}
If(!$Procs){"$Computer - not running Notepad"; Copy-Item -Path "\\server01\c$\test\file.txt" -Destination "\\$computer\c$\test\" -Force}
elseif($Procs){"$Computer - is running Notepad"}
}
Edit2(for clean output):
$computers = #("PC1","PC2","PC3")
$RNote = #()
$NNote = #()
$off = #()
Foreach($computer in $computers){
$TestC = Test-Connection -ComputerName $computer -Count 1
If(!($TestC)){$off += $computer} Else{
$Procs = invoke-command -ComputerName $computer { Get-Process Notepad -ErrorAction SilentlyContinue}
If(!$Procs){$NNote +=$computer; Copy-Item -Path "\\server01\c$\test\file.txt" -Destination "\\$computer\c$\test\" -Force}
elseif($Procs){$RNote +=$computer}
}
}
$leng =[array]$RNote.count,$NNote.Count,$off.count
[int]$max = ($leng | measure -Maximum).Maximum
for($i=0; $i -lt $max;$i++){
[pscustomobject]#{
"Notepad On" = $(if ($RNote[$i]){$RNote[$i]})
"Notepad Off" = $(if ($NNote[$i]){$NNote[$i]})
"Offline " = $(if ($off[$i]){$off[$i]})
}
}
I think this is what you're looking for or at least close:
$Results = #()
$Results +=
Invoke-Command -ComputerName DellXPS137000, DellXPS8920 -ScriptBlock {
$GPArgs = #{Name = "Notepad++"
ErrorAction = "SilentlyContinue"}
If ( $Null -ne (get-process #GPArgs )) {
#Process your copy here
$Status = "Success"
}
Else {$Status = "Failed"}
$Machine =
(Get-CimInstance -ClassName 'Win32_OperatingSystem').CSName
Return ,"$Machine : $Status"
}
Value of $Results:
PS> $results
DELLXPS137000 : Success
DELLXPS8920 : Failed
HTH

Stopping & Restarting Services Remotely Using Set-Service

I've got a list of 10-15 services that I routinely need to restart on 6 servers. I have a script that calls a list of services, then calls a list of the servers, and then stops all the services:
$Services = Get-Content -Path "C:\Powershell\Services.txt"
$Machines = Get-Content -Path "C:\Powershell\Machines.txt"
Get-Service -Name $Services -ComputerName $Machines | Set-Service -Status Stopped
I then have another separate script to start them up again:
$Services = Get-Content -Path "C:\Powershell\Services.txt"
$Machines = Get-Content -Path "C:\Powershell\Machines.txt"
Get-Service -Name $Services -ComputerName $Machines | Set-Service -Status Running
I've checked around and can't seem to find a way of putting this into a single script. As I understand, Set-Service only has the ability to Stop, Start & Pause services, not restart them at the same time.
Any ideas? I might be missing something completely obvious.
To restart services simply use Restart-Service:
$Services = Get-Content -Path "C:\Powershell\Services.txt"
$Machines = Get-Content -Path "C:\Powershell\Machines.txt"
Get-Service -Name $Services -ComputerName $Machines | Restart-Service
Since according to the comments PowerShell v6 has removed support for remote access from the *-Service cmdlets you need to resort to Invoke-Command for remote execution when running v6 or newer, like this:
Invoke-Command -Computer $Machines -ScriptBlock {
Get-Service -Name $using:Services -ErrorAction SilentlyContinue |
Restart-Service
}
or like this:
Invoke-Command -Computer $Machines -ScriptBlock {
Restart-Service $using:Services -ErrorAction SilentlyContinue
}
Another option would be WMI:
$fltr = ($Services | ForEach-Object { 'Name="{0}"' -f $_ }) -join ' or '
Get-WmiObject Win32_Service -Computer $Machines -Filter $fltr | ForEach-Object {
$_.StopService()
$_.StartService()
}
I am with Ansgar, this should work
$Services = Get-Content -Path "C:\Powershell\Services.txt"
$Machines = Get-Content -Path "C:\Powershell\Machines.txt"
foreach ($service in $services){
foreach ($computer in $Machines){
Invoke-Command -ComputerName $computer -ScriptBlock{
Restart-Service -DisplayName $service}
}
}
it is a little messy but should give you a starting point
Sorry I forgot to take time to explain what is going on, so you import each of your txt docs and then it will process for each service and each computer and restart the services.
You can try this single liner command:
Get-Content .\services.txt | %{Get-WmiObject -Class Win32_Service -ComputerName (Get-Content .\computers.txt) -Filter "Name='$_'"} | %{$_.StopService()}; Get-Content .\services.txt | %{Get-WmiObject -Class Win32_Service -ComputerName (Get-Content .\computers.txt) -Filter "Name='$_'"} | %{$_.StartService()}

PowerShell pass a switch to a function with Invoke-Command

I'm having some difficulties passing the switch -CleanFolders to a function by using Invoke-Command. I found this, but I don't really know how to implement it as it's not targeted to a function.
Calling my function like this works fine:
Delete-OldFiles $Target $OlderThanDays $Server -CleanFolders
Invoke-Command -ComputerName "$Server" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)
But this doesn't work at all:
Invoke-Command -ComputerName "$Server" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server, -CleanFolders)
Full script:
#__________________________________________________________________________________________________________________________________
$ImportFile = "S:\Input\Scheduled Task\Auto_Clean.csv"
$Password = cat "S:\Input\pwd.txt" | ConvertTo-SecureString -Force
$UserName = "domain\me"
#__________________________________________________________________________________________________________________________________
# Scriptblock for running the function in a job
$JobFunc = {
# Function that removes files older than x days in all subfolders
Function Delete-OldFiles {
<#
.SYNOPSIS
Script to delete files and folders older than x days
.DESCRIPTION
Remove files older than x days in all subfolders and write success and failure actions to the logfile in "\\DEUSTHEIDIT02\Log\Scheduled Task\Auto_Clean\".
By default, empty foldes will be left behind and not deleted.
.PARAMETER Target
The path that will be recusively scanned for old files
.PARAMETER OlderThanDays
Filter for age of file, entered in days. Use 0 for all files to be removed
.PARAMETER CleanFolders
If this switch is specified folders that are older than 'OlderThanDays' and are empty will be removed. Default behaviour of this script is to leave empty folders behind.
.EXAMPLE
Delete-OldFiles -Target "\\grouphc.net\bnl\DEPARTMENTS\Brussels\CBR\SHARE\Target" -OlderThanDays "10"
Delete-OldFiles "\\grouphc.net\bnl\DEPARTMENTS\Brussels\CBR\SHARE\Target" "10"
Delete-OldFiles "E:\DEPARTMENTS\CBR\SHARE\Target" "10"
Description:
Deletes all files older than 10 days in the Target folder and all of its subfolders and write success and failure to the log.
.EXAMPLE
Delete-OldFiles "\\grouphc.net\bnl\DEPARTMENTS\Brussels\CBR\SHARE\Target" "10" -CleanFolders
Description:
Deletes all files older than 10 days and all empty folders in the Target folder and all of its subfolders and write success and failure to the log.
.NOTES
REQUIREMENTS Remote server:
PowerShell 2.0
As admin run 'Set-ExecutionPolicy RemoteSigned'
As amdin run 'Enable-WSManCredSSP -Role Server -Force'
REQUIREMENTS Script server:
Enable-WSManCredSSP -Role Client -DelegateComputer *.grouphc.net -Force
CHANGELOG
2014/05/06 Script born
2014/05/07 Added total runtime of the script to the logfile
2014/05/12 Added timestamps, fail and success messages to the logfile
2014/05/13 Added PowerShell 2.0 compatibility for Windows Server 2003
2014/05/13 Added remove empty directories
2014/05/14 Added comment section on top
2014/05/15 Added parameters to pass variables $Target and $OlderThanDays
2014/05/19 Added CSV input file for easy management
2014/05/20 Created function Delete-OldFiles and Delete-OldFolders
2014/05/22 Rewrote script for calling functions
2014/05/23 Added switch -CleanFolders
2014/06/02 Added password authentication for double hop
2014/06/03 Added loging capability to different files with timestamps
.AUTHOR
Me #>
[CmdletBinding(SupportsShouldProcess=$True)] # Add -WhatIf support for dry run
Param(
[Parameter(Mandatory=$True,Position=1)]
[ValidateScript({Test-Path $_})]
[String]$Target,
[Parameter(Mandatory=$True,Position=2)]
[Int]$OlderThanDays,
[Parameter(Mandatory=$False,Position=3)]
[String]$Server,
[switch]$CleanFolders
)
#__________________________________________________________________________________________________________________________________
# Create logfile with the correct name
# Gets date and reformats to be used in log filename
$TempDate = (get-date).ToString("dd-MM-yyyy")
# Reformats $Target so it can be used in the log filename
$TempFolderPath = $Target -replace '\\','_'
$TempFolderPath = $TempFolderPath -replace ':',''
$TempFolderPath = $TempFolderPath -replace ' ',''
# Combines the date and the path scanned into the log filename
$script:LogFile = "\\DEUSTHEIDIT02\Log\Scheduled Task\Auto_Clean\$Server - $TempFolderPath - $TempDate.log"
#__________________________________________________________________________________________________________________________________
# Check the version of PowerShell
if ($PSVersionTable.PSVersion.Major -ge "3") {
# PowerShell 3+ Remove files older than (FASTER)
Get-ChildItem -Path $Target -Recurse -File |
Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } |
ForEach {
$Item = $_.FullName
Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue
# Log succes/failure
$Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()
if (Test-Path $Item) {
"$Timestamp | FAILLED: $Server $Item (IN USE)"
}
else {
"$Timestamp | REMOVED: $Server $Item"
}
} | Tee-Object $LogFile -Append }
Else {
# PowerShell 2 Remove files older than
Get-ChildItem -Path $Target -Recurse |
Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } |
ForEach {
$Item = $_.FullName
Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue
# Log succes/failure
$Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()
if (Test-Path $Item) {
Write-Host "$Timestamp | FAILLED: $Server $Item (IN USE)"
"$Timestamp | FAILLED: $Server $Item (IN USE)"
}
else {
Write-Host "$Timestamp | REMOVED: $Server $Item"
"$Timestamp | REMOVED: $Server $Item"
}
} | Out-File $LogFile -Append }
#__________________________________________________________________________________________________________________________________
# Switch -CleanFolders deletes empty folders older than x days
if ($CleanFolders) {
# Check the version of PowerShell
if ($PSVersionTable.PSVersion.Major -ge "3") {
# PowerShell 3+ Remove empty folders older than (FASTER)
Get-ChildItem -Path $Target -Recurse -Force -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } |
Where-Object { (Get-ChildItem -Path $_.FullName -Recurse -Force -File) -eq $null } |
ForEach {
$Item = $_.FullName
Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue
# Log succes/failure
$Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()
if (Test-Path $Item) {
"$Timestamp | FAILLED: $Server $Item (IN USE)"
}
else {
"$Timestamp | REMOVED: $Server $Item"
}
} | Tee-Object $LogFile -Append
}
else {
# PowerShell 2 Remove empty folders older than
Get-ChildItem -Path $Target -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } |
Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } |
ForEach {
$Item = $_.FullName
Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue
# Log succes/failure
$Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()
if (Test-Path $Item) {
Write-Host "$Timestamp | FAILLED: $Server $Item (IN USE)"
"$Timestamp | FAILLED: $Server $Item (IN USE)"
}
else {
Write-Host "$Timestamp | REMOVED: $Server $Item"
"$Timestamp | REMOVED: $Server $Item"
}
} | Out-File $LogFile -Append
}
}
}
}
#__________________________________________________________________________________________________________________________________
# Read input file and ignore all lines starting with #
$File = (Import-Csv -Path $ImportFile -Header "Server", "Target", "OlderThanDays" | Where { $_.Server -NotMatch "#" } )
#__________________________________________________________________________________________________________________________________
# If the UNC Path is provided we will run the script locally else it wil be run on the remote server as a job
Foreach ($_ in $File) {
# Set easy names
$Server = $_.Server
$Target = $_.Target
$OlderThanDays = $_.OlderThanDays
if ($Server -eq "UNC")
{
Write-Host "UNC Path detected: $Target, $OlderThanDays" -ForegroundColor Yellow
Start-Job -ScriptBlock {Param($Target, $OlderThanDays, $Server) Delete-OldFiles $Target $OlderThanDays $Server} -InitializationScript $JobFunc -ArgumentList ($Target, $OlderThanDays, $Server) -Name DelFiles
# Remove empty folders to: Delete-OldFiles $Target $OlderThanDays $Server -CleanFolders
}
else
{
Write-Host "Local path detected: $Server, $Target, $OlderThanDays" -ForegroundColor Cyan
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName,$Password
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName,$Password
Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {$JobFunc; Delete-OldFiles $Target $OlderThanDays $Server} -ArgumentList ($Target, $OlderThanDays, $Server) #-AsJob -JobName DelFiles
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {Delete-OldFiles $args[0] $args[1] $args[2] -CleanFolders:$args[3]} -ArgumentList ($Target, $OlderThanDays, $Server, $true) -AsJob -JobName DelFiles
# Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server) -AsJob -JobName DelFiles
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {Delete-OldFiles $Target, $OlderThanDays, $Server} -ArgumentList ($Target, $OlderThanDays, $Server) #-AsJob -JobName DelFiles
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server) #-AsJob -JobName DelFiles
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {$JobFunc} -ArgumentList ($Target, $OlderThanDays, $Server) -AsJob -JobName DelFiles
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)
}
}
Thank you for your help.
Try like this:
$sb = {
function Delete-OldFiles {
#...
}
Delete-OldFiles $args[0] $args[1] $args[2] -CleanFolders:$args[3]
}
Invoke-Command -ComputerName $Server -Authentication Credssp `
-Credential $Credentials -ScriptBlock $sb `
-ArgumentList ($Target, $OlderThanDays, $Server, $true)

powershell remote

I am trying to run this from my local machine (Win7 & PS v2.0)
cls
$sess = Enter-PSSession -ComputerName blmcrmpoc
Invoke-Command -Session $sess -Scriptblock
{
$path = "C:\inetpub\logs\LogFiles"
$lastWrite = (Get-Date).AddDays(-90)
$oldLogs = Get-ChildItem -path $path -Recurse -Filter *.log | Where {$_.LastWriteTime -le $lastWrite}
if ($oldlogs.count -gt 0)
{foreach ($log in $oldLogs)
{$log.Delete()}}}
But I get this error.
***Invoke-Command : Cannot validate argument on parameter 'Session'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
What am I missing?
Try:
cls
$sess = New-PSSession -ComputerName blmcrmpoc
Invoke-Command -Session $sess -Scriptblock
{
$path = "C:\inetpub\logs\LogFiles"
$lastWrite = (Get-Date).AddDays(-90)
$oldLogs = Get-ChildItem -path $path -Recurse -Filter *.log | Where {$_.LastWriteTime -le $lastWrite}
if ($oldlogs.count -gt 0)
{
foreach ($log in $oldLogs)
{
$log.Delete()
}
}
}
With Enter-PSSession you ENTER a pssession(you start remoting it so you could write the commands directly as if it were the local machine). If you want to use Invoke-Command on a specific session, you create the session using New-Session because this creates a session without entering it.
How to access argument list for scriptblock
ArgumentList is based on use with scriptblock commands, like:
you have to pass arugments for script block..
cls
$sess = Enter-PSSession -ComputerName blmcrmpoc
Invoke-Command -Session $sess -Scriptblock
{
$path = "C:\inetpub\logs\LogFiles"
$lastWrite = (Get-Date).AddDays(-90)
$oldLogs = Get-ChildItem -path $path -Recurse -Filter *.log | Where {$_.LastWriteTime -le $lastWrite}
if ($oldlogs.count -gt 0)
{
$xArgvalue= arg[0]
$yArgvalue= arg[1]
foreach ($log in $oldLogs)
{
$log.Delete()
}
}
} -ArgumentList $x,$y
I found on below link how to pass arguments to script block