I want to test if New-Item throws an error, for which i am using the -WhatIf parameter and catch the error if an error occurs. If no error occurs, i dont want the -WhatIf output in my console.
I tried the following, but the "WhatIf:"-Output still gets printed to the Powershell console:
New-Item -Path $Path -Name $Name -ItemType $ItemType -ErrorAction stop -WhatIf | Out-Null
I also tried to use $WhatIfPreference as in this StackOverflow answer, which had the same result.
Related
Below is a simple Try Catch but when I was testing it, when successful it appears to file so I included a location which didnt exist into the variable to test the failure, but oddly even though the failure appears in the ISE window the out still shows as suceeded maing something isnt quite right with below, any ideas as Im lost at what is wrong.
## The location/filename where the Logs will be stored
$varfullpath = "I:\Dev\BI\Reference Data\Release_Event_log.txt"
## The location/filename of the Source to copy from
$sourceDirectory = "C:\Users\Simon.Evans\Documents\Source Data\kljhkjlOS\"
## The location/filename of the Destination to copy to
$destinationDirectory = "I:\Dev\BI\Projects\Powershell\Test Area\Source Data\OkjhkhDS\"
$Server = "CHH-BITEST"
$CurrentDate = Get-Date
try{
Get-ChildItem -Path $sourceDirectory -File -Filter "*.csv" | Copy-Item -Destination $destinationDirectory -ErrorAction Stop
Write-Log -Message "Copy from $sourceDirectory to $destinationDirectory suceeded" -path $varfullpath
}
catch{
$Error[0] | Write-Log -path $varfullpath
Write-log -Message "Copy from $sourceDirectory to $destinationDirectory Failed" -Level Error -path $varfullpath
}
Start-Process notepad $varfullpath ## Opens the file immediately for review
The error is thrown by the get-childitemcommand.
Add the -ErrorAction Stop to this command like that:
Get-ChildItem -Path $sourceDirectory -File -Filter "*.csv" -ErrorAction Stop | Copy-Item -Destination $destinationDirectory -ErrorAction Stop
Some additions to #guiwhatsthat's answer:
PowerShell distinguishes between terminate errors and non-terminating errors. With the help of the common ErrorAction parameter you can setup the behaviour of a cmdlet if such kind of error occurrs. If you want to change the behaviour of multiple cmdlets, or sections in your script you can change the value of $ErrorActionPreference.
From PowerShell documentation:
$ErrorActionPreference
Determines how PowerShell responds to a non-terminating error (an error that does not stop the cmdlet processing) at the command line or in a script, cmdlet, or provider, such as the errors generated by the Write-Error cmdlet.
You can also use the ErrorAction common parameter of a cmdlet to override the preference for a specific command.
Valid values:
Stop: Displays the error message and stops executing.
Inquire: Displays the error message and asks you whether you want to continue.
Continue: Displays the error message and continues (Default) executing.
Suspend: Automatically suspends a workflow job to allow for further investigation. After investigation, the workflow can be resumed.
SilentlyContinue: No effect. The error message is not displayed and execution continues without interruption.
I'm trying to create a script to delete all files out of %temp%. It works but now I need to get rid of the errors. Below is what I have but I'm still getting errors. Any ideas?
try
{
Get-Childitem $Env:temp | Remove-Item -Recurse -Force
}
Catch
{
}
Lots of files in temp can be in use or otherwise inaccessible for removable as that is the scratch space for processes to leave data.
Most common cmdlets support -ErrorAction so that you don't have to the change the default one and risk missing an important error. In your case you can use ...
Get-Childitem $Env:temp | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
Since you are not generating terminating errors which is what Try is for you can just remove the block entirely.
FWIW if you really do need try/catch make sure you use terminating errors
try{
Get-ChildItem $Env:temp | Remove-Item -Recurse -Force -ErrorAction Stop
} Catch{
# Handle Stuff
Write-Host "Removal not 100% successful"
}
I have a simple script to delete a file, I know it could be more robust, but here it is
$LogFile = ".\deleteRegPol.log"
try
{
Remove-Item "c:\test\new text document.txt" -force
Add-Content $LogFile -Value "We ran the command"
}
catch [Exception]
{
Add-Content $LogFile -Value $_
}
finally
{
}
When the file I am trying to delete doesn't exist, I get an error on the command line but in my log file, it says the command ran. This is telling me that an exception was not thrown resulting in the flow going to the catch block. Why not?
PowerShell does not normally throw an exception when there is an error. Instead it writes a record to the error stream, which you can redirect. To force it to throw there are two options. One is to set the global error preference to stop:
$ErrorActionPreference = "Stop"
The other is to set the ErrorAction parameter to stop. This is supported for cmdlets that accept the so-called common parameters, which Remove-Item does:
Remove-Item "c:\test\new text document.txt" -force -EA "Stop"
To redirect the error stream you use the code 2:
Remove-Item "c:\test\new text document.txt" -Force 2>> $LogFile
That would append the error to the log file. The record isn't written to the error stream if your option is "Stop" however. It is simply included in the exception that is thrown.
Add the ErrorAction switch to your Remove-Item command:
Remove-Item "c:\test\new text document.txt" -force -ErrorAction Stop
There's quite a good treatment on error handling here:
http://blogs.msdn.com/b/kebab/archive/2013/06/09/an-introduction-to-error-handling-in-powershell.aspx
When I run a recursive Copy-Item from a folder that has sub folders to a new folder that contains the same sub folders as the original, it throws an error when the subfolders already exist.
How can I suppress this because it is a false negative and can make true failures harder to see?
Example:
Copy-Item "C:\realFolder\*" "C:\realFolder_new" -recurse
Copy-Item : Item with specified name C:\realFolder_new\subFolder already exists.
You could try capturing any errors that happen, and then decide whether you care about it or not:
Copy-Item "C:\realFolder\*" "C:\realFolder_new" -recurse -ErrorVariable capturedErrors -ErrorAction SilentlyContinue
$capturedErrors | foreach-object { if ($_ -notmatch "already exists") { write-error $_ } }
If you add -Force to your command it will overwrite the existing files and you won't see the error.
-Recurse will replace all items within each folder and all subfolders.
Copy-Item "C:\realFolder\*" "C:\realFolder_new" -Recurse -Force
You can set the error handling behavior to ignore using:
Copy-Item "C:\realFolder\*" "C:\realFolder_new" -recurse -ErrorAction SilentlyContinue
However this will also suppress errors you did want to know about!
I have a program that copies folders and files recursively.
example:
Copy-Item -path "$folderA" -destination "$folderB" -recurse
Sometimes the files do not copy. Is there a way to "step inside the recursion" or a better way to do it, so I can enable some kind of error checking during the process rather than after wards. Possibly even do a Test-Path and prompt for a recopy?
You can. For example the following code snippet will actually copy and check each file for possible errors. You can also put your custom code at the beginning to check for some prerequisites:
get-childItem $source -filter *.* | foreach-object {
# here you can put your pre-copy tests...
copy-item $_.FullName -destination $target -errorAction SilentlyContinue -errorVariable errors
foreach($error in $errors)
{
if ($error.Exception -ne $null)
{
write-host -foregroundColor Red "Exception: $($error.Exception)"
}
write-host -foregroundColor Red "Error: An error occured during copy operation."
}
}