Author Posts

May 14, 2015 at 12:21 am

Hi,

I've written this script that looks at a text file for certain fields then adds an App-v application into SCCM.

I'm pretty pleased but believe i can only use "try...catch" once, so how can i put in some error catching ?

#Set Application details to add to SCCM from text template

$DefaultAppPath = "\\theaa.local\dfsdata\sccm\software\"

$Content = get-content "\\aa-cm002v\e$\scripts\AppV_Template.txt"
$App_DT_Name = $Content[3]
$App_Name = $Content[5]
$App_Source_Location = $Content[7]
$OptRef =
$Publisher = $Content[9]
$SoftVer = $Content[11]
$Folder = $Content[13]

#Full location path

$LocationFull = "$DefaultAppPath"+"$App_Source_Location"

#Set Module and CMsite directory

$ModulePath = "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin"
$SetDrive = "set-location AAC:"

#Import module

Import-Module $ModulePath\ConfigurationManager.psd1

#Set directory

Invoke-expression $SetDrive

#Create new application. "#" if the below command is required.

Try {
New-CMApplication -Name $App_Name -AutoInstall $true -Publisher $Publisher -SoftwareVersion $SoftVer
Write-Output "Application Created Successfully"
exit 0 }
Catch {
Write-Output "Failed to create Application"
Exit 1001 }

#Create New Application deployment file

Try {
Add-CMDeploymentType -ApplicationName $App_Name -DeploymentTypeName $App_DT_Name -AppV5xInstaller -ForceForUnknownPublisher $true -InstallationFileLocation $LocationFull
Write-Output "Application Deployment file Created"
exit 0 }
Catch {
Write-Output "Failed to create Application Deployment file"
Exit 1001 }

#Move Application to folder

Try {
$GetApp = Get-CMApplication -name $App_Name
Move-CMObject -FolderPath ".\Application\Publisher\$Folder" -InputObject $GetApp
Write-Output "Application moved to $folder folder"
exit 0 }
Catch {
Write-Output "Failed to move Application to Folder"
Exit 1001 }

May 14, 2015 at 3:12 am

I have a similar application that uses a ton of try catches.
Its a really messy error handling system and the best you can do is call a function for each catch to display generic info.
With mine I always pass at least two parameters to this function – $_ and a user friendly text message.
Sometimes I add an object to be deleted as some of my application create an object then do lots of things to it.
If one of those "things" fails then passing the object allows me to delete it so you dont leave half built garbage behind.

Cheers
David Z

May 14, 2015 at 4:04 am

You can use try/catch as many times as you need. You can even have another try/catch nested inside another try, catch or finally block, if needed.

May 14, 2015 at 4:23 am

You can also use execute commands in the catch block. It's not just for displaying generic info. I've actually used try/catch for decision making in cases where cmdlets would throw a terminating error if there was no data to display.

May 14, 2015 at 4:48 am

Awesome, it works like a dream. One month into my learning and i'm really proud i've done this by myself !!

##Import App-V application

#Set Application details to add to SCCM from text template
$DefaultAppPath = "\\theaa.local\dfsdata\sccm\software\"

$Content = get-content "\\aa-cm002v\e$\scripts\AppV_Template.txt"
$App_DT_Name = $Content[3]
$App_Name = $Content[5]
$App_Source_Location = $Content[7]
$OptRef =
$Publisher = $Content[9]
$SoftVer = $Content[11]
$Folder = $Content[13]
$DPGroup = "All Distribution Points"

#Full location path
$LocationFull = "$DefaultAppPath"+"$App_Source_Location"

#Set Module, CMsite directory and revert back to orginal prompt
$ModulePath = "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin"
$SetDriveStart = "set-location AAC:"
$SetDriveEnd = "set-location E:"

#Import module
Import-Module $ModulePath\ConfigurationManager.psd1

