Hi, I would like some advice/help on improving the script below which was written with help on another forum.
I will explain the requirements first so you can see what I am doing.
- To copy a file to lots of computers on domain network, but file can only be copied if specific process (app) is not running
So the steps I need to do:-
1) Check if computer is online or accessible - I used Test-Connection for this as seemed to work okay - but had to add -ErrorAction SilentlyContinue if not got error "Test-Connection : Testing connection to computer 'Tfdffdd' failed: No such host is known" for computers which didn't exist in DNS etc. Store failure computer namesin a variable to try later, if pass then continue - NOTE: Perhaps I should use -Quiet here to just get back a boolean result?
2) I then need to check I can actually access the computer using PS Remoting as had some cases where get error below due to firewall config or because they are on a public network - these are things I can easily fix when I know which computers are affected - but no point in trying to copy a file if can't even connect etc - so handy to store failure computer names in another variable which I can sort later, and if connect okay to continue
[Lxxxx] Connecting to remote server Lxxxx failed with the following error message : WinRM cannot process the request. The following error with errorcode 0x80090322 occurred while using Kerberos authentication: An unknown security error occurred. Possible causes are: -The user name or password specified are invalid. -Kerberos is used when no authentication method and no user name are specified. -Kerberos accepts domain user names, but not local user names. -The Service Principal Name (SPN) for the remote computer name and port does not exist. -The client and remote computers are in different domains and there is no trust between the two domains. After checking for the above issues, try the following: -Check the Event Viewer for events related to authentication. -Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport. Note that computers in the TrustedHosts list might not be authenticated. -For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic. + CategoryInfo : OpenError: (Lxxxx:String) [], PSRemotingTransportException + FullyQualifiedErrorId : -2144108387,PSSessionStateBroken
For this I had tried Test-WSMan but that comes back as all okay even though I can't connect to them, so instead I used Invoke-Command which worked fine
3) I then check to see if a specifc process is running - using Get-Process which works fine - if process is running then store computer name in variable to try again later, if process is not running then continue
4) Copy file to computer - for this Copy-Item worked fine - BUT on the odd computer (down to a current DNS issue) I get an error below which I need to handle somehow as with current script it thinks it is a success wrongly
Copy-Item : The network path was not found
At C:\Tmp\PCA_TESTING_ONLY\file_copy.ps1:11 char:37
- ... =$computer; Copy-Item -Path "\lb-nordc\SoftwareInstalls\CCH_ProAudit ...
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
- FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
5) show results based on which of the four stages it got to - e.g. offiline, remoting failed, process running, file copied okay
Below are two version of the scripts I have been using.
I am still learning so would like any comments / advice on
a)
how the scripts can be made better - any other methods I could use e.g. try..catch to make it better / more bulletproof?
b)
any poor scripting practices etc
c)
how to combine the two checks e.g. Test-Connection first and then check can access remotely second before continuing (point 1 and 2 above) - or is the second bit an area for try..catch perhaps?
d)
how to handle file copy-item error in point 4 above
Anything I have missed please ask.
Much appreciated in advance for any feedback / help given :)
Script 1 - just checking if online using Test-Connection
$computers = @("PC1", "PC3")
$RNote = @()
$NNote = @()
$off = @()
Foreach ($computer in $computers) {
$TestC = Test-Connection -ComputerName $computer -Count 1 -ErrorAction SilentlyContinue
If (!($TestC)) { $off += $computer } Else {
$Procs = Invoke-Command -ComputerName $computer { Get-Process Notepad -ErrorAction SilentlyContinue }
If (!$Procs) { $NNote += $computer; Copy-Item -Path "\\lserver\myfile.txt" -Destination "\\$computer\c$\folder\" -Force }
elseif ($Procs) { $RNote += $computer }
}
}
$leng = [array]$RNote.count, $NNote.Count, $off.count
[int]$max = ($leng | Measure-Object -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] })
}
}
Script 2 - checking if can access using ps remoting
$computers = @("NOa-IT")
$RNote = @()
$NNote = @()
$off = @()
Foreach ($computer in $computers) {
$TestRemote = Invoke-Command -ComputerName $computer { 1 } -ErrorAction SilentlyContinue
If (($TestRemote -ne 1)) { $off += $computer } Else {
$Procs = Invoke-Command -ComputerName $computer { Get-Process Proaudit -ErrorAction SilentlyContinue }
If (!$Procs) { $NNote += $computer; Copy-Item -Path "\\server\myfile.txt" -Destination "\\$computer\c$\folder\" -Force }
elseif ($Procs) { $RNote += $computer }
}
}
$leng = [array]$RNote.count, $NNote.Count, $off.count
[int]$max = ($leng | Measure-Object -Maximum).Maximum
for ($i = 0; $i -lt $max; $i++) {
[pscustomobject]@{
"File NOT Copied" = $(if ($RNote[$i]) { $RNote[$i] })
"File Copied" = $(if ($NNote[$i]) { $NNote[$i] })
"Offline " = $(if ($off[$i]) { $off[$i] })
}
}