It has been a while since the last time I blogged. In this post I will show the last step in my PowerShell script thats create and deploy an application in SCCM 2012. The steps of the script are
- Create Application SCCM 2012 XML
- Import XML into SCCM 2012
- Create Collection
- Create Collection Rule
- Distribute Content to Distribution group
- Deploy Application to collection
I will explain the last step of this script. Altough it is a simple step it was hard to discover how it worked. In 2012 deploying an application is actually assigning an application to a collection. It therefore uses the wmi class SMS_ApplicationAssignment. To deploy an application al you have to do is to create an instance, fill it with values en save it. An example is shown below
$ApplicationAssignmentClass = [wmiclass] "\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_ApplicationAssignment" $newApplicationAssingment = $ApplicationAssignmentClass.CreateInstance() $newApplicationAssingment.ApplicationName = "Microsoft Office 2013 NL" $newApplicationAssingment.AssignmentName = "Deploy Microsoft Office 2013" $newApplicationAssingment.AssignedCIs = $CI_ID $newApplicationAssingment.CollectionName = $ColllectionName $newApplicationAssingment.CreationTime = "20120101120000.000000+***" $newApplicationAssingment.LocaleID = 1043 $newApplicationAssingment.SourceSite = "S01 $newApplicationAssingment.StartTime = "20120101120000.000000+***" $newApplicationAssingment.SuppressReboot = $true $newApplicationAssingment.NotifyUser = $true $newApplicationAssingment.TargetCollectionID = $CollectionID $newApplicationAssingment.OfferTypeID = 2 $newApplicationAssingment.WoLEnabled = $false $newApplicationAssingment.RebootOutsideOfServiceWindows = $false $newApplicationAssingment.OverrideServiceWindows = $false $newApplicationAssingment.UseGMTTimes = $true [void] $newApplicationAssingment.Put()
Hi Rob,
In the above script, what should be the values of $CI_ID
Thanks,
Vedayaj
Hi Vedayaj,
$CI_ID should contain de CI_ID of the application that you want to deploy (advertise). This can be found in the class SMS_Application
Gr,
Rob
Hi,
I need help on automating deployment of multiple SCCM applications which are not deployed yet to a particular collection.
Means if in the SCCM application if see the deployment is 0 then the script should automatically deploy it.
Hi Manju,
Do you mean that you want to detect if an application is already deployed to a collection. If this is not the case you want the script to deploy the application to that collection? Am I correct
grtz Rob
Hi Rob,
Yes, In my ConfigMgr application view if any of the application is not yet deployed to the collection, then script should help in deploying.
What you can do is create a script that list all active applications (SMS_Application) where isLatest=true and isEnable=true. And that has no instance in SMS_ApplicationAssignment (CI_ID).
Hoi Rob,
Heb een kleine toevoeging gemaakt voor de functie Add-SCCMCollectionRule waarmee je een direct group membership kunt toevoegen aan een collectie:
————————————————————————————————————————
Function Add-SCCMCollectionRule {
[CmdletBinding()]
PARAM (
[Parameter(Mandatory=$true, HelpMessage=”SCCM Server”)][Alias(“Server”,”SmsServer”)][System.Object] $SccmServer,
[Parameter(Mandatory=$true, HelpMessage=”CollectionID”, ValueFromPipelineByPropertyName=$true)] $collectionID,
[Parameter(Mandatory=$false, HelpMessage=”Computer name to add (direct)”, ValueFromPipeline=$true)] [String] $name,
[Parameter(Mandatory=$false, HelpMessage=”User Group name to add (direct)”, ValueFromPipeline=$true)] [String] $groupname,
[Parameter(Mandatory=$false, HelpMessage=”WQL Query Expression”, ValueFromPipeline=$true)] [String] $queryExpression = $null,
[Parameter(Mandatory=$false, HelpMessage=”Limit to collection (Query)”, ValueFromPipeline=$false)] [String] $limitToCollectionId = $null,
[Parameter(Mandatory=$true, HelpMessage=”Rule Name”, ValueFromPipeline=$true)] [String] $queryRuleName
)
PROCESS {
# Get the specified collection (to make sure we have the lazy properties)
$coll = [wmi]”$($SccmServer.SccmProvider.NamespacePath):SMS_Collection.CollectionID=’$collectionID'”
# Build the new rule
if ($queryExpression.Length -gt 0) {
# Create a query rule
$ruleClass = [WMICLASS]”$($SccmServer.SccmProvider.NamespacePath):SMS_CollectionRuleQuery”
$newRule = $ruleClass.CreateInstance()
$newRule.RuleName = $queryRuleName
$newRule.QueryExpression = $queryExpression
$null = $coll.AddMembershipRule($newRule)
} elseif ($groupname.Length -gt 0) {
$ruleClass = [WMICLASS]”$($SccmServer.SccmProvider.NamespacePath):SMS_CollectionRuleDirect”
# Find User Group
$usergroup = Get-SCCMObject -sccmServer $Sccmserver -class “SMS_R_UserGroup” -filter “SMS_R_UserGroup.UserGroupName=’$groupname'”
If ($usergroup -eq $null) {
Write-Host -ForegroundColor Red “UserGroup $groupname not found in SCCM, no membership has been added to the collection”
}
Else {
Write-Verbose “Adding new rule for UserGroup $groupname”
$newRule = $ruleClass.CreateInstance()
$newRule.RuleName = $queryRuleName
$newRule.ResourceClassName = “SMS_R_UserGroup”
$newRule.ResourceID = $usergroup.ResourceID
$null = $coll.AddMembershipRule($newRule)
}
} else {
$ruleClass = [WMICLASS]”$($SccmServer.SccmProvider.NamespacePath):SMS_CollectionRuleDirect”
# Find each computer
$computer = Get-SCCMComputer -sccmServer $SccmServer -NetbiosName $name
# See if the computer is already a member
$found = $false
if ($coll.CollectionRules -ne $null) {
foreach ($member in $coll.CollectionRules) {
if ($member.ResourceID -eq $computer.ResourceID) {
$found = $true
}
}
}
if (-not $found) {
Write-Verbose “Adding new rule for computer $name”
$newRule = $ruleClass.CreateInstance()
$newRule.RuleName = $name
$newRule.ResourceClassName = “SMS_R_System”
$newRule.ResourceID = $computer.ResourceID
$null = $coll.AddMembershipRule($newRule)
} else {
Write-Verbose “Computer $name is already in the collection”
}
}
}
}
———————————————————————————————————————–
Moet je alleen nog alle aanroepen naar deze functie aanpassen, zodat de extra parameter meegegeven wordt. Bijv.:
Add-SCCMCollectionRule $con $col.CollectionID $null “TestUsersGroup” $null “SMS00004” “UW-TST\TestUsersGroup”
Thank you for this post. Unfortunately i can’t get it to work because i get a Put error. It says: Exception calling “Put” with “0” arguments: Generic Failure.
This is my script:
$computer = “LocalHost”
$namespace = “root\SMS\site_BLA”
$target = Get-WmiObject -class SMS_Collection -computername $computer -namespace $namespace | where {$_.Name -eq “Windows 7”}
$collectionID = $target.CollectionID
$collectionName = $target.Name
$app = Get-WmiObject -class SMS_Application -computername $computer -namespace $namespace | where {$_.LocalizedDisplayname -eq “BLA Reader”}
$applicationID = $app.CI_ID
$applicationName = $app.LocalizedDisplayname
$newApplicationAssingment = ([wmiclass]”\\$computer\root\SMS\site_BLA:SMS_ApplicationAssignment”).CreateInstance()
$newApplicationAssingment.ApplicationName = “$applicationName”
$newApplicationAssingment.AssignmentName = “Deploy BLA Reader”
$newApplicationAssingment.AssignedCIs = “$applicationID”
$newApplicationAssingment.CollectionName = “$collectionName”
$newApplicationAssingment.LocaleID = “1033”
$newApplicationAssingment.SourceSite = “BLA”
$newApplicationAssingment.TargetCollectionID = “$collectionID”
$newApplicationAssingment.OfferTypeID = “2”
$newApplicationAssingment.put()
Hi,
I guess one of the required fields are NULL so therefore you get this useless generic failure message. Can you test it if you fill in the field NotifyUser for the newApplicationAssignment object.
Unfortunately it doesn’t help. Adding even more to the newApplicationAssignment doesn’t help neither.
The new instance is created though. But somehow the put doesn’t work.
Did you included the start time as well…. You can also check the SMSProv.log on you SCCM server for a detailed error message.
Yes i did.
$Format = get-date -format yyyyMMddHHmmss
$Date = $Format + “.000000+***”
I changed the script to use a Set-WmiInstance now just to see if it changes anything but somehow it looks like the AssignedCIs and the LocalID are causing the issue.
Can you give me all the informatie you have stored in the $newApplicationAssignment object.
And check if $applicationID gives you one object or an array of CI_IDs
Thank you Rob, i got it working. After checking the SMSProv.log i found that the SuppressReboot is mandatory. If you don’t add this the sql query will fail.
I added it to the script and have a deployment in my sccm 2012 console 🙂
Hi Rob, sorry to bother you again but i have another question.
Is it possible to create a deployment in sccm 2012 which will be performed immediately? is there a way to control this? Like i have an application in sccm 2012 and i want it to be installed immediately on one of my windows 7 agents.
SCCM is designed for middle size and large environments and therefore it is not possible to install an application immediately. As it could have a huge impact on the environment. What you could do is to create a script that connects to the desired client and start the policy refresh. It then should install the application that is mandatory to that client.
Thank you Rob. I will play with the policy refresh and simulate an immediate deployment on an agent.
Hi,
thank you for your bits. I was able to successfully implement them with my script.
The only thing that seems to be missing is the “DeploymentIntent” (whether I want to uninstall or install an app).
For some reason this is not a property of this wmi class, however it can be found in other ones that are related to Deployments (SMS_DeploymentInfo for example).
Any idea how to accomplish this?
Thanks.
Again there was no (correct) documentation about it but with some tests I figured out how you can uninstall an application.
Setting the following property will cause the application to uninstall DesiredConfigType = 2
If you check documentation that is availble you can see that there is some documentation but that is not very clear (link).
Thank you so much for this info!
Highly appreciated 🙂
Sometimes I wonder why stuff like that isn’t documented when it’s one of the most important properties…
Oh well – thanks again! You’re my personal hero for the day 😉
What is the challenge if they had documented this. It would be far to easy ;-). SCCM application and powershell is not the best combination for now. As there is no cmdlts in SCCM 2012 SP1 to create an application. But it keeps us busy.
If you have more questions please ask. Being hero of the day feels good and now I want to be it again after this day 😛
You’re welcome – well creating an application is sorta possible using cmdlets. That is if your applications are strictly msi.
While Script-based applications are theoretically supported by the cmdlet there is a bug somewhere in there which leads to the cmdlet “working” but effectively doing nothing.
Regards
Hi Rob. Thank you for providing this code. I was able to Create a deployment. I am fairly new to CM and powershell I had a question. I plan to use this to test my application also. So if i wanted to delete the deployment i created via this script how would i go about doing that. I already saw in the previous comments how to deploy the uninstall so thank you for that bit of information also.
Your help is greatly appreciated.
If you have SCCM 2012 SP1 you can delete a deployment with the following code
$appname = “””
$colname = “
$app = Get-CMApplication -Name $appname
$col = Get-CMDeviceCollection -Name $colname
$deployment = Get-CMDeployment -CollectionName $colname |?{$_.ModelName -eq $app.ModelName}
Remove-CMDeployment -DeploymentId $deployment.DeploymentID -ApplicationName $app.LocalizedDisplayName -Force