Dynamically deploying packages and applications to computers using a Task Sequence via PowerShell in ConfigMgr 2012


Peter van der Woude created an excellent PowerShell script and blog post to dynamically deploy applications to computers via a Task Sequence within ConfigMgr.

At a client recently, I was tasked with implementing this script. I decided that I would embellish the script and add in support for dynamic package deployment and also allow for cross-forest installation, trusted and non-trusted and workgroup client install.

This is achieved by running a section of the script as a service account which is given the Read-Only Analyst role in ConfigMgr.

The complete script can be downloaded from the Technet Galleries here.

Pre-Requisites

The following pre-requisites need to be configured to allow for Application Task Sequence deployment of dynamic apps and packages

  1. The script requires PowerShell v3 and above to run. If executing against Windows 2008 server OS then install .Net 4.0 and WMF 3.0
  2. A service account is required to run the Dynamic Apps/Packages script. This service account needs to be assigned the role of ‘Read-Only Analyst’ within the ConfigMgr 2012 console.
  3. Permissions are assigned for the service account to execute a remote PowerShell session on the ConfigMgr site server .

To do this run the following command on the site server in PowerShell (as administrator).

Set-PSSessionConfiguration microsoft.powershell –ShowSecurityDescriptorUI

Confirm by pressing ‘Y’ then add the relevant AD group and add in execute(invoke) permissions and apply.

DynApp-001

Press ‘Y’ again to confirm.

Creating Applications or Packages for Task Sequence Deployment

The standard method for creating an application or package with ConfigMgr 2012 should be followed but certain caveats exist for them to work as dynamic installs.

  • The maximum number of dynamic applications that can be deployed using the script is 99.
  • If creating a Package installation then an associated install Program needs to be created.
  • Task Sequences are a great way to install applications and their dependencies in a specific order. By changing the installation to a dynamic list there is no way to order the installs. Therefore any dependency chains should be set within the actual package or application. Note it is not possible to link dependencies between applications and package. Dependencies can only be set with the same model type.
  • Each install should be set to ‘allow installation’ from within a Task Sequence, otherwise that particular application or package will fail to install.

For an Application, right click on the application and choose Properties. In the General Information tab select ‘Allow this application to be installed from the Install Application task sequence action without being deployed’

DynApp-002

For a Package, right click the Program and choose Properties

DynApp-003

Select the Advanced tab and choose ‘Allow this program to be installed from the Install Package task sequence action without being deployed’

DynApp-004

  • It is recommended to assign a meaningful ‘Program Name’ to a Package as this will be written to the smsts.log when running the Task Sequence and helpful for troubleshooting if there are any issues.

For example: Install SCOM Agent

DynApp-005

  • It is recommended to use the package model within Task Sequence deployment rather than applications.

Configure ConfigMgr 2012 to cater for the Dynamic Apps/Packages script

Certain conditions must exist within ConfigMgr for the Dynamic Apps/Packages script to execute successfully. Without these conditions in place the script will not enumerate applications or packages.

  • A ‘Container Node’ should be created for all application or package install collections to be housed under. This container node, ‘Application Deployment’ in my example, is referenced in the dynamic apps/pack script as the starting point for gathering information on which collections the device being deployed is a member of.

DynApp-006

  • Individual ‘AppDeploy’ collections are created per application or package.

DynApp-007

  • Each collection has to have a relevant application or package deployed to it. The apps or package must be set as ‘Required’ deployments.

DynApp-008

  • Each deployment when set to ‘Required’ must be set to install ‘As soon as possible’ if a package or application.

DynApp-009

DynApp-010

Create the Package for the Dynamic Application Script

A package needs to be created within ConfigMgr to hold the dynamic application script. The package should be set with ‘No Program’ associated.

DynApp-011

In this instance the package ‘Dynamic Apps & Packages’ has been created to host the file.

DynApp-012

Create the Application Deployment Task Sequence and Deployment

The Task Sequence for dynamic application and package deployment consists of three steps:

  • A step to run the script and enumerate applications and packages targeted at the device being built
  • A step to install the applications targeted at the device
  • A step to install the packages targeted at the device

DynApp-013

Create the Dynamic Packages List

This step is a ‘Run PowerShell Script’ task.  The Dynamic Apps & Packages package highlighted in the previous section is the referenced package and the script ‘DynamicAppsPackages.ps1’ is added to the ‘Script Name’ box. The execution policy should always be set to ‘Bypass’ unless the script is signed.

DynApp-014

Install Packages

Packages that have been enumerated when the script executes will be stored as a list of variables. Starting with APPID001 and incrementing.

The ‘Install software packages according to dynamic variable list’ check box is selected and the ‘Base variable name’ APPid entered.

DynApp-015

A condition needs to be entered into the task sequence to skip the ‘Install Packages’ step if no packages are deployed to the device being built.

In the Options tab of the ‘Install Packages’ step a condition has been created. The criteria states:

‘If the SkipPackages task sequence variable does not exist then do not run the step’

The SkipPackages variable is created by the dynamic app/packages script only if no packages are deployed against the device. Therefore if this were the case the step would be ignored and the Task Sequence would continue.

DynApp-016

Install Applications

The ‘Install Applications’ step is identical to the ‘Install Package’ step but with minor differences.

Applications that have been enumerated when the script executes will be stored as a list of variables. Starting with APPID01.  Note a two digit, rather than three, number.

The ‘Install applications according to dynamic variable list’ check box is selected and the ‘Base variable name’ APPid entered.

DynApp-017

Again a condition needs to be entered into the task sequence to skip the ‘Install Applications’ step if no applications are deployed to the device being built.

In the Options tab of the ‘Install Applications’ step a condition has been created. The criteria states:

‘If the SkipApplications task sequence variable does not exist then do not run the step’

As with the ‘SkipPackages’ variable, ‘SkipApplications’ is created by the dynamic app/packages script, only if no packages are deployed against the device, and the step will be ignored.

DynApp-018

Create the Task Sequence deployment

The ‘Automation Dynamic Applications’ Task Sequence is deployed as a ‘Required’ deployment to the ‘Automation Dynamic Applications’ collection.

DynApp-019

The Dynamic Applications & Packages script breakdown

The complete script can be downloaded from the Technet Galleries here.

This section takes the script apart and explains what is happening in each section of the script.

The script can be broken down into three areas:

  1. Variables and credentials are set locally and a commands are invoked to run a remote session as a service account user.
  2. Enumeration of applications and packages take place on a remote session on the site server
  3. Results are brought back to the local session and then stored as Task Sequence variables.

The example code is run against a test device which has three packages and one application deployed to it.

Variables

The following variables are defined in the script

# $ResourceName = local hostname of the device running the script
# $password = password of service account running the app/pack enumeration for the device
# $cred = Creates a PSCredential object of username/password that will run the remote session on behalf of the device
# $CountPack = counter for package enumeration
# $CountApp = counter for app enumeration
# $SiteCode = ConfigMgr site for the environment
# $SiteServer = ConfigMgr site server hostname for the environment
# $Container = Container Node in ConfigMgr that stores all the application and package deployment collections
# $PackageEnumerate = Array to store all packages in the remote session
# $ApplicationEnumerate = Array to store all applications in the remote session
# $localPackages = Variable to store all packages when back in local session before passing to Task Sequence
# $localApplications = Variable to store all packages when back in local session before passing to Task Sequence

Section 1 – Some local variables defined

