I had a client that required to install Tier 3 applications dynamically during the build process. The idea behind it was to ensure that all the applications which the user requirements were installed. So that when the laptop was delivered there was no waiting for the application to download and install. Of course, each user has different requirements so the solution needed to be dynamic. There are some requirements for this soultion to work.
- Applications will need to be deployed to a user collections. All the collections will need to be under one unique container name.
- The user is required to be assigned to the device (Device Affinity) during the build process.
- Applications have to be allowed to install via Task Sequence.
User Collections
To enable the script to determine what applications have been assign to the user. A query of the user collections is required to gather information on the user's membership of the collection. To ensure that only certain applications are installed a unique container name with all the user collections under it will need to created. For example, a container called "Tier 3 Applications " has been created which is unique to any other container. All the collections are contained within this folder so that only these collections will be queried.
Primary User Assignment
During the build process, the device will need to be assigned to the user. This can be done if you are importing the computer to SCCM before building the laptop using. Import the computer information.Allow Application to install in TS
To be able to install applications dynamically the “Allow this application to be installed from the Install Application task sequence action without being deployed” needs to be selected.If the applications are not enabled to install during the task sequence it will fail with the below error in the C:\Windows\Logs\smsts.log.
"App Policy for Application not received. Make sure the application is marked for dynamic app install. Policy download failed, hr=0x80004005"
Install Applications Dynamically Script
The following PowerShell script will find the primary user via WMI in SCCM. It will then look to see if they are a member of the user collections. Review the applications deployed to it and then create a .csv file to create the Task Sequence Variable. The reason a .csv file is created is due to the script requiring to run under an account with administrative rights to the SCCM server to run WMI.
To use the script you will need the following details:
To use the script you will need the following details:
- Site Code
- Site Server Name
- Unique Container Name
Here is an example of what it will look like to pass these variables to the script:
InstallApplicationsDynamically.ps1 -SiteCode "AU1" -ContainerName "Tier 3 Applications" -SiteServer "SiteServerName.astzum.local"
Here is the "InstallApplicationsDynamically.ps1" script:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
To install applications dynamically in SCCM during the build process. | |
.DESCRIPTION | |
The following is required for the script to work: | |
- The device will need to have a primary user assigned to it. | |
- A unique container name with the user collections which have applications deployed to it. | |
- Application enabled to install during Task Sequence. | |
The script will n d collecting the information a .csv file is created with an Application ID and the application name. | |
.EXAMPLE | |
You will require the Site Server, Sitecode and the unique container name were all the user collections have applications deployed to. | |
InstallApplicationsDynamically.ps1 - SiteCode "AU1" -ContainerName "Tier 3 Applications" -SiteServer "SiteServerName.astzum.local" | |
#> | |
########## Param #################### | |
Param( | |
[Parameter(Mandatory=$true)] | |
[String] $SiteCode, | |
[Parameter(Mandatory=$true)] | |
[String] $ContainerName, | |
[Parameter(Mandatory=$true)] | |
[String] $SiteServer | |
) | |
################# Functions ################# | |
Function LogWrite | |
{ | |
Param ([string]$logstring) | |
Add-content "C:\Windows\Temp\Tier3ApplicationScript.log" -value $logstring | |
} | |
################# Setting Variables ################# | |
$Count = 1 | |
$csvfile= @() | |
$CsvFileCheck = $false | |
$ResourceName = $env:COMPUTERNAME | |
################# Script ################# | |
#Find the Primary User of the Device | |
$RelationShipArray = Get-WmiObject -ComputerName $SiteServer -Class SMS_UserMachineRelationship -Namespace root\SMS\Site_$SiteCode -Filter "ResourceName='$ResourceName'" | |
foreach ($user in $RelationShipArray){ | |
If ($user.Isactive -eq $true){ | |
$PrimaryUser = $user.UniqueUserName | |
} | |
} | |
If ($PrimaryUser -eq $null){ | |
LogWrite "Unable to get the PrimaryUser for the device. Exiting Script." | |
Exit 0 | |
}else{ | |
LogWrite "PrimaryUser is $PrimaryUser" | |
} | |
#Change the backslash to double backslash for the query to work | |
$PrimaryUser = $PrimaryUser.Replace('\','\\') | |
#Find the Resource ID of Primary User | |
$PrimaryUSerID = (Get-WmiObject -ComputerName $SiteServer -Namespace root\SMS\Site_$SiteCode -Class SMS_R_USER -Filter "UniqueUserName='$PrimaryUser'").ResourceID | |
LogWrite "PrimaryUserID is $PrimaryUserID" | |
#Find USer Collection Continer ID | |
$ContainerNodeId = (Get-WmiObject -ComputerName $SiteServer -Class SMS_ObjectContainerNode -Namespace root/SMS/site_$SiteCode -Filter "Name='$ContainerName' and ObjectTypeName='SMS_Collection_User'").ContainerNodeId | |
#Query what collection ID's are under the contianer name | |
$ArrayCollectionId = (Get-WmiObject -ComputerName $SiteServer -Class SMS_ObjectContainerItem -Namespace root/SMS/site_$SiteCode -Filter "ContainerNodeID='$ContainerNodeId'").InstanceKey | |
#Check every collection under the Tier 3 application container to see if the user is a member of it | |
Foreach ($collectionid in $ArrayCollectionId){ | |
#There is a class for every collection. Querying each class is the quickest method. | |
$class = "SMS_CM_RES_COLL_$collectionid" | |
#Serach the collection | |
$Collection = (Get-WmiObject -ComputerName $SiteServer -Class $class -Namespace root\SMS\Site_$SiteCode -filter "ResourceID=$PrimaryUSerID").ResourceID | |
#The search results are successful check to see what applications are being deployed to that collection. | |
If ($Collection -ne $null){ | |
LogWrite "User is a member of the collection:$CollectionId" | |
$Applications = (Get-WmiObject -ComputerName $SiteServer -Class SMS_ApplicationAssignment -Namespace root/SMS/site_$SiteCode -Filter "TargetCollectionID='$CollectionId' and OfferTypeID='0'").ApplicationName | |
If ($Applications -ne $Null){ | |
foreach ($ApplicationName in $Applications) { | |
LogWrite "The collection $collectionId has the Application $ApplicationName deployed to it. " | |
#Create a Application Variable for every application needing to be installed. | |
$Id = "{0:00}" -f $Count | |
$AppId = "AppID$Id" | |
$Count = $Count + 1 | |
LogWrite "AppID is $AppID" | |
#Setting Task Sequence Variable | |
$CsvFileCheck = $true | |
$row = New-Object System.Object | |
$row | Add-Member -MemberType NoteProperty -Name "AppId" -Value $AppID | |
$row | Add-Member -MemberType NoteProperty -Name "Name" -Value $ApplicationName | |
$csvfile += $row | |
} | |
}else{ | |
LogWrite "No Application found for collection $Collection" | |
} | |
} | |
If ($CsvFileCheck -eq $true){$csvfile | Export-CSV -Path "C:\Windows\Temp\Tier3ApplicationScript.csv" -NoTypeInformation} | |
} |
Setting Task Sequence Variables Script
The script "SettingTaskSequenceVariables.ps1" will set the Task Sequence variables of applications that have been discovered for the user. This is done by importing the .csv file "C:\Windows\Temp\Tier3ApplicationScript.csv".Here is the "SettingTaskSequenceVariables.ps1" script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Creating Task Sequence Variables from the discovered applications in | |
InstallApplicationsDynamically.ps1. | |
.DESCRIPTION | |
Obtaining the Tier3ApplicationScript.csv and creating Task Sequence Variables | |
#> | |
################# Set Variables ################# | |
$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment | |
################# Main Script ################# | |
#Import applications | |
$array = import-csv "C:\Windows\Temp\Tier3ApplicationScript.csv" | |
#Create the task sequence variables for each applications | |
foreach ($app in $array){ | |
$AppId = $app.AppID | |
$ApplicationName = $App.Name | |
$tsenv.Value("$AppId") = $ApplicationName | |
} |
Create a package for the scripts
You will need to create a package which will have both the scripts in it. We can then call this package when executing the scripts during the build.No need for a program to be created.
Task Sequence
Okay, the last step is to add the steps to the build. There is going to be three steps in total.- InstallApplicationsDynamically.ps1(Run Command Line)
- SettingTaskSequenceVariables.ps1 (Run Powershell Script)
- Install the applcations (Install Applications)
Frist create the step to discover the applications for the primary user. Ensure the account used to run the step has rights to run WMI on the SCCM Site Server.
The last step is to install applications by using the AppID task sequence variable set.
Check in the C:\Windows\Logs\smsts.log to see if the application installs. If the log file says that SCCM is unable to install the application due to permission issues. Check to ensure the application is enabled to be deployed using a task sequence
Troubleshooting
A log file called “Tier3ApplicationScript.log” is created under C:\Windows\Temp.
The log file shows if there is a primary user attached to the device and also the primaryuserID. If there is no primary user or primaryuserID then no applications will install. The log also shows what applications will be installed.
If the applications didn’t install, then check the C:\Windows\Logs\smsts.log file to see if there are any errors. First, check to see if the task sequence variables have been created,
No comments:
Post a Comment