Try Catch output [duplicate] - powershell

I have a working powershell script, but when it cannot find a hostname, it throws a non-terminating exception and writes to the screen that that hostname was unable to be found. I want to catch that exception and simply write to the screen: Not Found. Then I want the script to carry on like normal.
Here is the script:
$listOfComputers = IMPORT-CSV test.txt
$b = "2013-09-11"
ForEach($computer in $listOfComputers){
$name = $computer.Name
Write-Host $name -NoNewLine
try{$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $name)}
catch [Exception] {write-host " Not Found" -foreground blue}
$key = $reg.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\\Results\\Install")
$a = $key.GetValue("LastSuccessTime")
$a = $a.Substring(0,10)
if($a -le $b){Write-Host " " $a -foreground magenta}
else{Write-Host " " $a}
}
Here is the output:
PS C:\PowerShell Scripts> .\windowsUpdates.ps1
OLDBEAR Not Found
You cannot call a method on a null-valued expression.
At C:\PowerShell Scripts\windowsUpdates.ps1:8 char:1
+ $key =
$reg.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpd
...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\PowerShell Scripts\windowsUpdates.ps1:9 char:1
+ $a = $key.GetValue("LastSuccessTime")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\PowerShell Scripts\windowsUpdates.ps1:10 char:1
+ $a = $a.Substring(0,10)
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Any help is appreciated.

Skip the try/catch altogether, and instead test for connectivity before attempting to access the registry. This should speed your script up, as you won't be waiting for a timeout from OpenRemoteBaseKey on systems that are offline.
$listOfComputers = IMPORT-CSV test.txt
$b = "2013-09-11"
ForEach($computer in $listOfComputers){
$name = $computer.Name
Write-Host $name -NoNewLine
if (-not (Test-Connection -computername $name -count 1 -Quiet -ErrorAction SilentlyContinue) {
write-host " Not Found" -foreground blue;
continue;
}
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $name)
$key = $reg.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\\Results\\Install")
$a = $key.GetValue("LastSuccessTime")
$a = $a.Substring(0,10)
if($a -le $b) {
Write-Host " " $a -foreground magenta
}
else {
Write-Host " " $a;
}
}
You could also test connectivity in bulk before hitting the main loop, filtering any computers that aren't accessible out of your list. See my answer over here for a way to do that.

Related

Passing filepath parameters to function

Below mentioned code is giving error, and I'm not able to troubleshoot issue. Can anyone please help, we are just passing SourceFile and DestinationFile location to this function...
ProcessDocumentsData "D:\Files\Scan1.doc","D:\Files\Scan1.csv"
Clear-Host
function ProcessDocumentsData {
Param(
[string]$SourceFile,
[string]$DestinationFile
)
$DestinationFileName = $DestinationFile
$SourceFileName = $SourceFile
$tableNum = 13
$delimiter = ','
$objWord = New-Object -Com Word.Application
$objWord.Visible = $false # $false
$objDocument = $objWord.Documents.Open($SourceFileName)
$LETable = $objDocument.Tables.Item($tableNum)
$LETableCols = $LETable.Columns.Count
$LETableRows = $LETable.Rows.Count
$RawCSV = for($r=1; $r -le $LETableRows; $r++) {
$content= #()
for($c=1; $c -le $LETableCols; $c++) {
#Write-Host ("R:{0},C:{1}" -f $r,$c)
$content += ("`"{0}`"" -f $LETable.Cell($r,$c).Range.Text -replace "(`r|`n|`t)|$([char]7)?")
}
$Content -join $delimiter
}
$Csv = $RawCSV | ConvertFrom-Csv
$objDocument.Close()
$objWord.Quit()
# Stop Winword Process
$rc = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objWord)
$Csv
$Csv | Export-Csv $DestinationFileName -NoTypeInformation
}
I'm getting the following error:
ProcessDocumentsData "D:\Files\Scan1.doc","D:\Files\Scan1.csv"
Command failed
At line:7 char:1
+ $objDocument = $objWord.Documents.Open($filename)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
You cannot call a method on a null-valued expression.
At line:8 char:1
+ $LETable = $objDocument.Tables.Item($tableNum)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:21 char:1
+ $objDocument.Close()
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
In PowerShell, when calling a function multiple parameters are delimited by a whitespace.
Try to call the function like that:
ProcessDocumentsData "D:\Files\Scan1.doc" "D:\Files\Scan1.csv"

Error executing script in powershell WSUS GetUpdate()

