Bug copying item with Literalpath or intended? - powershell

Consider the following really simple code:
Try {
Copy-Item -Path '\\server\g$\thisfolder\thisfiledoesntexist.ini' -Destination 'c:\temp' -ErrorAction Stop
}
Catch {
"Ran into an issue: $_"
}
This will work fine to trap the error for a non-existent souce file. However the following will not - there's no error generated.
Try {
Copy-Item -LiteralPath '\\?\UNC\server\g$\thisfolder\thisfiledoesntexist.ini' -Destination 'c:\temp' -ErrorAction Stop
}
Catch {
"Ran into an issue: $_"
}
However...this WILL trap the error
Try {
Get-ChildItem -LiteralPath '\\?\UNC\server\g$\thisfolder\thisfiledoesntexist.ini' -ErrorAction Stop | Copy-Item
}
Catch {
"Ran into an issue: $_"
}
This is the first time I've had occasion to use Literal paths - is this behaviour intended/expected?

I think you've found a bug with Copy-Item under Windows PowerShell. It seems including a ? character anywhere in input for either -Path or -LiteralPath stops an error from being trapped for a non-existent path.
The bug seems to have been fixed on PowerShell Core, where your code above does result in an exception being caused.

Related

Try Catch Query Powershell

Can anyone advise why when I run this script I still get a generic error generated by powershell? It is nested in an IF statement originally.
try {
Remove-Item -Path "C:\Users$env:USERNAME\AppData\Local\Microsoft\Outlook" -Force -Recurse | Out-Null
} catch { "Appdata Cache does not exist!"
}
catch only works on terminating errors. So you’ll have to change your try statement to. Also you’re missing a “\” in your path
Try{
Remove-Item C:\Users\$env:USERNAME\AppData\Local\Microsoft\Outlook" -Force -Recurse -ErrorAction Stop
}Catch{
“Appdata cache doesn’t exist”
}
Also Remove-Item doesn’t return an object so you don’t need to redirect it to null

Powershell is missing the terminator: " and Missing closing '}' in statement block or type definition

I am new on powershell and I have an issue. I am trying to make a script that cleans all my directories older than 30 days, but when I run it, it breaks. Does anyone know what problem I have?
$fromNDays = $args[0]
$cutOffDate = (Get-Date).AddDays(-$fromNDays)
$directoriesToDelete = Get-ChildItem -Path $path -Attributes Directory -Filter r* | Where-Object LastWriteTime -le $cutOffDate
echo "deleting from $cutOffDate"
cd $(Agent.ReleaseDirectory)
cd ..\..
pwd
Foreach($directoryToDelete in $directoriesToDelete)
{
if($directoryToDelete.Name -ne "ReleaseRootMapping")
{
try
{
echo "Deleting directory $directoryToDelete"
Remove-Item –path $directoryToDelete.FullName -Force -Recurse
}
catch
{
echo "Failed deleting $directoryToDelete.FullName"
}
}
}
The error that I have when it runs is:
echo "Failed deleting $directoryToDelete.FullName"
+ ~
2020-03-09T09:55:23.3827859Z ##[error]The string is missing the terminator: ".
deleteReleaseDirectoryFrom30.ps1:12 char:5
2020-03-09T09:55:23.3832466Z ##[error]+ {
2020-03-09T09:55:23.3836221Z ##[error]Missing closing '}' in statement block or type definition.
This error apears on line 12, 23, 8 and 10
In your code, the script doesn't know, that $directoryToDelete.FullName is a variable.
So first, put them one into brackets:
try{
echo "Deleting directory ${directoryToDelete}"
Remove-Item –path ${directoryToDelete.FullName} -Force -Recurse
}
catch
{
echo "Failed deleting ${directoryToDelete.FullName}"
}
As described here : https://github.com/PowerShell/vscode-powershell/issues/1308, there is this problem with PS and VSCode.
According to the answers on GitHub, a solution is to paste your code in the Powershell ISE (you can do a simple Windows search for that), and save using it. Then you can continue coding with VsCode or anything else you use.
Hope this helps you, even though I'm a bit late here...

Handle Directory Exists Exception

