4
votes

I'm using a power shell script to copy some files from my computer to a USB drive. However, even though I'm catching the System.IO exception, I still get the error at the bottom. How do I properly catch this exception, so it shows the message in my Catch block.

CLS

$parentDirectory="C:\Users\someUser"
$userDirectory="someUserDirectory"
$copyDrive="E:"
$folderName="Downloads"
$date = Get-Date
$dateDay=$date.Day
$dateMonth=$date.Month
$dateYear=$date.Year
$folderDate=$dateDay.ToString()+"-"+$dateMonth.ToString()+"-"+$dateYear.ToString();


Try{
     New-Item -Path $copyDrive\$folderDate -ItemType directory
     Copy-Item $parentDirectory\$userDirectory\$folderName\* $copyDrive\$folderDate
   }
Catch [System.IO]
{
    WriteOutput "Directory Exists Already"
}


New-Item : Item with specified name E:\16-12-2014 already exists.
At C:\Users\someUser\Desktop\checkexist.ps1:15 char:9
+         New-Item -Path $copyDrive\$folderDate -ItemType directory
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceExists: (E:\16-12-2014:String) [New-Item], IOException
    + FullyQualifiedErrorId : DirectoryExist,Microsoft.PowerShell.Commands.NewItemCommand
4

4 Answers

6
votes

If you want to catch an exception for a New-Item call, you need to do two things:

  1. Set $ErrorActionPreference = "Stop" by default its value is Continue. This will make the script Stop in case of exceptions.

  2. Trap the correct exception and/or all of them

if you want to trap all exceptions, just use catch without arguments:

catch 
{
    Write-Output "Directory Exists Already"
}

if you want to trap a specific exception, first find out which one it is, by checking the value of

$error[0].Exception.GetType().FullName

and in your case the value is:

System.IO.IOException

then you can use this value as an argument to your catch, like this:

catch [System.IO.IOException]
{
    Write-Output "Directory Exists Already"
}

Source worth reading: An introduction to Error Handling in Powershell

1
votes

If you add -ErrorAction Stop to the line creating the directory you can catch [System.IO.IOException](not [System.IO]). You should also catch all other exceptions that can potentially occur:

try {
   New-Item -Path $copyDrive\$folderDate -ItemType directory -ErrorAction Stop
   Copy-Item $parentDirectory\$userDirectory\$folderName\* $copyDrive\$folderDate -ErrorAction Stop
}

catch [System.IO.IOException] {
   WriteOutput $_.Exception.Message
}

catch {
   #some other error
}
1
votes

In addition you can spot exactly Directory Exist (unfortunally no File Exist error type for files).

$resExistErr=[System.Management.Automation.ErrorCategory]::ResourceExists

try {
        New-Item item -ItemType Directory -ErrorAction Stop
    }
    catch [System.IO.IOException] 
    {
        if ($_.CategoryInfo.Category -eq $resExistErr) {Write-host "Dir Exist"}
    }
0
votes

I don't suggest actually catching the error in this case. Although that may be the correct action in general, in this specific case I would do the following:

$newFolder = "$copyDrive\$folderDate"

if (-not (Test-Path $newFolder)) {
    New-Item -Path $newFolder -ItemType directory
    Copy-Item $parentDirectory\$userDirectory\$folderName\* $newFolder
} else {
    Write-Output "Directory Exists Already"
}