I am currently having an issue logging exceptions in my PowerShell script. I am trying to copy a file to C:\Windows\System32 and I want to add an error line to my log file if it errors. I have tried this two ways so far.
Example 1:
$LogPath = "C:\Test.txt
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
Copy-Item $scriptPath\Devcon.exe C:\Windows\System32 -ErrorAction SilentlyContinue -ErrorVariable $Errors
Foreach($error in $Errors)
{
add-content -Path $LogPath -Value $($error.Exception) -Force
}
Example 2:
$LogPath = "C:\Test.txt
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
Try{
Copy-Item $scriptPath\Devcon.exe C:\Windows\System32
}
Catch [System.Exception]
{
add-content -Path $LogPath -Value "There was an error why trying to copy the file." -Force
add-content -Path $LogPath -Value $Error -Force
}
I can add items to the log file so I know it's not a permissions issue with the file. What am I missing?
I believe the error you are getting is non-terminating. This is why it does not end up in a catch block.
Try this instead of your Copy-Item line:
Copy-Item $scriptPath\Devcon.exe C:\Windows\System32 -ErrorAction Stop
Help on ErrorAction (MSDN).
Related
I have 3 commands inside of a Try and I want custom Catch error messages for each of them in case of an error
e.g. If the first will fail then I would like to get the following message: "Error creating a directory!"
If the second will fail then: "Copy items failed"
If the third will fail then: "Content is not created"
How can I apply that?
Try{
New-Item -ItemType Directory -Name "Script" -Path "C:\Temp\" -Force
Copy-Item -Path $FilePath_ps1 -Destination C:\temp\script -Force
Set-Content -Value "test" -Path "C:\Temp\Script\test.txt" -Force
}
Catch{
" what code do I need here?"
}
Thanks for your help.
The answer zett42 gave is correct. Here is how you would implement it in your solution:
$errorAction = "STOP"
Try{
$errorMsg = "New-Item failed"
New-Item -ItemType Directory -Name "Script" -Path "C:\Temp\" -Force -ErrorAction $errorAction
$errorMsg = "Copy-Item failed"
Copy-Item -Path $FilePath_ps1 -Destination C:\temp\script -Force -ErrorAction $errorAction
$errorMsg = "Set-Content failed"
Set-Content -Value "test" -Path "C:\Temp\Script\test.txt" -Force -ErrorAction $errorAction
}Catch{
$errorMsg + " with error: $_"
}
The output would be for instance:
Copy-Item failed with error: Cannot bind argument to parameter 'Path'
because it is null.
I have added the ErrorAction to make sure it stops on every error right after the execution.
I managed to get rid of the message by changing line 53 to :
New-Item -Path $sFullPath -ItemType File -Force
Which also allows removal of the Test-Path above this (thanks to -Force), But I don't understand why New-Item would try to create a new folder when -ItemType File has been specified, AND the path and name have both been provided ...
I am trying to use Logging_Functions.ps1 Module which I got here.
This is how I am calling it:
."\\DC1\NETLOGON\PSSubs\Logging_Functions.ps1"
Log-Start -LogPath "\\DC1\NETLOGON\PSSubs" -LogName "Test_Log.log" -ScriptVersion "1.5"
As per the documentation. However, when running the above I am seeing this annoying message:
New-Item : The file '\DC1\NETLOGON\PSSubs' already exists.
At \DC1\NETLOGON\PSSubs\Logging_Functions.ps1:53 char:5
+ New-Item -Path $LogPath -Value $LogName -ItemType File
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (\DC1\NETLOGON\PSSubs:String) [New-Item], IOException
+ FullyQualifiedErrorId : NewItemIOError,Microsoft.PowerShell.Commands.NewItemCommand
Even though this error appears, the file is created and I have no idea why it is complaining about the folder name, as line 53 is not asking it to create the folder.
When I run the exact same line inside the actual Logging_Functions.ps1 file, it works without error. I've included the Log-Start function below (which I altered slightly on line 53 to replace -Value with -Name as this seems correct):
Function Log-Start{
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true)][string]$LogPath,
[Parameter(Mandatory=$true)][string]$LogName,
[Parameter(Mandatory=$true)][string]$ScriptVersion
)
Process{
$sFullPath = $LogPath + "\" + $LogName
#Check if file exists and delete if it does
If((Test-Path -Path $sFullPath)){
Remove-Item -Path $sFullPath -Force
}
#Create file and start logging
New-Item -Path $LogPath -Name $LogName -ItemType File
Add-Content -Path $sFullPath -Value "***************************************************************************************************"
Add-Content -Path $sFullPath -Value "Started processing at [$([DateTime]::Now)]."
Add-Content -Path $sFullPath -Value "***************************************************************************************************"
Add-Content -Path $sFullPath -Value ""
Add-Content -Path $sFullPath -Value "Running script version [$ScriptVersion]."
Add-Content -Path $sFullPath -Value ""
Add-Content -Path $sFullPath -Value "***************************************************************************************************"
Add-Content -Path $sFullPath -Value ""
#Write to screen for debug mode
Write-Debug "***************************************************************************************************"
Write-Debug "Started processing at [$([DateTime]::Now)]."
Write-Debug "***************************************************************************************************"
Write-Debug ""
Write-Debug "Running script version [$ScriptVersion]."
Write-Debug ""
Write-Debug "***************************************************************************************************"
Write-Debug ""
}
}
Can anyone please help explain what the difference is here? Why would one way cause an error and not the other, when they are supposedly doing the exact same thing? Thanks!
You can change all of this:
#Check if file exists and delete if it does
If((Test-Path -Path $sFullPath)){
Remove-Item -Path $sFullPath -Force
}
#Create file and start logging
New-Item -Path $LogPath -Name $LogName -ItemType File
To the following one liner, as the -Force will overwrite any file that already exists:
New-Item -Path $sFullPath -ItemType File -Force
I am looking to log the output of my script to a log file. But not able to get the output to a file.
Set-ExecutionPolicy RemoteSigned
$server_names = Get-Content "E:\Bibin\Copy\complist.txt"
$Folder=$((Get-Date).ToString('yyyy-MM-dd'))
$Logfile = "E:\Bibin\Copy\copy.log"
Function LogWrite
{
Param ([string]$logstring)
Add-content $Logfile -value $logstring
}
Foreach ($server in $server_names)
{
$FileExists = Test-Path "\\$server\C$\temp\TEST\*"
If ($FileExists -eq $True)
{
New-Item "\\$server\C$\temp\TEST\$Folder" -type directory
Move-Item "\\$server\C$\temp\TEST\*" -Destination "\\$server\C$\temp\TEST\$Folder" -force
Copy-Item "\\DC1NAS02P00\data\IT\CPS\Projects\NGNet\CpsServerUpgradeFiles\Upgrade Version 2.0\2003_Files\*.*" -Destination "\\$server\C$\temp\TEST" -Recurse
}
Else
{
New-Item "\\$server\C$\temp\TEST" -type directory
Copy-Item "\\DC1NAS02P00\PDSdata\IT\CPS\Projects\NGNet\CpsServerUpgradeFiles\Upgrade Version 2.0\2003_Files\*.*" -Destination "\\$server\C$\temp\TEST" -Recurse
}
}
Also I want some time gap between New_item and Move-item, since it is saying file is already in use ..
Thanks
Bibin
instead of using Add-Content use Out-File.
Also try robocopy instead of copy, this will wait for the locks to release before copying.
I am running the below script. If the Copy-Item command is successfully completed, it does not show any messages such as how many files are copied. How do I capture this?
Note: I also need to capture the error message which the script is doing correctly.
$LogFile = "P:\users\Logname.log"
$msg = Copy-Item P:\Bkp_20130610\* P:\users -force -recurse -ErrorAction SilentlyContinue
if (-not $?)
{
msg1 = $Error[0].Exception.Message
Write-Host "Encountered error. Error Message is $msg1."
exit
}
$msg > $LogFile
Write-Host "Hello"
You can obtein a list of copied files in this way
$files = copy-item -path $from -destination $to -passthru
pipe it to | ? { -not $_.psiscontainer } if you are copying folder and you don't want them in the count
then use
$files.count
You can use the -Verbose switch with the Copy-Item cmdlet:
$msg=Copy-Item P:\Bkp_20130610\* P:\users -force -recurse -ErrorAction SilentlyContinue -Verbose
Within ISE, I've tried both the below. Neither is working. The only way is to clear $error and test after the copy attempt. Any suggestions?
$cpy = Copy-Item -Path "D:\~a\2K0NVK0.xt" -Destination "D:\~Bkup-F\2K0NVK10.txt" -Force -passthru -ErrorAction SilentlyContinue
if($cpy){ $cpy # only displays on successful copy }
Try{
Copy-Item -Path "D:\~a\2K0NVK0.xt" -Destination "D:\~Bkup-F\2K0NVK10.txt" -Force -ErrorAction SilentlyContinue
} Catch { write-host "Hit a bug!" # not being displayed }
A try/catch only works when ErrorAction is set to Stop.