I am new to PowerShell. I have a piece of code which checks whether a folder "ilalog" exists or not. When I run this script first time, it is checking for the folder "ilalog",if it does not exist,it is creating. When I run the script second time. I receive the error below:
An item with the specified name D:\Temp\ilalog already exists
"FullyQualifiedErrorId :
DirectoryExist,Microsoft.PowerShell.Commands.NewItemCommand".
how to handle this exception
I have tried using try and Catch block
$rgflder="ilalog"
[bool]$checkrg=Test-Path D:\Gdump\$rgfolder -PathType Any
if ( $checkrg -eq $False)
{
try{
New-Item -Path "D:\Gdump" -Name "$rgflder" -ItemType "directory"
}
catch [System.IO.IOException]
{
if ($_.CategoryInfo.Category -eq $resExistErr) {Write-host "Dir Exist"}
}
}
else
{
Write-Output "Directory Exists"
}
If you want to continue processing your script while taking action based on an error type, a simple way is to just examine the $error variable. Using Trap may be an option as well.
$error.clear()
New-Item -Path "D:\Gdump" -Name "$rgflder" -ItemType "directory"
if ($error[0].Exception.GetType().Fullname -eq 'System.IO.IOException') {
"Dir Exists"
}
else {
"Dir was created"
}
If you want to use try-catch, you need to treat your non-terminating error as a terminating error to activate the catch block. You can do this with -ErrorAction Stop.
try {
New-Item -Path "D:\Gdump" -Name "$rgflder" -ItemType "directory" -ErrorAction Stop
}
catch [System.IO.IOException]
{
"Exception caught!"
}
Alternatively, you can manage this within your session by setting $ErrorActionPreference = 'Stop', which will apply to all commands within that session.
Keep in mind that the value passed to -ErrorAction overrides the setting in $ErrorActionPreference. Also, error action settings have no affect on terminating errors. So you cannot expect to set -ErrorAction Continue and have code continue processing on a terminating error.
Many commands return objects that may or may not be terminating errors. You will find more success explicitly, specifying when you want to throw a terminating error.
You can read more about error action preference at About Common Parameters. I actually like Everything About Exceptions for exception handling in PowerShell.
Why not simply do like below?
$rgflder="ilalog"
# combine the path and foldername
$rgPath = Join-Path -Path 'D:\Gdump' -ChildPath $rgflder
# test if the folder already exists
if (Test-Path $rgPath -PathType Container) {
Write-Output "Directory Exists"
}
else {
# if not, create the new folder
try {
$null = New-Item -Path $rgPath -ItemType Directory -ErrorAction Stop
Write-Output "Created directory '$rgPath'"
}
catch {
# something terrible happened..
Write-Error "Error creating folder '$rgPath': $($_.Exception.Message)"
}
}

PowerShell Remove Junction

As of Windows 10 PowerShell is finally capable of creating Junctions and links natively.
Howerver the Remove-Item function seems to be unaware of the junction and tries to remove the directory asking for confirmation and if it should recursively delete items within.
So, the question is:
Is there a way to remove a junction using PowerShell native Cmdlets? (i.e. without calling cmd)
Is there a way to remove a junction using PowerShell?
Currently, at least in PowerShell v5, this is considered "fixed". What you can do is use the -Force switch, else you will get an error calling the path an NTFS junction. The reason that I at least use the quotes on fixed is that using the switch will still make the message about children in the directory show up. Selecting Y will still only delete the junction in my testing using PSv5.
Remove-Item "C:\temp\junction" -Force -Confirm:$False
If that doesn't work for you or you don't have v5 you can use the .Net method to delete a directory. This appears to work correctly as well.
[io.directory]::Delete("C:\temp\junction")
have a try on this "command-let":
cmd /c rmdir .\Target
source:Powershell Remove-Item and symbolic links
Simple command -
rm [path of file] -Force
After search by Google for a long time, I found the answer:
function Remove-Any-File-Force ($Target) {
if ( Test-Path -Path "$Target" ){
& $env:SystemRoot\System32\ATTRIB.exe -S -H -R "$Target" >$null 2>$null
} else {
return
}
$TargetAttributes = (Get-Item -Path $Target -Force).Attributes.ToString()
if ($TargetAttributes -match "ReparsePoint") {
if ($TargetAttributes -match "Archive") {
Remove-Item -Path "$Target" -Force
} else {
try {
& $env:SystemRoot\System32\cmd.exe /c rmdir /Q "$Target" >$null 2>$null
} catch {
try {
[io.directory]::Delete("$Target")
} catch {
Remove-Item -Path "$Target" -Force
}
}
}
} else {
if ($TargetAttributes -match "Directory") {
Remove-Item -Path "$Target" -Force -Recurse
} else {
Remove-Item -Path "$Target" -Force
}
}
}

PowerShell module terminating unexpectedly

A PowerShell module I'm working on is behaving very strangely...
I have the following code in a RestoreTestFiles.psm1 file (located in %USERPROFILE%\My Documents\WindowsPowerShell\Modules\RestoreTestFiles\):
Function Restore-TestFiles([string]$backupDir, [string]$destinationDir, [bool]$overwrite)
{
if (!(Test-Path $backupDir))
{
Write-Host "Error, $backupDir does not exist."
return
}
if ($backupDir.EndsWith("\*"))
{
Write-Host "$backupDir ends with \*!"
}
else
{
Write-Host "$backupDir does not end with \*."
}
if ($overwrite)
{
Copy-Item -Path $backupDir -Destination $destinationDir -Recurse -Force
}
else
{
Copy-Item -Path $backupDir -Destination $destinationDir -Recurse
}
Write-Host "Files sucessfully copied from $backupDir to $destinationDir."
}
And I call the function like this:
Import-Module RestoreTestFiles
Restore-TestFiles "C:\some\path\*" "C:\someOther\path\"
For some reason, the output is only either
C:\some\path\* ends with \*!
or
C:\some\path does not end with \*.
But it never runs the Copy-Item or the final Write-Host. If I set a breakpoint, the execution is all messed up:
Stops at breakpoint set on if (!(Test-Path $backupDir))
I step into and it goes to if ($backupDir.EndsWith("\*"))
I step into and it goes to Write-Host "$backupDir ends with \*!"
I step into and it stops running.
Why is the script terminating before it is supposed to?
Edit: I tried moving the function to a regular .ps1 script and called the function from the same script and it works fine...it only terminates prematurely if the function is in a module and called from outside the module. What gives?
I was able to fix this by completely closing all open instances of the PowerShell ISE and re-opening my module.