try {
#Set directory
Invoke-expression $SetDriveStart

#Create new application. "#" if the below command is required.
Try {
New-CMApplication -Name $App_Name -AutoInstall $true -Publisher $Publisher -SoftwareVersion $SoftVer | out-null
Write-Output "Created $App_Name succesfully" }
Catch {
Write-Output "Creating $App_Name failed" }

#Create New Application deployment file
Try {
Add-CMDeploymentType -ApplicationName $App_Name -DeploymentTypeName $App_DT_Name -AppV5xInstaller -ForceForUnknownPublisher $true -InstallationFileLocation $LocationFull | out-null
Write-Output "Created $App_DT_Name succesfully" }
Catch {
Write-Output "Creating $App_DT_Name failed" }

#Move Application to folder
Try {
$GetApp = Get-CMApplication -name $App_Name
Move-CMObject -FolderPath ".\Application\Publisher\$Folder" -InputObject $GetApp
Write-Output "Moved $App_Name to $Folder succesfully" }
Catch {
Write-Output "Moving $App_Name to $Folder failed" }

#Distribute application
Try {
Start-CMContentDistribution -ApplicationName $App_Name -DistributionPointGroupName $DPGroup
Write-Output "Distributed content to $DPGroup" }
Catch {
Write-Output "Failed to Distribute content to $DPGroup" }

#Set location back to E drive
Invoke-expression $SetDriveEnd

Write-Output "Virtual App created in SCCM and currently distributing"
exit 0 }
Catch {
Write-Output "Failed to Create Virtual App"
Exit 1001 }

May 14, 2015 at 6:14 am

As you learn Powershell, keep in mind that not indenting your code results in the death of kittens and puppies are kicked. As your experience grows, so will your scripts, so you need to learn indention to see the flow of the script and be able to troubleshoot. Also, there isn't really a need to specify "Write-Output" and in your first try\catch (under the main try catch), I updated your catch. You are capturing something failed, but not why. Minimally, grabbing the exception message will get you troubleshooting information. Would you rather have this "Failed to Create Virtual App" or "Failed to Create Virtual App. Access Denied." as your message? Which one can your troubleshoot faster?

##Import App-V application

#Set Application details to add to SCCM from text template
 $DefaultAppPath = "\\theaa.local\dfsdata\sccm\software\"

$Content = get-content "\\aa-cm002v\e$\scripts\AppV_Template.txt"
$App_DT_Name = $Content[3]
$App_Name = $Content[5]
$App_Source_Location = $Content[7]
$OptRef =
$Publisher = $Content[9]
$SoftVer = $Content[11]
$Folder = $Content[13]
$DPGroup = "All Distribution Points"

#Full location path
$LocationFull = "$DefaultAppPath"+"$App_Source_Location"

#Set Module, CMsite directory and revert back to orginal prompt
$ModulePath = "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin"
$SetDriveStart = "set-location AAC:"
$SetDriveEnd = "set-location E:"

#Import module
 Import-Module $ModulePath\ConfigurationManager.psd1

try {
     #Set directory
     Invoke-expression $SetDriveStart

    #Create new application. "#" if the below command is required.
     Try {
         New-CMApplication -Name $App_Name -AutoInstall $true -Publisher $Publisher -SoftwareVersion $SoftVer | out-null
         Write-Output "Created $App_Name succesfully" 
     }
     Catch {
        "Creating {0} failed. {1}" -f $App_Name, $_.Exception.Message
     }

    #Create New Application deployment file
     Try {
         Add-CMDeploymentType -ApplicationName $App_Name -DeploymentTypeName $App_DT_Name -AppV5xInstaller -ForceForUnknownPublisher $true -InstallationFileLocation $LocationFull | out-null
         Write-Output "Created $App_DT_Name succesfully" 
     }
     Catch {
         Write-Output "Creating $App_DT_Name failed" 
     }

    #Move Application to folder
     Try {
         $GetApp = Get-CMApplication -name $App_Name
         Move-CMObject -FolderPath ".\Application\Publisher\$Folder" -InputObject $GetApp
         Write-Output "Moved $App_Name to $Folder succesfully" 
     }
     Catch {
        Write-Output "Moving $App_Name to $Folder failed"
     }

    #Distribute application
     Try {
         Start-CMContentDistribution -ApplicationName $App_Name -DistributionPointGroupName $DPGroup
         Write-Output "Distributed content to $DPGroup"
     }
     Catch {
        Write-Output "Failed to Distribute content to $DPGroup" 
     }

    #Set location back to E drive
    Invoke-expression $SetDriveEnd

    Write-Output "Virtual App created in SCCM and currently distributing"
    exit 0 
 }
 Catch {
    Write-Output "Failed to Create Virtual App"
    Exit 1001 
}

May 14, 2015 at 6:23 am

The lack of indentation might be just be on the forums, because the OP didn't use the [ pre ] and [ /pre ] tags (which hopefully show up because I stuck in some extra whitespace.)

