Install computer-targeted application during OS deployment via PowerShell and ConfigMgr 2012

A few months ago I did a blog post about installing user-targeted applications during operating system deployments via PowerShell and ConfigMgr. This time I will do a similar post, on request, about installing computer-targeted applications during operating system deployments. Yes, I know it might be worth a discussing about why someone is still using computer-targeted deployments, but that will not be a part of this blog post.

Script

A big part of this script, and by that also this post, might look familiar, as it’s based on the previous script for user-targeted applications. Just like with that previous script I will go through all the key steps of the script. The following five steps make sure that I only get the applications that are required for the computer. Also, in case there is nothing targeted a new variable will be created to prevent the Install Application step from starting.

Step 1 – Get the container node

The first step is to get the container node of the application deployment collections. This will be used to make sure that only (device-)collections used for application deployments will be queried. This information can be retrieved in WMI in the class SMS_ObjectContainerNode. This class shows the different folders in the console and its location. The property ObjectTypeName can be used to see the type of objects in the folder. In my case, I occasionally use identical folder names. So to get the container node information that I need, I use the following code snippet:

$ContainerNodeId = (Get-WmiObject -ComputerName $SiteServer ` -Class SMS_ObjectContainerNode ` -Namespace root/SMS/site_$SiteCode ` -Filter "Name='$Container' and ` ObjectTypeName='SMS_Collection_Device'").ContainerNodeId

Step 2 – Get the collections

The second step is to get the collections within the container with a specific collection member. This information can be retrieved in WMI via the classes SMS_ObjectContainerItem and SMS_FullCollectionMembership. This first class shows the relation between an container and the objects within an container and the second class shows the different collection members and their memberships. So to get the collections within the container and with a specific collection member, I need to join these two classes. To do this, I use the following code snippet:

$CollectionIds = (Get-WmiObject -ComputerName $SiteServer ` -Namespace root/SMS/site_$SiteCode -Query "SELECT fcm.* ` FROM SMS_FullCollectionMembership fcm, ` SMS_ObjectContainerItem oci ` WHERE oci.ContainerNodeID='$ContainerNodeId' ` AND fcm.Name='$ResourceName' ` AND fcm.CollectionID=oci.InstanceKey").CollectionId

Step 3 – Get the targeted applications

The third step is to get the applications that are targeted to the filtered collections. This makes sure that only applications deployed to collections, of which the device is a member, will be filtered. This information can be found in WMI in the class SMS_ApplicationAssignment. The property OfferTypeID can be used to see if the deployment is required or available and I only want to have the required applications. So this makes that I use the following code snippet:

$ApplicationNames = (Get-WmiObject -ComputerName $SiteServer ` -Class SMS_ApplicationAssignment ` -Namespace root/SMS/site_$SiteCode ` -Filter "TargetCollectionID='$CollectionId' and ` OfferTypeID='0'").ApplicationName

Step 4 – Create the task sequence variables

The fourth step is to create task sequence variables for the applications that have to be installed during the OS deployment. For every application I create a task sequence variable named APPIdXX with the value of the application. To achieve this I use the following code snippet:

foreach ($ApplicationName in $ApplicationNames) { $Id = "{0:D2}" -f $Count $AppId = "APPId$Id" $TSEnv.Value($AppId) = $ApplicationName $Count = $Count + 1 }

Step 5 – Create an extra task sequence variable

The fifth, and last, step is to create a task sequence variable in case there are no applications targeted to the computer. This variable can be used to skip the Install application step, to prevent it from failing. As a Install application step will fail when there is a base variable configured, but there are none supplied during the task sequence. To achieve this I use the following code snippet:

else { $TSEnv.Value("SkipApplications") = "True" break }

>> The complete script is available via download here on the TechNet Galleries! <<

Usage

Now download the PowerShell script via the link above and add the PowerShell script to an old-school Package, so it will be available for a task sequence. Then create a standard Install an existing image package task sequence. Now edit the task sequence and make sure the following steps are included:

  • InstCompTargAdd a step Run PowerShell Script with the following settings:
    • Package: <NameOfPackageThatContainsTheScript>
    • Script name: <NameOfTheScript>
    • Parameters: %_SMSTSMachineName%
      • Note: The script needs more input parameters, but I usually add those parameters directly in the script as they are “static” per environment.
    • PowerShell execution policy: Bypass
  • Add a step Install Application with the following settings:
    • Select Install applications according to dynamic variable list
    • Base variable name: APPId
    • Add Condition Task Sequence Variable SkipApplications not exists

Note: The computer account running the script needs read access to ConfigMgr. So in most cases this would mean that the Domain Computers need read access to ConfigMgr. This can be achieved via the build-in role of Read-only Analyst

54 thoughts on “Install computer-targeted application during OS deployment via PowerShell and ConfigMgr 2012

  1. Hi Peter,

    I tried running your script and I get the following error within task sequence. Its giving me access denied errors but I am using domain admin account (Administrator) to run SCCM, TS etc. Just to be sure, I went ahead and added the administrator account to Wmi containers and provided full access.

    For the parameters, I am using the following

    $SiteCode = “P01”
    $SiteServer = “SCCM-1602.mydomainname.com”
    $Container = “Profiles”

    My collection where all the software deployments are targeted to is placed under following folder structure in SCCM

    Device Collections > OSD > Profiles so that is why $container is set to Profiles.

    Any idea what am I doing wrong here?

    C/P from my smsts.log file…

    Get-WmiObject : Access is denied. (Exception from HRESULT: 0x80070005 RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    (E_ACCESSDENIED)) RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    At RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    C:\_SMSTaskSequence\Packages\P0100026\Get-TargetedApplications_Computer.ps1:17 RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    char:25 RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    + … erNodeId = (Get-WmiObject -ComputerName $SiteServer -Class SMS_Object … RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    + CategoryInfo : NotSpecified: (:) [Get-WmiObject], UnauthorizedA RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    ccessException RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.Pow RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    erShell.Commands.GetWmiObjectCommand RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    Get-WmiObject : Access is denied. (Exception from HRESULT: 0x80070005 RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    (E_ACCESSDENIED)) RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    At RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    C:\_SMSTaskSequence\Packages\P0100026\Get-TargetedApplications_Computer.ps1:18 RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    char:23 RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    + … ctionIds = (Get-WmiObject -ComputerName $SiteServer -Namespace root/S … RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    + CategoryInfo : NotSpecified: (:) [Get-WmiObject], UnauthorizedA RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    ccessException RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.Pow RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    erShell.Commands.GetWmiObjectCommand RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)
    RunPowerShellScript 3/29/2017 4:45:14 PM 3188 (0x0C74)

  2. Hi Peter,

    I have one question lets say I want to do a new OS installation on computer2 and my current computer is computer1. Can I change the computer lookup for the script to look at computer2? This way all software from his legacy system is installed on the new computer.

    Regards,

    Jeroen Budding

Leave a Comment