$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$password = $tsenv.Value("svcaccpassword")
$ResourceName = $env:computername
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @("<domain\username>",(ConvertTo-SecureString -String $password -AsPlainText -Force))
$CountPack = 1
$CountApp = 1

A password, for the service account that will run the remote session, is set as a collection variable on the collection targeted for deployment by the Task Sequence, read from the Task Sequence environment ($tsenv.Value(“svcaccpassword”) ) and stored as the variable $password.

DynApp-020

This is assigned into a PSCredential object along with the service account username . Note that the $cred variable in the script needs to be amended to add the domain\username for the service account running the remote session.

$cred = New-Object System.Management.Automation.PSCredential -ArgumentList @("<domain\username>",(ConvertTo-SecureString -String $password -AsPlainText -Force))

Counters for package and application enumeration are set to 1. They will be used later in the script to create the APPID001/01, APPDID002/02 variables.

Section 2 – Scriptblock: The Remote Session

The following section of PowerShell code is the ‘meat’ of the piece. It runs in a remote session on the site server and is called from section 3 of the script. It’s the section that will enumerate all the applications and packages deployed to the device.

The code’s results are stored as a variable called $ScriptBlockContent and all the code is contained within parenthesis

$ScriptBlockContent = { CODE HERE }

Onto the code:

param ($ResourceName)
$SiteCode = "<SITE CODE>"
$SiteServer = "<SITE SERVER>"
$Container = "Application Deployment"
Write-Host "$ResourceName"
$PackageEnumerate = @()
$ApplicationEnumerate = @()

Note – change the $SiteCode and $SiteServer variables to reflect your ConfigMgr site details.

Since the code runs in the remote session, the local hostname of the device defined in Section 1 needs to be passed over to the remote session. The invoke-command in Section 3 achieves this, but the param ($ResourceName) defined in Section 2 accepts the local to remote variable in the remote session.

Other essential variables are defined before running the queries to enumerate applications and packages (e.g. site code – see Variables section for definitions). Note a write-host of $ResourceName. This will write the hostname of the device into ConfigMgr’s smsts.log file (the log file used to check Task Sequence’s). This is a visual check in the log file so we can ensure the code is running against the correct device should any error checking be required.

The code moves into the query phase to collate the app/package information we need to extract.

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

After running the code on the site server it is determined that the ContainerNodeID for the “Application Deployment” container node is ‘16777253’, in this example.  Note that the ID will never change for this node.

DynApp-021

$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

The ContainerNodeID can then be used to link two WMI classes and return the list of collections within the Container Node which the device is a member of. The query above achieves this.

WMI Explorer can effectively show how this query works.

Running a query of SELECT * FROM SMS_FullCollectionMembership where Name = ‘<myhostname>’ retrieves all collection membership for the device.  (Note ResourceID = 16777679)

DynApp-022

 

For the purposes of the application/package enumeration, only the collection membership within the Container Node ‘Application Deployment’ is required, since this the location where all apps & packages are deployed to.

Running a query of SELECT * FROM SMS_ObjectContainerItem where ContainerNodeID = ‘16777253’ returns all the collections that contained within the container node.

DynApp-023

Note that the InstanceKey in each result can be matched against the CollectionID from the FullCollectionMembership query and therefore the results can be filtered down to only the collections in the Container Node that the device is a member of.

The final query gives the required result

SELECT fcm.* FROM SMS_FullCollectionMembership fcm, SMS_ObjectContainerItem oci WHERE oci.ContainerNodeID='$ContainerNodeId' AND fcm.Name='$ResourceName' AND fcm.CollectionID=oci.InstanceKey

Collection membership of four collections within the container node ‘Application Deployment’

DynApp-024

DynApp-025

