Every ConfigMgr admin knows that new Application model has been introduced in ConfigMgr 12 but the Packages are here to stay for a while. Packages and Programs are ideal for deploying Scripts (one time or reoccurring ones) and better suited for deploying apps during OSD (heard this one).
ConfigMgr ideally has 3 ways of working with it and below is the pic which says it all :
The post is broken up in 3 parts (based on how you use ConfigMgr):
- GUI Way - Doing this to show background on how we do it manually.
- Cmdlet Way - using the CM cmdlets to create the package and program
- WMI Way - exploring WMI to do the same.
I believe that doing things for few first times the GUI way helps understand and grasp the process but moving on we should try to automate repetitive tasks. Below is an animated gif showing how to create a minimalist Package & Program (for 7-zip) in ConfigMgr Console :
Cmdlet Way :
Using the cmdlets is straight forward but for sake of people who are starting new with PowerShell way of managing ConfigMgr. Below are the detailed steps.
Import the ConfigMgr Module. You should have ConfigMgr cmdlet library installed on your box now
Import the ConfigMgr Module. You should have ConfigMgr cmdlet library installed on your box now
PS>Import-Module -Name ConfigurationManager
Once done, the next step is discover the cmdlets. How you ask
PS>Get-Command -Noun CMPackage -Module ConfigurationManager CommandType Name ModuleName ----------- ---- ---------- Cmdlet Export-CMPackage ConfigurationManager Cmdlet Get-CMPackage ConfigurationManager Cmdlet Import-CMPackage ConfigurationManager Cmdlet New-CMPackage ConfigurationManager Cmdlet Remove-CMPackage ConfigurationManager Cmdlet Set-CMPackage ConfigurationManager
Now go ahead and read the help for the cmdlet New-CMPackage to understand what I will be doing next. Create a new Package:
PS>New-CMPackage –Name “7Zip – PS Way” –Path "\\dexsccm\Packages\7-zip\v9.20"
If one looks closely at the syntax of the New-CMPackage file they will immediately notice that the cmdlet doesn't let you set whole lot of options in the package you just created. See below the different parameter sets for the cmdlet:
PS>Get-Command New-CMPackage -Syntax New-CMPackage -Name[-Description ] [-Manufacturer ] [-Language ] [-Version ] [-Path ] [-DisableWildcardHandling] [-ForceWildcardHandling] [-WhatIf] [-Confirm] [commonparameters] New-CMPackage -FromDefinition -PackageDefinitionName -SourceFileType -SourceFolderPathType -SourceFolderPath [-DisableWildcardHandling] [-ForceWildcardHandling] [-WhatIf] [-Confirm] commonparameters] New-CMPackage -FromDefinition -PackagePath -PackageNoSourceFile [-DisableWildcardHandling] [-ForceWildcardHandling] [-WhatIf] [-Confirm] [commonparameters] New-CMPackage -FromDefinition -PackagePath -SourceFileType -SourceFolderPathType -SourceFolderPath [-DisableWildcardHandling] [-ForceWildcardHandling] [-WhatIf] [-Confirm] [commonparameters] New-CMPackage -FromDefinition -PackageDefinitionName -PackageNoSourceFile [-DisableWildcardHandling] [-ForceWildcardHandling] [-WhatIf] [-Confirm] [commonparameters]
So how does one Set all those properties for a Package via PowerShell ??
Go ahead and read the help for Set-CMPackage cmdle and you will know this is the cmdlet which will do the rest customization needed for the Package created. Suppose I want to enable binary differential replication for this package along with setting the distribution priority to high for this package, use below :
PS>Set-CMPackage -Name “7Zip – PS Way” -EnableBinaryDeltaReplication PS>Set-CMPackage -Name “7Zip – PS Way” -DistributionPriority High
Did you notice above, I had to use the Set-CMPackage cmdlet twice, Why ?
Hint - Check what are Parameter sets for a cmdlet in PowerShell.
Moving on, Now time to create the Program (standard) for the package which will install the 7zip package for us. The cmdlet is New-CMProgram, if you still don't know how to figure that out read the help for Get-Command ;)
Let's create the Program:
PS>New-CMProgram -PackageName “7Zip – PS Way” -StandardProgramName "7zip PS Install - Program" -CommandLine "msiexec.exe /I 7z920-x64.msi /quiet /norestart"
Now you can configure a lot of options for the program while creating it or you can also use Set-CMProgram to configure them later, for example I am setting the run type for the above standard program created as hidden type :
Set-CMProgram -PackageName “7Zip – PS Way” -StandardProgramName "7zip PS Install - Program" -StandardProgram -RunType Hidden
One can play with the Set-CMProgram to tweak the program settings as per need, there are a whole lot of the Parameters and switches to play with this cmdlet.
Once the Package and Program have been created it is time to distribute them to the DP Groups or DP. The cmdlet is Start-CMContentDistribution.
Start-CMContentDistribution -PackageName “7Zip – PS Way” -DistributionPointGroupName DexLabDPGroup
WMI Way :
Let's get to the more adventurous way of creating the Packages & Programs using WMI.
Fair Warning that this is a more complex way and if you don't understand how WMI works then my advice would be to stick to the cmdlet way.
Start with creating a WMI Instance of SMS_Package class, supply the Package name and the PkgSourcePath while creating the instance.
New-CimInstance -ClassName SMS_Package -Property @{'Name'='7zip - WMI Way';'PkgSourcePath'="\\dexsccm\Pa
ages\7-zip\v9.20"} -Namespace Root/SMS/site_DEX
ActionInProgress : 1
AlternateContentProviders :
Description :
ExtendedData :
ExtendedDataSize : 0
ForcedDisconnectDelay : 5
ForcedDisconnectEnabled : False
ForcedDisconnectNumRetries : 2
Icon :
IconSize : 0
IgnoreAddressSchedule : False
ISVData :
ISVDataSize : 0
IsVersionCompatible :
Language :
LastRefreshTime : 4/10/1970 6:35:00 AM
LocalizedCategoryInstanceNames : {}
Manufacturer :
MIFFilename :
MIFName :
MIFPublisher :
MIFVersion :
Name : 7zip - WMI Way
NumOfPrograms : 0
PackageID : DEX00017
PackageSize : 0
PackageType : 0
PkgFlags : 0
PkgSourceFlag : 1
PkgSourcePath : \\dexsccm\Packages\7-zip\v9.20
PreferredAddressType :
------ Snipped -------
Now, if we look at the Package created, we will soon notice that the PkgSourceFlag is set to 1 (default value - STORAGE_NO_SOURCE. The program does not use source files.), Check the documentation and you will realize you need to set it to 2 (STORAGE_DIRECT). With the value of 1 set for PkgSourceFlag you will see the below in the properties for the Package.
So let's get to it now. First get the CIMInstance stored in a variable and then use Set-CIMInstance to set the property PkgSourceFlag on it and verify the changes. Below is the code and gif in action (it shows green screen for the code executed) :
# get the CIM Instance stored in a variable $package = Get-CimInstance -ClassName SMS_Package -Filter "Name='7zip - WMI Way'" -Namespace root/SMS/site_DEX # set the PkgSourceFlag on the CIM Instance Set-CimInstance -InputObject $Package -Property @{'PkgSourceFlag'=[uint32]2}
Let's move ahead and create a new Program to install the Package using WMI. The WMI class tp focus on is SMS_Program. Before creating the WMI/CIM Instance reading the documentation of the classes is must to avoid any surprises.
The doc for the SMS_Program in Remarks lists below :
A program is always associated with a parent package and typically represents the installation program for the package. Note that more than one program can be associated with the same package. The application uses the PackageID property to make this association. Your application cannot change this property after the SMS_Program object is created. To associate the program with a different package, the application must delete the object and create a new object with a new PackageID value.
As mentioned above, we need PackageID for our Package in order to associate a Program t o it. If you are following this post then the variable $Package already has the PackageID property which we can dot reference and use.
Below is the code snippet which I used to create a new Program for the Package :
$ProgramHash3 = @{
PackageID=$($package.PackageID);
ProgramName='7zip WMI Install - Program';
CommandLine='msiexec.exe /I 7z920-x64.msi /quiet /norestart'
}
New-CimInstance -ClassName SMS_Program -Namespace Root/SMS/site_DEX -Property $ProgramHash3
Note - Found a bug at the MSDN SMS_Program documentation which says that the CommandLine property is not a Key Qualifier. Below is what the doc says :
CommandLine
Data type: String
Access type: Read/Write
Qualifiers: [ResID(904), ResDLL("SMS_RSTT.dll")]
The command line that runs when the program is started. The default value is "".
Voila, Now you can read the documentation of the SMS_Program class and try using the Set-CIMInstance to set some of the writable attributes on the Object. As an exercise leaving the Content distribution using WMI here, if I remember correctly I did cover it in one of the earlier posts (not sure which one though).
Resources:
My PowerShell + ConfigMgr Posts collection (quite a few):
http://www.dexterposh.com/p/collection-of-all-my-configmgr.html
Configuration Manager PowerShell Tuesdays: Creating and Distributing a Package / Program
http://blogs.technet.com/b/neilp/archive/2013/01/15/configuration-manager-sp1-powershell-tuesday-creating-and-distribution-a-package-program.aspx
SMS_Package Class:
https://msdn.microsoft.com/en-us/library/cc144361.aspx