May 14, 2015 at 6:36 am

Hi Rob,

Great tip with the error output, wasn't aware of that.
Dave is right, i did indent the script but its not formatted very well when i pasted it.

Thanks everyone.

May 14, 2015 at 6:50 am

Kittens lives are at stake here, use your [ pre ] and [ /pre ] tags. 🙂

May 14, 2015 at 7:20 am

I will do in future...can't risk the kittens !

May 15, 2015 at 3:14 am

If I may make a suggestion; don't use Write-Output unless it is actually output that needs to be handled in some way outside of the script. Use Write-Verbose/Write-Warning/Write-Error to write information to screen, and Write-Output to pass data along the pipeline.

Another suggestion, don't return errorcodes. That's so 1990s. PowerShell has exceptional exception handling, which you yourself have discovered. Throw a useful error instead of 1001.

[cmdletbinding()] #required to get -Verbose functionality
param()

##Import App-V application
 
#Set Application details to add to SCCM from text template
$DefaultAppPath = "\\theaa.local\dfsdata\sccm\software\"
 
$Content = get-content "\\aa-cm002v\e$\scripts\AppV_Template.txt"
$App_DT_Name = $Content[3]
$App_Name = $Content[5]
$App_Source_Location = $Content[7]
$OptRef =
$Publisher = $Content[9]
$SoftVer = $Content[11]
$Folder = $Content[13]
$DPGroup = "All Distribution Points"
 
#Full location path
$LocationFull = "$DefaultAppPath"+"$App_Source_Location"
 
#Set Module, CMsite directory and revert back to orginal prompt
$ModulePath = "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin"
$SetDriveStart = "set-location AAC:"
$SetDriveEnd = "set-location E:"
 
#Import module
Import-Module $ModulePath\ConfigurationManager.psd1
 
try {
     #Set directory
     Invoke-expression $SetDriveStart
 
    #Create new application. "#" if the below command is required.
     Try {
         New-CMApplication -Name $App_Name -AutoInstall $true -Publisher $Publisher -SoftwareVersion $SoftVer | out-null
         Write-Verbose "Created $App_Name succesfully" 
     }
     Catch {
         throw ("Creating {0} failed. {1}" -f $App_Name, $_.Exception.Message)
     }
 
    #Create New Application deployment file
     Try {
         Add-CMDeploymentType -ApplicationName $App_Name -DeploymentTypeName $App_DT_Name -AppV5xInstaller -ForceForUnknownPublisher $true -InstallationFileLocation $LocationFull | out-null
         Write-Verbose "Created $App_DT_Name succesfully" 
     }
     Catch {
         throw "Creating $App_DT_Name failed" 
     }
 
    #Move Application to folder
     Try {
         $GetApp = Get-CMApplication -name $App_Name
         Move-CMObject -FolderPath ".\Application\Publisher\$Folder" -InputObject $GetApp
         Write-Verbose "Moved $App_Name to $Folder succesfully" 
     }
     Catch {
         throw "Moving $App_Name to $Folder failed"
     }
 
    #Distribute application
     Try {
         Start-CMContentDistribution -ApplicationName $App_Name -DistributionPointGroupName $DPGroup
         Write-Verbose "Distributed content to $DPGroup"
     }
     Catch {
         throw "Failed to Distribute content to $DPGroup" 
     }
 
    #Set location back to E drive
    Invoke-expression $SetDriveEnd
 
    Write-Verbose "Virtual App created in SCCM and currently distributing"
}
Catch {
    Write-Error "Failed to Create Virtual App: $_"
}

May 15, 2015 at 3:17 am

Heck if you want to go crazy with exception handling, read up on how to do custom exceptions.

Custom errors

This post goes into a bit of detail.

May 15, 2015 at 5:11 am

Thank you Martin, very helpful. Much appreciated.

May 15, 2015 at 5:19 am

Martin,

I've attempted the script with your amendments on an App i know should fail as its already in SCCM.

I now get the "Red error writing" instead of an nicely outputted error. Have i missed something ?

May 15, 2015 at 5:45 am

Well it all depends on how you handle the exception. In my example I use Write-Error which produces the fancy red text. You could do Write-Warning instead, or something completely different. That's why it's called exception handling. You handle exceptions however you like.

May 15, 2015 at 6:29 am

Arrrr....i see. Thanks. I'm currently going through Jeff Hicks brilliant videos on the Pluralsight website. But all this is great to know.