I executed a Powershell script, but I got an error
Script
[datetime]$dataIni = "2017/01/01"
[datetime]$dataFim = "2017/01/20"
$serverWsus = "server1"
[void]
$wsus =[Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($serverWsus,$False,8530)
Write-Progress -Activity 'Getting updates...' -PercentComplete 0
$updatesneeded = $wsus.GetUpdate() | ? {($_.CreationDate -gt
[datetime]$dateFirst -and
$_.CreationDate -lt [datetime]$dateLast) -and
($_.Title -notmatch "Itanium" -and
$_.Title -match "Windows Server 2008 x64" -and
$_.UpdateClassificationTitle -eq "Security Updates")}
$i = 0
$total = $updatesneeded.Count
foreach ($update in $updatesneeded)
{
Write-Progress -Activity 'Approving updates...' -Status "%Complete" -
PercentComplete (($i/$total) * 100)
Approve-WsusUpdate -Update $update -Action Install -TargetGroupName 'enviroment'
$i++
}
Write-Host "Updates approved: $total" -ForegroundColor Yellow
Error
Cannot find an overload for "GetUpdate" and the argument count: "0".
At line:11 char:1
+ $updatesneeded = $wsus.GetUpdate() | ? {($_.CreationDate -gt [datetime]$dateFirs ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Approve-WsusUpdate : Cannot bind parameter 'Update'. Cannot convert the "Microsoft.UpdateServices.Internal.BaseApi.Update" value of type "Microsoft.UpdateServices.Internal.BaseApi.Update"
to type "Microsoft.UpdateServices.Commands.WsusUpdate".
At line:22 char:32
+ Approve-WsusUpdate -Update $update -Action Install -TargetGroupName 'enviroment'
+ ~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Approve-WsusUpdate], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.UpdateServices.Commands.ApproveWsusUpdateCommand

Erroraaction in uploading file by FTP

I have a file with IP address of servers. And script reads adress ($line) by adress, but sometimes can occur address of server that will be down. It is necessary to script steel run till end of IP address. So I used -Erroraction Continue to Set_FTPConnection But script break anyway. How to solve this problem?
foreach ($line in $FTPServer)
{
Start-Transcript -Path $results
Write-Host -Object "ftp url: $line"
Set-FTPConnection -Credentials $FTPCredential -Server $line -Session MySession -UsePassive -ErrorAction Continue
$Session = Get-FTPConnection -Session MySession
$Session>>.\sessions.txt
#Write-Host $Error[0]
if($session.UsePassive -eq "True"){$connect="OK"}
else{$connect="FAIL"}
foreach ($item in (Get-ChildItem .\Upload))
{
#Get-FTPChildItem -Session $Session -Path /htdocs #-Recurse
Write-Host -Object "Uploading $item..."
$Send= Add-FTPItem -Session $Session -Path $FTPPlace -LocalPath .\Upload\$item -Overwrite -ErrorAction Continue #>> .\up.txt #.\Upload\test.txt
$item|gm >>.\up.txt
if($Send.Name -eq $item.Name){$Rec="OK"}
else{$Rec="!!!-FAIL-!!!"}
$array = $line, $item, $connect, $Rec
$FailTable=New-Object -TypeName PSObject -Property ([ordered]#{"FTP Server"=$array[0]; "File"=$array[1];"Connected"=$array[2];"Uploaded"=$array[3]})
Add-Content .\stats.txt $FailTable
}
Stop-Transcript
}
Errors:
From my code
Transcript started, output file is .\logs.txt
ftp url: 10.80.59.173
Set-FTPConnection : Exception calling "GetResponse" with "0" argument(s): "Unable to connect to the remote server"
At F:\DPI FTP\FTPUpload_v2.ps1:25 char:13
+ Set-FTPConnection -Credentials $FTPCredential -Server $li ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Set-FTPConnection
With Test-NetConnection
Start-Transcript : Transcription cannot be started.
At F:\DPI FTP\FTPUpload_v2.ps1:21 char:9
+ Start-Transcript -Path $results #if $session.usepa ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Transcript], PSInvalidOperationException
+ FullyQualifiedErrorId : CannotStartTranscription,Microsoft.PowerShell.Commands.StartTranscriptCommand
ftp url: 10.80.59.173
Test-NetConnection : The term 'Test-NetConnection' is not recognized as the name of a cmdlet, function, script file, or operable program. Ch
eck the spelling of the name, or if a path was included, verify that the path is correct and try again.
At F:\DPI FTP\FTPUpload_v2.ps1:23 char:13
+ If (Test-NetConnection $line -Port '21')
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Test-NetConnection:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Transcript started, output file is .\logs.txt
ftp url: 10.80.59.170
Test-NetConnection : The term 'Test-NetConnection' is not recognized as the name of a cmdlet, function, script file, or operable program. Ch
eck the spelling of the name, or if a path was included, verify that the path is correct and try again.
At F:\DPI FTP\FTPUpload_v2.ps1:23 char:13
+ If (Test-NetConnection $line -Port '21')
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Test-NetConnection:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
With If:
WARNING: Could not connect to 10.80.59.173
Start-Transcript : Transcription cannot be started.
At F:\DPI FTP\FTPUpload_v2.ps1:20 char:9
+ Start-Transcript -Path $results #if $session.usepa ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Transcript], PSInvalidOperationException
+ FullyQualifiedErrorId : CannotStartTranscription,Microsoft.PowerShell.Commands.StartTranscriptCommand
Stop-Transcript : An error occurred stopping transcription: The host is not currently transcribing.
At F:\DPI FTP\FTPUpload_v2.ps1:47 char:9
+ Stop-Transcript
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Stop-Transcript], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.PowerShell.Commands.StopTranscriptCommand
Continue is actually the default setting. It means that if a non-terminating error occurs, it will show the error and then should be continuing with the command and rest of the script. You could try SilentlyContinue to see if that helps.
Alternatively you could test if the IP Address is connectable first. If you're using Windows 8/Server 2012 or newer and PowerShell v4+ you could use Test-NetConnection -Port 21 to do this specifically for the FTP port, if not you could use Test-Connection instead (which is a PS equivalent of Ping):
foreach ($line in $FTPServer)
{
Start-Transcript -Path $results
Write-Host -Object "ftp url: $line"
If (Test-Connection $line) {
Set-FTPConnection -Credentials $FTPCredential -Server $line -Session MySession -UsePassive -ErrorAction Continue
$Session = Get-FTPConnection -Session MySession
$Session>>.\sessions.txt
#Write-Host $Error[0]
if($session.UsePassive -eq "True"){$connect="OK"}
else{$connect="FAIL"}
foreach ($item in (Get-ChildItem .\Upload))
{
#Get-FTPChildItem -Session $Session -Path /htdocs #-Recurse
Write-Host -Object "Uploading $item..."
$Send= Add-FTPItem -Session $Session -Path $FTPPlace -LocalPath .\Upload\$item -Overwrite -ErrorAction Continue #>> .\up.txt #.\Upload\test.txt
$item|gm >>.\up.txt
if($Send.Name -eq $item.Name){$Rec="OK"}
else{$Rec="!!!-FAIL-!!!"}
$array = $line, $item, $connect, $Rec
$FailTable=New-Object -TypeName PSObject -Property ([ordered]#{"FTP Server"=$array[0]; "File"=$array[1];"Connected"=$array[2];"Uploaded"=$array[3]})
Add-Content .\stats.txt $FailTable
}
Stop-Transcript
} Else {
Write-Warning "Could not connect to $line"
}
}

Receiving odd error message in PS script

I have a PowerShell script that goes out grabs the currently logged in user on a remote computer and gets the total size of their local profile C:\users\USERNAME\documents, pictures, music, etc. I have confirmed that the remote computer is online and the user is logged in. While the script is working, in the sense that it gets the folder size, it returns this message:
Get-WmiObject : Invalid parameter
At C:\Users\administrator\Desktop\get_folder_size.ps1:4 char:9
+ $user = Get-WmiObject Win32_ComputerSystem -ComputerName $system | Se ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
You cannot call a method on a null-valued expression.
At C:\Users\administrator\Desktop\get_folder_size.ps1:5 char:1
+ $pos = $user.IndexOf("\")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\administrator\Desktop\get_folder_size.ps1:6 char:1
+ $user = $user.Substring($pos+1)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
I'm confused because if I'm reading the message correctly it shouldn't be able to grab the username thus not get the correct folder and the size.
Here is the code that I'm running
foreach ($system in Get-Content "C:\net_view.txt")
{
$colItems = 0
$user = Get-WmiObject Win32_ComputerSystem -ComputerName $system |
Select-Object -ExpandProperty UserName
$pos = $user.IndexOf("\")
$user = $user.Substring($pos+1)
$path = $system +"\c$\users\" + $user
$colItems = (Get-ChildItem $path -Recurse -ErrorAction SilentlyContinue |
Measure-Object -property length -sum)
"{0:N2}" -f ($colItems.sum / 1MB) + " MB"
Add-Content C:\users\administrator\desktop\profile_size.txt ($colItems.sum / 1MB)
Add-Content C:\users\administrator\desktop\profile_size.txt $system
}

powershell get-content path null error

$commonElementsLocation = ((Get-Location).Path + "\FolderMatchingCommonWords.txt")
if ($commonElementsLocation) {
$result += Start-Job -InitializationScript {
$commonElements = Get-Content -Path $commonElementsLocation
} -ScriptBlock $testScriptBlock -ArgumentList "testing" | Wait-Job | Receive-Job
}
Not sure what I am doing wrong here - probably a stupid mistake, but I put a condition around the Start-Job statement, and powershell still gives the following error:
Get-Content : Cannot bind argument to parameter 'Path' because it is null.
At line:1 char:39
+ $commonElements = (Get-Content -Path $commonElementsLocation)
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetContentC
ommand
Running startup script threw an error: Cannot bind argument to parameter 'Path' because it is null..
+ CategoryInfo : OpenError: (localhost:String) [], RemoteException
+ FullyQualifiedErrorId : PSSessionStateBroken
In v3 add $using:
....(Get-Content -Path $using:commonElementsLocation...
You have already used a variable for a script block once with $testScriptBlock. You could just do that again for -InitializationScript?
$anotherSB = [scriptblock]::create("$commonElements = (Get-Content -Path $commonElementsLocation)")
$result += Start-Job -InitializationScript $anotherSB -ScriptBlock $testScriptBlock -ArgumentList "testing" | Wait-Job | Receive-Job