if ($CollectionIds -ne $null) {
foreach ($CollectionId in $CollectionIds) {
$ApplicationNames = (Get-WmiObject -ComputerName $SiteServer -Class SMS_ApplicationAssignment -Namespace root/SMS/site_$SiteCode -Filter "TargetCollectionID='$CollectionId' and OfferTypeID='0'").ApplicationName
$AdvertisementDetails = Get-WmiObject -ComputerName $SiteServer -Class SMS_AdvertisementInfo -Namespace root/SMS/site_$SiteCode -Filter "CollectionID='$CollectionID' and PackageType='0'"

if ($AdvertisementDetails -ne $null) {foreach ($AdvertisementDetail in $AdvertisementDetails) {
$PackageEnumerate += ($AdvertisementDetail.PackageID+':'+$AdvertisementDetail.ProgramName)
}
}

if ($ApplicationNames -ne $null) {foreach ($ApplicationName in $ApplicationNames) {
$ApplicationEnumerate += $ApplicationName
}
}

The next step of the code loops for each result collected, e.g. for each Collection ID.

Initially the code checks to see if no Collection ID were returned. If Collection ID’s were returned in the previous query then execute the loop.

 

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

The code checks in the WMI class ‘SMS_ApplicationAssignment’ for each Collection ID, ensures that each targeted collection is a ‘Required’ deployment and stores the application name deployed to the collection in a variable called $ApplicationNames.

DynApp-026

For my test device one application has been enumerated – ‘FileZilla_FTP_Client  – Unattended’

A similar loop is applied to packages.

$AdvertisementDetails = Get-WmiObject -ComputerName $SiteServer -Class SMS_AdvertisementInfo -Namespace root/SMS/site_$SiteCode -Filter "CollectionID='$CollectionID' and PackageType='0'"

The code checks the WMI class ‘SMS_AdvertisementInfo’ for each CollectionID. Ensures that each targeted deployment is of type ‘Package’ and stores all the advertisements details into the variable $AdvertisementDetails.

DynApp-027

For my test device three deployments are enumerated: SITECODE20081, SITECODE20080 & SITECODE2007F.

Finally the enumerated results of the application and package search need to be stored into separate arrays, $PackageEnumerate, $ApplicationEnumerate, which can be retrieved from the remote session.

if ($AdvertisementDetails -ne $null) {foreach ($AdvertisementDetail in $AdvertisementDetails) {
$PackageEnumerate += ($AdvertisementDetail.PackageID+':'+$AdvertisementDetail.ProgramName)
}
}

if ($ApplicationNames -ne $null) {foreach ($ApplicationName in $ApplicationNames) {
$ApplicationEnumerate += $ApplicationName
}
}

The code takes the results from the $AdvertisementDetails and stores the deployments PackageID and ProgramName for each Package separated by a colon. Note this is the format the Task Sequence expects for the dynamic package list.

For example: SITECODE00043:Install SCOM Agent

Note – Look at WMI class that the advertisement details were retrieved from to see what properties are available to use.

DynApp-028

The results from $ApplicationNames are stored into an array $ApplicationsEnumerate. Only the ApplicationName property is needed for the Task Sequence dynamic applications list.

DynApp-029

Section 3 – Invoking the Scriptblock and writing back to the Task Sequence

$Session = New-PSSession -ComputerName <site server> -Credential $cred
Invoke-Command -Session $Session -ScriptBlock $ScriptBlockContent -ArgumentList $ResourceName

A new PowerShell session is created on the site server, using the credentials supplied in ‘Section 1 – Some local variables defined ’. Note: set the -ComputerName variable to your site server host name

The invoke-Command runs the scriptblock in the session, and passes though the local variable of $ResouceName (or local hostname) to the remote session.

$localPackages = Invoke-Command -Session $Session -ScriptBlock {$PackageEnumerate}
$localApplications = Invoke-Command -Session $Session -ScriptBlock {$ApplicationEnumerate}
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment

The code brings the arrays $PackageEnumerate and $ApplicationEnumerate back to the local session and they are stored as $localPackages and $localApplications respectively.

A Task Sequence COM object is created as the variable $TSEnv to allow the arrays to be written back to the TS as Task Sequence variables.

if ($localPackages -ne $null) {foreach ($Package in $localPackages) {
$Id = "{0:D3}" -f $CountPack
$AppId = "APPID$Id"
$TSEnv.Value($AppId) = $Package
Write-Host $AppId $Package
$CountPack = $CountPack + 1
}
}

The code now checks to ensure that $localPackages is not an empty variable and if not process each ‘$Package’ detail in $localPackages. It creates a three digit ID ({0:D3} and with the value of $CountPack, 1, being the first value of the ID. So 001. The variable APPID becomes ‘APPID + 001’ or APPID001 and this value is written to the Task Sequence with the value of $Package.

So APPID001 could be SITECODE00043:Install SCOM Agent.

A write-host exists so that the data is written to the ConfigMgr smsts.log file as a visual aid to error checking.

$CountPack is incremented by 1 and the loop continues until all variables in $localPackages are written back to the Task Sequence. Note the $TSEnv variable is remmed out in this example as it will only generate errors when run outside of the Task Sequence environment.

DynApp-030

if ($localApplications -ne $null) {foreach ($Application in $localApplications) {
$Id = "{0:D2}" -f $CountApp
$AppId = "APPID$Id"
$TSEnv.Value($AppId) = $Application
Write-Host $AppId $Application
$CountApp = $CountApp + 1
}
}

The application code works in exactly the same way, except that it only generates a two digit APPID and writes back in the format APPID01 ApplicationName

For example, APPID01 FileZilla_FTP_Client – Unattended

DynApp-031

Section 4 – SkipPackages & SkipApplications

As mentioned previously the Task Sequence requires conditions to skip the steps for application or package install if no deployments are targeted to the device for either type of installation. If these conditions are not applied the Task Sequence will error and fail.

 

if ($CountPack -eq "1") {
$TSEnv.Value("SkipPackages") = "True"
write-host "Skip Packages"
}

if ($CountApp -eq "1") {
$TSEnv.Value("SkipApplications") = "True"
Write-Host "Skip Applications"
}

The final lines of code check to see of the $CountPack and $CountApp variables are still equal to 1. If they are it means that no deployments are assigned.

So for each type the Task Sequence variables SkipPackages or SkipApplications are written back to the Task Sequence environment.

Remember that the TS has been set to not run the relevant steps if the variables exist.

DynApp-016

DynApp-018

The complete script can be downloaded from the Technet Galleries here.

 

102 comments

  1. WOW…that just freaked me out and i’ll be testing that shortly, the blog post was a very interesting read, you just earned a new follower 🙂 thanks for taking the time to comment out each block as i know it is sometime exhausting 🙂

    very good post,

    a big thanks from France!

  2. Thank you. I have been testing it today whole sunday. Your script works, it did find all the applications and packages, and created a correct list, installed most of apps and package.

    But for some reason, not all application installed. AppEnforce.log said “waitforrunningprocess failed. error 0x87d00213.”.

    Is it possible put some kind of sleep or time out example 30 seconds between each app start to install?

    1. I recreated my applications, seems those applications what I created before I intergated MDT to SCCM are failed to install in Full OSD, but now that all work after I recreated again. Thank you for your script!

  3. I tested it a bit more today, recreated apps didn’t help, again failed install application with Error 0x87d00213.

    1. Test your apps outside of the Task Sequence and ensure that they install successfully first.

      Error 0x87D00213 (-2016411117) means

      Install took longer than allowed.
      Try install again usually associated with installs that require user input to complete.
      Review install logs.

      Is one of the apps causing this by requiring user input or something like that?

  4. Those applications are Adobe Flash Plugin, Java 8 update 45 and mPollux. They all installed nicely after OS is deployed. Other applications what installed during OSD, AppEnfore.log said “Waitig for process xxx to finish. Timeout = 120 minunts. Mutta these other applications what failed, the log said timout = 0 minutes.
    Just wondering is it possible releated I deploy Wndows 10 Preview? And I am using SCCM MDT deployment.
    Well..of course, my problem is not realated with your script, your script works nicely! Thank you again for that.

    Here is the log.

    AppEnfore.log:

    Waiting for process 3928 to finish. Timeout = 0 minutes. AppEnforce 29.4.2015 10:42:59 1804 (0x070C)
    Exceeded timeout of 0 minutes while waiting for process 3928 to finish. AppEnforce 29.4.2015 10:42:59 1804 (0x070C)
    WaitForRunningProcess failed. Error 0x87d00213. AppEnforce 29.4.2015 10:42:59 1804 (0x070C)
    CScriptHandler::CompleteEnforcement failed with 0x87d00213 AppEnforce 29.4.2015 10:42:59 1804 (0x070C)
    CAppProvider::CompleteEnforcement failed with error 0x87d00213 AppEnforce 29.4.2015 10:42:59 1804 (0x070C)
    ++++++ Failed to enforce app. Error 0x87d00213. ++++++ AppEnforce 29.4.2015 10:42:59 1804 (0x070C)

  5. You need to work out what apps are causing this and why, Timeout – again could relate to a hidden user input that is required, Install the apps outside of SCCM using the same install criteria to narrow down the problem.

  6. Thanks for your Post!

    I tried to use your script but it doesn’t work.

    If I try to create in PowerShell the object “$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment” I receive the following error:

    New-Object : Retrieving the COM class factory for component with CLSID {00000000-0000-0000-0000-000000000000} failed
    due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
    At line:1 char:10
    + $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ResourceUnavailable: (:) [New-Object], COMException
    + FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand

    (This error is the same if I use PS in 32 and 64bit in a 64bit machines)

    With internet I found some information about the problem with this object and a 64bit sytem, is correct?
    My network use only a 64bit machines…
    You know how I can fix this problem?

    Thanks for your help!

    Best Regards

    Sebastian

    PS I’m sorry for my bad English

      1. Ah ok, I didn’t know this…

        I tried to use in a task with no success (now I’m looking the error in internet), but I tried to run manually the single line of the script for locate the problem… But now I know that this way doesn’t work.

        The last time I tried (in this moment) the error was 0x80004005, maybe I put a wrong password with my network account…

        I’ll try soon!

        Thanks for your help!

      2. There’s a couple of lines in the script you can comment out and then test it locally on the device. I’ll reply later with the lines you take out as I’m not in front of a pc at the moment. Checking your smsts.log for your error though.

      3. Thaks for your help!

        I found my first error: I don’t changed the row “$Session = New-PSSession -ComputerName -Credential $cred” in section 3;
        Now I changed “” with “$SiteServer” (I have only 1 site server).

        If I run the script manually it seems that it works properly.
        If I try with a task it finish without error, but no Application or Packages are installed.

        Here an extract of smsts.log
        – Parsing step node AAAAAAAAAA is the step with PS Script
        – Parsing step node BBBBBBBBBB is the step for install the Applications
        – Parsing step node CCCCCCCCCC is the step for install the Packages

        If I read correctly the log there are some problem with variables: “No variables found in default variable list”.

        You know where I made another mistake?

      4. It’s failing on the New-PSSession : with error Impossibile convalidare l’argomento sul parametro =. Have you set a service account up to run the remote PowerShell session and give it rights to run the session on the site server. See my ‘Pre-Requisites’ section

      5. Yes, I have made this setting, I restarted the service and I tried to restart the entire server.
        The account is the “principal” account for SCCM (is also member of schema admin and he is the one I use for software distribution).
        I tried to give him “full control” permission without success.

      6. Sebastian – I have run a Google translate on your errors and the line ‘ L’argomento Š null o vuoto. Fornire un argomento che non sia ‘ means that the parameter for -ComputerName in the New-PSSession line is null. Looking at my code I have the following ‘$Session = New-PSSession -ComputerName (site server) -Credential $cred’. Really I should have put ‘$Session = New-PSSession -ComputerName $SiteServer -Credential $cred’ or you could change the (site server) to the hostname of your ConfigMgr site server – eg -ComputerName ConfigMgr001. Test that out. It should resolve the problem. Let me know if ok and I will amend the code and post the fix to the TechNet Gallery.

      7. Hi SCCMentor,
        I’m sorry but I forgot to tell you that we use Windows in Italian language… but the server is in English (I hope this is not a problem).

        In this days I tried to made different test.

        I tried to put the server name explicitly and use the variable, but this don’t change the result.

        I write the variables’ content in different files with command: $CountApp | Out-File “C:\Windows\TEMP\CountApp.txt” -encoding UTF8
        This to see their content. The variable on the server’s sessions are created in the C of the server

        But is it correct that the last part of the script run locally and not in the session on the server?
        (where you add the APPIDXXX on the collections)
        I wanted to try to make it run on the server but I have yet to understand how to do it.

        I hope that tomorrow I’ll have time for more tests.

        Thanks again for all your help!

      8. You can run it direct from a client if you take out all references to the TS environment. You will then see the script generate the app/packages list. The script runs local. The pssession connects to the site sever and then the last part of the script is local to the device again

      9. Dear SCCMentor, I hope you spend a beautifull Christmas

        Finnaly I found my mistake!
        In some application and package I forgot to set the flag “Allow this program to be installed from the install Package/application task without being deployed”.
        Obviously on the first application and first package and in 2-3 others…
        Now I checked all (it’s about 100 programs) and I found it.

        The script works!!!

        Thanks for all!

        I wish to begin magnificently the 2016

        Best Regards Sebastian

  7. Hi Paul
    I’m using a SQL Query to pull together a dynamic application list during the OSD.. This works fine but now we do have applications with supersedences which are still deployed to the machines. Does your code cover this?
    Best Regards

    1. Peter, I haven’t tested a superseded app but the code is looking for deployments so what ever you have deployed against the device will get the deployment installed.

      1. OK. I can look at updating the script Mike to leverage subfolders utilising the ParentContainerNodeID details of the SMS_ObjectContainerNode class. Give a me a couple of days as currently my test lab is in a state and I can look into updating the script and posting it to TechNet. If you’d like to test the update for me when ready then let me know. Cheers Paul

    1. Mike I have a test script that takes into account nesting of container nodes. Would you like to test this? Let me know and I can get this to you.

      Cheers
      Paul

    1. Hi Mike. I hit a dead end and then the weekend took over. Hoping to look at this again this week. Some progress but not a complete solution yet. Cheers Paul

      1. Hi Mike. I started work on it and then other things took over. Not sure when I will be able to fit in at the moment but it’s on my list. Sorry

  8. Paul, I would like to extend my gratitude. This proved to be extremely useful in one of my other projects involving dynamic application installation and customized web portals.

  9. Hi Paul

    Can you please give me support?

    I’m trying to run this script on a OSD task sequence but it fails. I’ve created an account in my AD (called SCCM service account). I added this account to the Collection where I’m deploying the task sequence, with the password.

    My task sequence is failing somewhere, related to the script. My error is:

    At C:\_SMSTaskSequence\Packages\P0100008\DynamicAppsPackages.ps1:70 char:40 RunPowerShellScript 20/09/2016 12:54:20 5876 (0x16F4)
    + $Session = New-PSSession -ComputerName -Credential $cre … RunPowerShellScript 20/09/2016 12:54:20 5876 (0x16F4)
    + ~ RunPowerShellScript 20/09/2016 12:54:20 5876 (0x16F4)
    The ‘<' operator is reserved for future use. RunPowerShellScript 20/09/2016 12:54:20 5876 (0x16F4)
    + CategoryInfo : ParserError: (:) [], ParseException RunPowerShellScript 20/09/2016 12:54:20 5876 (0x16F4)
    + FullyQualifiedErrorId : RedirectionNotSupported RunPowerShellScript 20/09/2016 12:54:20 5876 (0x16F4)
    RunPowerShellScript 20/09/2016 12:54:20 5876 (0x16F4)
    Command line returned 1 RunPowerShellScript 20/09/2016 12:54:20 5876 (0x16F4)

    Incorrect function. (Error: 00000001; Source: Windows)

    If I try to run as a single Task Sequence, with the 3 steps as you shown here, it also fails with the same code error. I think made everything as shown in your step-by-step. It seems like it looking for an argument that is missing. Did I miss something ?

    Thanks in advance for your support!
    Jose

    1. Jose – this is an error in my code which I been meaning to update. It should read $SiteServer and not . I have updated the script on TechNet galleries can you please download and test? Thanks Paul

      1. Hi Paul,

        It works, yes. Although when I run the script, there are no applications/packages to run, which is strange since I’ve two deployments in my lab for targeting the device. I’m running this on CM 1606, fresh installation.

        I’ve looked into the logs and found this:

        New-PSSession : Cannot validate argument on parameter ‘ComputerName’. The RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        argument is null or empty. Provide an argument that is not null or empty, and RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        then try the command again. RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        At C:\_SMSTaskSequence\Packages\P0100008\DynamicAppsPackages.ps1:70 char:40 RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        + $Session = New-PSSession -ComputerName $SiteServer -Credential $cred RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        + ~~~~~~~~~~~ RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        + CategoryInfo : InvalidData: (:) [New-PSSession], ParameterBindi RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        ngValidationException RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        Shell.Commands.NewPSSessionCommand RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        Invoke-Command : Cannot validate argument on parameter ‘Session’. The argument RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        is null or empty. Provide an argument that is not null or empty, and then try RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        the command again. RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        At C:\_SMSTaskSequence\Packages\P0100008\DynamicAppsPackages.ps1:71 char:25 RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        + Invoke-Command -Session $Session -ScriptBlock $ScriptBlockContent -Ar … RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        + ~~~~~~~~ RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        + CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBind RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        ingValidationException RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        Shell.Commands.InvokeCommandCommand RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        RunPowerShellScript 21/09/2016 09:33:24 3356 (0x0D1C)
        Invoke-Command : Cannot validate argument on parameter ‘Session’. The argument RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)
        is null or empty. Provide an argument that is not null or empty, and then try RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)
        the command again. RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)
        At C:\_SMSTaskSequence\Packages\P0100008\DynamicAppsPackages.ps1:72 char:42 RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)
        + $localPackages = Invoke-Command -Session $Session -ScriptBlock {$Pack … RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)
        + ~~~~~~~~ RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)
        + CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBind RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)
        ingValidationException RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)
        Shell.Commands.InvokeCommandCommand RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)
        RunPowerShellScript 21/09/2016 09:33:25 3356 (0x0D1C)

        Note that the task sequence runs without any errors at least, but the SMSTS.log has all these entries. Should I edit something in the script?

        Thank you once again!

    1. Hi Paul
      I did now. Should I change also the variables:

      $password = $tsenv.Value(“to my password?”)
      $cred = New-Object System.Management.Automation.PSCredential -ArgumentList @(“MyDomain\svcaccpassword”,(ConvertTo-SecureString -String $password -AsPlainText -Force))

      I was assuming that this script would be reading from the collection the variables to authenticate.

      1. Absolutely. Change the details to the service account you are going to use to run the remote PSSession. This will be the service account that you have set up as a read-only analyst.

  10. There are still a lot of errors:

    ConvertTo-SecureString : Cannot bind argument to parameter ‘String’ because it RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    is an empty string. RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    At C:\_SMSTaskSequence\Packages\P0100008\DynamicAppsPackages.ps1:27 char:134 RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    + … boa\svcaccpassword”,(ConvertTo-SecureString -String $password -AsPlai … RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    + ~~~~~~~~~ RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    + CategoryInfo : InvalidData: (:) [ConvertTo-SecureString], Param RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    eterBindingValidationException RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAl RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    lowed,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    New-Object : A constructor was not found. Cannot find an appropriate RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    constructor for type System.Management.Automation.PSCredential. RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    At C:\_SMSTaskSequence\Packages\P0100008\DynamicAppsPackages.ps1:27 char:9 RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    + $cred = New-Object System.Management.Automation.PSCredential -Argumen … RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    + CategoryInfo : ObjectNotFound: (:) [New-Object], PSArgumentExce RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    ption RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    + FullyQualifiedErrorId : CannotFindAppropriateCtor,Microsoft.PowerShell.C RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    ommands.NewObjectCommand RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    RunPowerShellScript 21/09/2016 10:52:48 4800 (0x12C0)
    New-PSSession : Cannot validate argument on parameter ‘ComputerName’. The RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    argument is null or empty. Provide an argument that is not null or empty, and RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    then try the command again. RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    At C:\_SMSTaskSequence\Packages\P0100008\DynamicAppsPackages.ps1:70 char:40 RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + $Session = New-PSSession -ComputerName $SiteServer -Credential $cred RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + ~~~~~~~~~~~ RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + CategoryInfo : InvalidData: (:) [New-PSSession], ParameterBindi RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    ngValidationException RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    Shell.Commands.NewPSSessionCommand RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    Invoke-Command : Cannot validate argument on parameter ‘Session’. The argument RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    is null or empty. Provide an argument that is not null or empty, and then try RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    the command again. RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    At C:\_SMSTaskSequence\Packages\P0100008\DynamicAppsPackages.ps1:71 char:25 RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + Invoke-Command -Session $Session -ScriptBlock $ScriptBlockContent -Ar … RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + ~~~~~~~~ RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBind RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    ingValidationException RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    Shell.Commands.InvokeCommandCommand RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    Invoke-Command : Cannot validate argument on parameter ‘Session’. The argument RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    is null or empty. Provide an argument that is not null or empty, and then try RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    the command again. RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    At C:\_SMSTaskSequence\Packages\P0100008\DynamicAppsPackages.ps1:72 char:42 RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + $localPackages = Invoke-Command -Session $Session -ScriptBlock {$Pack … RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + ~~~~~~~~ RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBind RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    ingValidationException RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    Shell.Commands.InvokeCommandCommand RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    Invoke-Command : Cannot validate argument on parameter ‘Session’. The argument RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    is null or empty. Provide an argument that is not null or empty, and then try RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    the command again. RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    At C:\_SMSTaskSequence\Packages\P0100008\DynamicAppsPackages.ps1:73 char:46 RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + $localApplications = Invoke-Command -Session $Session -ScriptBlock {$ … RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + ~~~~~~~~ RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBind RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    ingValidationException RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Power RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    Shell.Commands.InvokeCommandCommand RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)
    RunPowerShellScript 21/09/2016 10:52:49 4800 (0x12C0)

    This is a lab. I’m using your account described in your step-by-step. I’m not sure what should I do anymore, but here is the script as it is right now:

    $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
    $password = $tsenv.Value(“AStr0ngPassW0rd”)
    $ResourceName = $env:computername
    $cred = New-Object System.Management.Automation.PSCredential -ArgumentList @(“LISBOA\svcaccpassword”,(ConvertTo-SecureString -String $password -AsPlainText -Force))
    $CountPack = 1
    $CountApp = 1

    $ScriptBlockContent = {

    param ($ResourceName)
    $SiteCode = “P01”
    $SiteServer = “CM01.LISBOA.POR”
    $Container = “Application Deployment”
    Write-Host “$ResourceName”
    $PackageEnumerate = @()
    $ApplicationEnumerate = @()

    1. Based on your log:ConvertTo-SecureString : Cannot bind argument to parameter ‘String’ because it is an empty string.

      I think you got this one wrong:
      $password =$tsenv.Value(“AStr0ngPassW0rd”)

      Seems you don’t have a variable name “AStr0ngPassW0rd” in your collection.

      Here should put variable name, not value of the variable, means not your actual password.
      Read the post again, it mentioned how to put the password variable in collection.

  11. Hello ,
    I try to create a dynamic Task Sequence SCCM2012 using poweshell .
    My problem is that i cant add a steps for installing package to my task sequence .
    I m looking for procedure or cmdlet powershell to add the steps to my task sequence .
    Thank you for any help .

  12. Hello ,
    I try to create a Custom Task Sequence SCCM2012 using poweshell .
    I am unable to add a steps for installing role through “Run Command line” option to my task sequence .
    I m looking for procedure or cmdlet powershell to add the steps to my task sequence.

  13. Hi
    Thanks for the awesome write up. I am fairly new to SCCM and have a question. During my OS deployment , I get prompt to enter Computer Name (OSDCOmputername). What I am looking to do is move the computer to a OU based on name .E.g IS-123 move to IS move etc. As I understand my collection will be based on these OU and then I will follow this article for application deployment.
    My apologies if its stupid question. I am very new to SCCM and need some advise. Appreciate your assistance. Thanks

      1. Thanks Paul,
        I am trying to follow the article below.
        http://thebillablelife.com/sccm-put-computer-in-ou-based-on-name-during-osd/

        I created a package with no program and deployed and followed the article. My task sequence runs fine and doesnt move the machine to the OU .

        Also I dont see any errors in the smsts logs. I am running the move step towards the end of deployment (post deployment). Can you please check the link and advise when you can. Appreciate it. Cheers

      1. Hi Paul,
        I started all over again today . It’s still failing when I use my domain admin account to run the script. I get below error
        C:\_SMSTaskSequence\Packages\P0100094\Move.vbs(13, 2) Microsoft VBScript runtime error: Permission denied InstallSoftware 2/15/2017 9:09:57 AM 3772 (0x0EBC)

        When I run the script without any user defined, it goes through fine but doesn’t do anything.

        The account I am using is domain admin. I have checked on all OU’s , domain admin has full access. Thanks for taking time to help me out. Appreciate it.

      2. You need to check the netstup.log first and foremost when running without a user defined. This will tell you where the problem lies. It is in the windows\debug folder on a device.

  14. Hi Paul,
    Here is the Netsetup log. I dont see anything related to computer move. Thanks

    02/15/2017 08:58:58:516 —————————————————————–
    02/15/2017 08:58:58:516 NetpDoDomainJoin
    02/15/2017 08:58:58:516 NetpDoDomainJoin: using new computer names
    02/15/2017 08:58:58:516 NetpDoDomainJoin: NetpGetNewMachineName returned 0x0
    02/15/2017 08:58:58:516 NetpDoDomainJoin: NetpGetNewHostName returned 0x0
    02/15/2017 08:58:58:516 NetpMachineValidToJoin: ‘EDAD-TAB’
    02/15/2017 08:58:58:516 NetpMachineValidToJoin: status: 0x0
    02/15/2017 08:58:58:516 NetpJoinDomain
    02/15/2017 08:58:58:516 HostName: EDAD-Tab
    02/15/2017 08:58:58:516 NetbiosName: EDAD-TAB
    02/15/2017 08:58:58:516 Domain: test.org\testDC1.test.org
    02/15/2017 08:58:58:516 MachineAccountOU: (NULL)
    02/15/2017 08:58:58:533 Account: test\chucknorris
    02/15/2017 08:58:58:533 Options: 0x23
    02/15/2017 08:58:58:533 NetpDisableIDNEncoding: no domain dns available – IDN encoding will NOT be disabled
    02/15/2017 08:58:58:533 NetpJoinDomainOnDs: NetpDisableIDNEncoding returned: 0x0
    02/15/2017 08:59:00:984 NetpJoinDomainOnDs: status of connecting to dc ‘\\testDC1.test.org’: 0x0
    02/15/2017 08:59:01:015 NetpJoinDomainOnDs: Passed DC ‘testDC1.test.org’ verified as DNS name ‘\\testDC1.test.org’
    02/15/2017 08:59:01:015 NetpDsGetDcName: status of verifying DNS A record name resolution for ‘testDC1.test.org’: 0x0
    02/15/2017 08:59:01:015 NetpGetDnsHostName: PrimaryDnsSuffix defaulted to DNS domain name: test.org
    02/15/2017 08:59:01:030 NetpProvisionComputerAccount:
    02/15/2017 08:59:01:030 lpDomain: test.org
    02/15/2017 08:59:01:030 lpHostName: EDAD-Tab
    02/15/2017 08:59:01:030 lpMachineAccountOU: (NULL)
    02/15/2017 08:59:01:030 lpDcName: testDC1.test.org
    02/15/2017 08:59:01:030 lpMachinePassword: (null)
    02/15/2017 08:59:01:030 lpAccount: test\chucknorris
    02/15/2017 08:59:01:030 lpPassword: (non-null)
    02/15/2017 08:59:01:030 dwJoinOptions: 0x23
    02/15/2017 08:59:01:030 dwOptions: 0x40000003
    02/15/2017 08:59:01:064 NetpLdapBind: Verified minimum encryption strength on testDC1.test.org: 0x0
    02/15/2017 08:59:01:064 NetpLdapGetLsaPrimaryDomain: reading domain data
    02/15/2017 08:59:01:064 NetpGetNCData: Reading NC data
    02/15/2017 08:59:01:077 NetpGetDomainData: Lookup domain data for: DC=test,DC=org
    02/15/2017 08:59:01:077 NetpGetDomainData: Lookup crossref data for: CN=Partitions,CN=Configuration,DC=test,DC=org
    02/15/2017 08:59:01:077 NetpLdapGetLsaPrimaryDomain: result of retrieving domain data: 0x0
    02/15/2017 08:59:01:077 NetpGetLocalDACDisabled: returning 0x0, *pfDACDisabled=TRUE
    02/15/2017 08:59:01:077 NetpCheckForDomainSIDCollision: returning 0x0(0).
    02/15/2017 08:59:01:124 NetpGetComputerObjectDn: Cracking DNS domain name test.org/ into Netbios on \\testDC1.test.org
    02/15/2017 08:59:01:124 NetpGetComputerObjectDn: Crack results: name = test\
    02/15/2017 08:59:01:124 NetpGetComputerObjectDn: Cracking account name test\EDAD-TAB$ on \\testDC1.test.org
    02/15/2017 08:59:01:141 NetpGetComputerObjectDn: Crack results: Account does not exist
    02/15/2017 08:59:01:141 NetpGetComputerObjectDn: Cracking Netbios domain name test\ into root DN on \\testDC1.test.org
    02/15/2017 08:59:01:141 NetpGetComputerObjectDn: Crack results: name = DC=test,DC=org
    02/15/2017 08:59:01:141 NetpGetComputerObjectDn: Got DN CN=EDAD-TAB,CN=Computers,DC=test,DC=org from the default computer container
    02/15/2017 08:59:01:156 NetpModifyComputerObjectInDs: Initial attribute values:
    02/15/2017 08:59:01:156 objectClass = Computer
    02/15/2017 08:59:01:156 SamAccountName = EDAD-TAB$
    02/15/2017 08:59:01:156 userAccountControl = 0x1000
    02/15/2017 08:59:01:156 DnsHostName = EDAD-Tab.test.org
    02/15/2017 08:59:01:156 ServicePrincipalName = HOST/EDAD-Tab.test.org RestrictedKrbHost/EDAD-Tab.test.org HOST/EDAD-TAB RestrictedKrbHost/EDAD-TAB
    02/15/2017 08:59:01:156 unicodePwd =
    02/15/2017 08:59:01:156 NetpModifyComputerObjectInDs: Computer Object does not exist in OU
    02/15/2017 08:59:01:156 NetpModifyComputerObjectInDs: Attribute values to set:
    02/15/2017 08:59:01:156 objectClass = Computer
    02/15/2017 08:59:01:156 SamAccountName = EDAD-TAB$
    02/15/2017 08:59:01:156 userAccountControl = 0x1000
    02/15/2017 08:59:01:156 DnsHostName = EDAD-Tab.test.org
    02/15/2017 08:59:01:156 ServicePrincipalName = HOST/EDAD-Tab.test.org RestrictedKrbHost/EDAD-Tab.test.org HOST/EDAD-TAB RestrictedKrbHost/EDAD-TAB
    02/15/2017 08:59:01:156 unicodePwd =
    02/15/2017 08:59:01:287 NetpDeleteMachineAccountKey: called for computer ‘EDAD-TAB’
    02/15/2017 08:59:01:301 NetpGetComputerObjectDn: Cracking DNS domain name test.org/ into Netbios on \\testDC1.test.org
    02/15/2017 08:59:01:314 NetpGetComputerObjectDn: Crack results: name = test\
    02/15/2017 08:59:01:314 NetpGetComputerObjectDn: Cracking account name test\EDAD-TAB$ on \\testDC1.test.org
    02/15/2017 08:59:01:314 NetpGetComputerObjectDn: Crack results: (Account already exists) DN = CN=EDAD-TAB,CN=Computers,DC=test,DC=org
    02/15/2017 08:59:01:329 NetpDeleteMachineAccountKey: msDS-KeyCredentialLink attr was not found on computer ‘EDAD-TAB’ – no action required.
    02/15/2017 08:59:01:329 NetpDeleteMachineAccountKey: returning Status: 0
    02/15/2017 08:59:01:329 ldap_unbind status: 0x0
    02/15/2017 08:59:01:329 NetpJoinCreatePackagePart: status:0x0.
    02/15/2017 08:59:01:366 NetpJoinDomainOnDs: Setting netlogon cache.
    02/15/2017 08:59:01:407 NetpJoinDomainOnDs: status of setting netlogon cache: 0x0
    02/15/2017 08:59:01:407 NetpJoinDomainOnDs: Function exits with status of: 0x0
    02/15/2017 08:59:01:407 NetpJoinDomainOnDs: status of disconnecting from ‘\\testDC1.test.org’: 0x0
    02/15/2017 08:59:01:407 NetpJoinDomain: DsrIsDeviceJoined returned false
    02/15/2017 08:59:01:533 NetpJoinDomain: NetpCompleteOfflineDomainJoin SUCCESS: Requested a reboot :0x0
    02/15/2017 08:59:01:533 NetpDoDomainJoin: status: 0x0
    tPrivileges: Setting backup/restore privileges.
    02/15/2017 08:59:01:346 NetpAddPartCollectionToRegistry.
    02/15/2017 08:59:01:346 NetpProvGetTargetProductVersion: Target product version: 10.0.14393.0
    02/15/2017 08:59:01:346 NetpAddPartCollectionToRegistry: delete OP state key status: 0x2.
    02/15/2017 08:59:01:346 NetpConvertBlobToJoinState: Translating provisioning data to internal format
    02/15/2017 08:59:01:346 NetpConvertBlobToJoinState: Selecting version 1
    02/15/2017 08:59:01:346 NetpConvertBlobToJoinState: exiting: 0x0
    02/15/2017 08:59:01:366 NetpJoin2RequestPackagePartInstall: Successfully persisted all fields
    02/15/2017 08:59:01:366 NetpAddPartCollectionToRegistry: Successfully initiated provisioning package installation: 2/2 part(s) installed.
    02/15/2017 08:59:01:366 NetpAddPartCollectionToRegistry: status: 0x0.
    02/15/2017 08:59:01:366 NetpOpenRegistry: status: 0x0.
    02/15/2017 08:59:01:366 NetpSetPrivileges: status: 0x0.
    02/15/2017 08:59:01:366 NetpRequestProvisioningPackageInstall: status: 0x0.
    02/15/2017 08:59:01:407 —————————————————————–
    02/15/2017 08:59:01:407 NetpProvContinueProvisioningPackageInstall:
    02/15/2017 08:59:01:407 Context: 0
    02/15/2017 08:59:01:407 NetpProvGetWindowsImageState: IMAGE_STATE_SPECIALIZE_RESEAL_TO_OOBE.
    02/15/2017 08:59:01:407 NetpCreatePartListFromRegistry: status: 0x0.
    02/15/2017 08:59:01:407 NetpCompleteOfflineDomainJoin
    02/15/2017 08:59:01:407 fBootTimeCaller: FALSE
    02/15/2017 08:59:01:407 fSetLocalGroups: TRUE
    02/15/2017 08:59:01:407 NetpJoinDomainLocal: NetpHandleJoinedStateInfo returned: 0x0
    02/15/2017 08:59:01:468 NetpJoinDomainLocal: NetpManageMachineSecret returned: 0x0.
    02/15/2017 08:59:01:468 Calling NetpQueryService to get Netlogon service state.
    02/15/2017 08:59:01:468 NetpJoinDomainLocal: NetpQueryService returned: 0x0.
    02/15/2017 08:59:01:468 NetpJoinDomainLocal: status of setting LSA pri. domain: 0x0
    02/15/2017 08:59:01:468 NetpManageLocalGroupsForJoin: Adding groups for new domain, removing groups from old domain, if any.
    02/15/2017 08:59:01:484 NetpManageLocalGroupsForJoin: status of modifying groups related to domain ‘test’ to local groups: 0x0
    02/15/2017 08:59:01:484 NetpManageLocalGroupsForJoin: INFO: No old domain groups to process.
    02/15/2017 08:59:01:484 NetpJoinDomainLocal: Status of managing local groups: 0x0
    02/15/2017 08:59:01:484 NetpJoinDomainLocal: status of setting ComputerNamePhysicalDnsDomain to ‘test.org’: 0x0
    02/15/2017 08:59:01:484 NetpJoinDomainLocal: Controlling services and setting service start type.
    02/15/2017 08:59:01:484 NetpJoinDomainLocal: Updating W32TimeConfig
    02/15/2017 08:59:01:516 NetpCompleteOfflineDomainJoin: status: 0x0
    02/15/2017 08:59:01:516 NetpJoinProvider2OLContinuePackagePartInstall: ignoring Context=0 (work finished already).
    02/15/2017 08:59:01:516 NetpProvContinueProvisioningPackageInstall: Provisioning package installation completed successfully.
    02/15/2017 08:59:01:516 NetpProvContinueProvisioningPackageInstall: delete OP state key status: 0x0.
    02/15/2017 08:59:01:516 NetpProvContinueProvisioningPackageInstall: status: 0xa99.

    1. So is the computer object currently in the Computers OU? Can you send the script as you have written it? Have you left the DomainOU field blank in Apply Network Settings? Did you put the move OU step in between Apply Windows and Apply Network as suggested? Does the fallback to the ‘Default:
      OSDDomainJoinOU = “LDAP://OU=Workstations,DC=yourdomain,DC=com” work if you done enter any OSDComputerName details? Need more information here.

      1. Below is the script

        Dim strComputer, OSDComputerName, env
        Dim objWMIService, objChassis, colChassis, strChassisType
        Dim OSDDomainOUName, strChassisTypeIs
        Set env = CreateObject(“Microsoft.SMS.TSEnvironment”)
        OSDComputerName = env(“OSDComputername”)
        If OSDComputerName=”” Then
        OSDComputerName=env(“_SMSTSMachineName”)
        End If

        ‘Default:
        OSDDomainJoinOU = “LDAP://OU=test Machines,DC=test,DC=org”
        subGenLocale
        env(“OSDDomainOUName”) = OSDDomainJoinOU
        WScript.Quit

        Sub subGenLocale
        Select Case Mid(ucase(OSDComputerName),1,4)
        Case “BPV”
        OSDDomainJoinOU = “LDAP://OU=BPV,OU=Windows 10,OU=test Machines,DC=test,DC=org”
        Case “FS”
        OSDDomainJoinOU = “LDAP://OU=FS,OU=Windows 10,OU=test Machines,DC=test,DC=org”
        Case “EDAD”
        OSDDomainJoinOU = “LDAP://OU=EDAD,OU=Windows 10,OU=test Machines,DC=test,DC=org”
        Case “Intake”
        OSDDomainJoinOU = “LDAP://OU=Intake,OU=Windows 10,OU=test Machines,DC=test,DC=org”

        End Select
        End Sub
        ————————

        Have you left the DomainOU field blank in Apply Network Settings
        Yes

        Did you put the move OU step in between Apply Windows and Apply Network as suggested
        No. I am doing it in my post Install. How is it differ to running in between Apply Windows & Apply Network vs post install. I will try it now.

        Does the fallback to the ‘Default:
        OSDDomainJoinOU = “LDAP://OU=Workstations,DC=yourdomain,DC=com”

        No, it goes to default Computers OU.

        Thanks

      2. Then the script must be failing in some way as it can’t be populating the unattend.xml file. Start to build a machine and then press F8 when the Setup Windows and ConfigMgr step is running. Copy the unattend.xml from the c:\windows\panther\unattend folder off to a network share. Take a look at the file in notepad. Is anything written in the tags?

  15. Hi Paul,
    I just tried it running in between Applying windows settings and Network settings.. I got below error in the smsts logs

    running a command line under a user account is not supported in WinPE InstallSoftware 2/15/2017 11:30:22 AM 520 (0x0208)
    cmd.Execute(pszPkgID, sProgramName, dwCmdLineExitCode), HRESULT=80004005 (e:\qfe\nts\sms\client\osdeployment\installsoftware\main.cpp,372) InstallSoftware 2/15/2017 11:30:22 AM 520 (0x0208)
    Install Software failed to run command line, hr=0x80004005 InstallSoftware 2/15/2017 11:30:22 AM 520 (0x0208)
    Process completed with exit code 2147500037 TSManager 2/15/2017 11:30:22 AM 1984 (0x07C0)
    !——————————————————————————————–! TSManager 2/15/2017 11:30:22 AM 1984 (0x07C0)
    Failed to run the action: Move OU.
    Unspecified error (Error: 80004005; Source: Windows) TSManager 2/15/2017 11:30:22 AM 1984 (0x07C0)

  16. Hi Paul,
    Happy to report that the script is working now. I am running in between Apply Windows Settings and Apply Network Settings with account. I am not sure what is difference is though If I run the script outside Apply Window and Network settings steps.
    Thanks again for your help. I am going to continue now and follow your article to deply applications. I highly appreciate your help and time. Cheers

      1. Btw don’t use a domain admin to domain join as the username and password used to domain join is stored in the unattend.xml and someone could easily copy that file off a device in the same way i suggested and therefore get a domain admins details

  17. Great post, Paul! I have a question on Static Application Task Sequence. Can I just create a custom Task Sequence with a number of Application Only in the Task Sequence, without a boot image or OS Image, then deploy to a computer collection? If so, how do I do it? Currently I created a Task Sequence with about 10 Applications, then I deployed it to a collection. However, nothing happens and I can’t find anything in the log (or don’t know what logs to look for). Thank you for your help!

    1. Sorry for the delay. Yes this is possible. Sounds like you have everything set up OK. Do you have it set as an Available TS? Check Software Center on a device that the TS is deployed to. Cheers Paul

      1. Hi Paul. Do you mean if I set it as “Available” in deployment? NO, I set it as “Required” when I deployed the TS. Or Do you mean if I have the check on application to set as Availible for Task Sequence? In this case, yes I have a check to allow application to use in TS. Please note that I don’t set up like the way you describe in the post. All my applications are in the same application folder. Then I created a TS with no Boot Image selected, then I just added the applications, then distributed to DPs, and deployed to a computer collection (just 1 computer for testing) and “Required” and deadline set as “As soon as possible”. What logs should I look for troubleshooting? I have looked at quite a few main log but found nothing. Please help and thank you for your contribution in this community!

  18. Is anything recorded in the smsts.log file? Is anything being cached to the client? Check the cas.log for any errors. Is the client communicating with the site? Check the ClientLocation.log, LocationServices.log first and make ensure. Check the Execmgr.log to see if the deployment is appearing in it.

  19. Hi Paul,
    I’m assuming all the logs that you mentioned are from Client computer. I checked all the logs and found nothing relate to the my Task Sequence. The client is communicating with the SCCM server and receiving other Applications and Packages. There is nothing recored in smsts.log file from “\\clientComputer\c$\windows\ccm\logs\smsts.log” There is no error in CAS.log, ClientLocation.log, LocationServices.log, and Execmgr.log. I’ve tried to search for the deployment info on these logs using Task Squence name and Task Sequence’s PackageID, but found nothing. Does application-only TS deployment is the wany with Application deployment? Is it supposed to show up in Scoftware Center? Am I missing something here?

      1. Yes, that was my first step. Today, I just did the CCM client repair and still no luck. The client is getting application packages but no evidence of deployed Task Sequence at all. This is very strange. I just deleted the deployment and try to deploy the TS again.

  20. Cracking Script. Thank you for the hard work that went into this. One gotcha that I ran into was that my “ContainerID” folder was not a unique name. I was running into “Generic failure” errors in powershell. You’re break down of the script was great as it made it easy for me to trouble shoot. I ran the powershell command on the site server to retrieve the container ID and noticed there were 3! I renamed the folder in the SCCM console to something unique and it worked like a charm.

  21. Hi Paul,
    I wrote a launcher for OSD using your script.
    I am stuck as:
    “WinPE-PowerShell has the following known limitations:
    – Windows PowerShell remoting is not supported. Any cmdlets that have remoting functionality will return an error.”

    can you give me a hint I should forget about running it before OS is deployed?

  22. Thanks for this. Am trying to implement at the moment. One question; will all applications/packages within the container node be installed or does the script look for only those deployed to collections that the computer is a member of?

  23. Hi Paul,
    2 questions:
    1) will this work /have you tried this with SCCM 1706 or higher?
    2) What happens to packages installed during the TS? Won’t they re-run when the normal collection eval will happen and the client “sees” the normal advertisement for this package?

    Thanks
    Michael

  24. Hi Paul,

    It all seems to be working fine with the script. However there is an interesting issue with the package installation. Application and package lists are created as expected. Applications are getting installed okay, but packages fail. When looking into the smsexe.log it sais that packages are waiting for maintenance window??? Have you got any idea why this happens.

    Thank you very much in advance.

    BR,

    Angel

      1. Hi,

        Yes, there is MW indeed. It is set from 10PM to 8AM and all clients in the environment. It seems to only affect packages which is strange. Neither the application deployments nor the package deployments are set to ignore MW, yet application go okay, packages not. execmgr.log says “Execution Request for advert ####### package ####### program install state change from Ready to WaitingServiceWindow”. Strange behavior.

  25. there is MW set from 10PM to 8AM. What’s strange is that this happens only with packages…application install fine. None of the deployments for either apps nor packages are set to ignore MW…

  26. Hi Paul,
    It has been a while since anyone has posted a reply but I have been using your Dynamic Application Deployment script for a number of years and it is really great. Recently my team and I have run into an issue where a few of the targeted apps aren’t installing during the primary OSD process. These apps are getting installed after the TS completes but the problem with that is it often leaves the Helpdesk technicians wondering after the final TS reboot. The applications typically still get installed because the device still evaluates them as required and since the installs are valid, they are installed. This behavior left me scratching my head so I went back to the SMSTS.LOG and I can see the dynamic application script is running but I don’t see the details of what packages and applications are actually enumerated. I searched for APPID and also by the actual names of the packages and they aren’t listed in the SMSTS.log. Can you give me any pointers as to why the individually enumerated apps aren’t getting logged? Also, to give some perspective, task sequences containing 10-15 dynamic apps seem to be handled flawlessly every single time but this particular dynamic deployment has 33 different apps.

    Also, just to let you know, we extended the process so that we are only using one TS for Windows 10 and one for Windows 11 but we have dynamic population of the device collections for the applications. How we are handling this is by assigning an AD group representing the user’s “role”. Then we have user collections that query for the AD group and populate the users into the collections. Next we have device collections that correspond to the user collection for role. We populate the “role” device collection with the primary device for the users in the referenced user collection. Then the device role collections are explicitly included in the dynamic deployment targeting collections. As an extra level of control we have an OSD deployment collection that is the limiting collection. We add this last step so that if there is a new version deployed within OSD, it won’t immediately try to install on a computer that is already in use. We have tweaked the collection evaluation so that it happens pretty quickly so that when Helpdesk receives a new user build, they can just PXE boot the machine and select Windows 10 or Windows 11 and the rest happens automatically based on the dynamic app deployment process. It really is brilliant and such a time saver.

    If I can get the logging issue sorted out, that would be a huge help.

    Oh and is there any way to add a system reboot during the dynamic app install? Occasionally we have apps that need this sort of thing and I could add a scripted reboot but I am concerned that if I do it this way it will cause the task sequence engine to not restart after the reboot. Any guidance here would be appreciated.

    Cheers,
    Chris

Leave a Reply