Sample #PowerShell code for my TechEd Session – Demo 2 – Create Collections and Maintenance Windows for Server Patching.

Here’s an example of creating collections (with maintenance windows) for server patching.

Start with a .csv of servers, and the desired patch window (download sample csv).

You then run the PowerShell script to group the systems and populate new collections.
Download Script…

(if you’re having trouble with copy/paste of the code, or if code doesn’t look correct (with line feed, etc), please try an alternate browser. . .:( )

#Demo 2 - Software Update Scenario
$CMModulePath = $Env:SMS_ADMIN_UI_PATH.ToString().SubString(0,$Env:SMS_ADMIN_UI_PATH.Length - 5) `
    + "\ConfigurationManager.psd1"
Import-Module $CMModulePath -force
cd PR1:

#Removing Old Collections that begin with 'Serverpatch'
Get-CMDeviceCollection| Where-Object {$ -like "serverpatch*"} | Remove-CMDeviceCollection -force

#import the csv of servers with patch window
$Servers = import-csv C:\scripts\ServerPatchWindows.csv

#use the group-object cmdlet to group servers into patch windows
$Servers | Group-Object Patchwindow | ForEach-Object {
    #Gives us a window name like ServerPatch_5_26_2014_20_00
    $PatchWindowName = "ServerPatch_" + $_.Name -replace "[:\./ ]", "_"

    "Creating Collection {0}" -f $PatchWindowName
    $NewColl = New-CMDeviceCollection -Name $PatchWindowName -LimitingCollectionName "All Servers" 

    #Create Schedule for 5 hour MW
    $Schedule = New-CMSchedule -Nonrecurring  -Start ([datetime]$_.Name) -durationinterval Hours -DurationCount 5

    #Create MW
    New-CMMaintenanceWindow -Name ("Maint" + $PatchWindowName) -ApplyToSoftwareUpdateOnly `
        -CollectionID $NewColl.CollectionID -Schedule $Schedule
    $Schedule = $null

    #Create Server list separated by commas
    $_.Group | foreach {
       $string = $string + '"' + $_.Servername + '",'

    #build the WQL and remove the extra comma
    $wql = "select *  from  SMS_R_System where SMS_R_System.Name in (" + $string.trimend(',') + ")"
    Add-CMDeviceCollectionQueryMembershipRule -CollectionId $NewColl.CollectionID `
        -RuleName "Query1" -QueryExpression $wql
    $string = $null

Download Script…

Happy Scripting!


This post first appeared on

Sample #PowerShell code for my TechEd Session – Demo 1 – Create and Deploy an Application

Here’s example code for my first demo at our TechEd session. Review the session here PCIT-B410. The code below is an extended version of what I showed in the session (or at least attempted to show, the demo gods were against me …),

Download the script…

Here’s a brief overview of the script:

  • Import ConfigMgr module
  • Create a new application
  • Create a new deployment type for the (modern) application
  • Create a new schedule for the collection (update collection membership daily)
  • Create a new user-based collection with a query membership rule, and apply the schedule.
  • Distribute the application to “Corporate DPs” DP group
  • Create a new simulation for the application
  • Remove the simulation, and create a required deployment

There’s obviously a lot going on in this script, and was meant to show the ability to do an end-to-end scenario. (This becomes significantly harder when you have other deployment types like script-based installer, for example).

Please add your comments for where you would like deeper-dive posts explaining certain tasks.

Download the script…

Happy Scripting!

#Demo 1 - Create and deploy software
#region Import ConfigMgr Module
$CMModulePath = `
    $Env:SMS_ADMIN_UI_PATH.ToString().SubString(0,$Env:SMS_ADMIN_UI_PATH.Length - 5) `
    + "\ConfigurationManager.psd1"
Import-Module $CMModulePath -force
cd PR1:

#Show ConfigMgr cmdlets- filter in gridview for Application and Deploymenttype
Get-Command -Module ConfigurationManager | out-gridview
#show help for New-CMApplication
Get-Help New-CMApplication

#region Create New CM Application
New-CMApplication -Name "TestApp Mobile Edge" -Owner "Greg Ramsey" `
    -ReleaseDate (get-date).ToShortDateString() -Keyword "Sales" `
    -IsFeatured $True -SoftwareVersion "" `
    -IconLocationFile "\\ws2012r2\source$\MobileEdge\testapp.ico"

#Could display the application by running the following:
#Get-CMApplication -Name "TestApp Mobile Edge"

#Show help for Add-CMDeploymentType
get-help Add-CMDeploymentType -ShowWindow

#Add-CMDeploymentType is painful - edit with Show-Command
Show-Command Add-CMDeploymentType

Add-CMDeploymentType -ApplicationName "TestApp Mobile Edge" `
    -AutoIdentifyFromInstallationFile -ForceForUnknownPublisher $True `
    -InstallationFileLocation \\ws2012r2\source$\MobileEdge\testappMobileEdge.Win8App_1.0.70.75_AnyCPU_Debug.appx `
    -Windows8AppInstaller `
    -AdministratorComment "Mobile Edge - Internal App" `
    -AllowClientsToUseFallbackSourceLocationForContent $True `
    -DeploymentTypeName "Mobile Edge for Windows 8" -OnSlowNetworkMode Download `
    -TriggerVPN $True

#region Create and populate new CM Collection
#Create schedule *daily*
$sched = New-CMSchedule -start (get-date) -DurationInterval 0 -RecurInterval Days -RecurCount 1 -DurationCount 1
#Create Collection with daily update (no incremental)
New-CMUserCollection -Name "Test Users" -LimitingCollectionName "All Users" -RefreshType Periodic `
    -RefreshSchedule $sched

#Create a WQL Query rule for the collection
Add-CMUserCollectionQueryMembershipRule -CollectionName "Test Users" `
    -QueryExpression "select *  from  SMS_R_User where SMS_R_User.UserName = 'ramseygr'" `
    -RuleName "TestUsers"


#region Deploy Software
#send content to DP
Start-CMContentDistribution -Applicationname "TestApp Mobile Edge" `
    -DistributionPointGroupName "Corporate DPs"

#Create a simulation deployment
Start-CMApplicationDeploymentSimulation -CollectionName "Test Users" `
    -Name "TestApp Mobile Edge" -DeployAction Install

#....3 days later... once you have results from simulation
#capture the info in the simulation
$Simulation = Get-CMDeployment -CollectionName "Test Users" | `
    Where-Object {$_.SoftwareName -eq "TestApp Mobile Edge" -and $_.DeploymentIntent -eq 3}

#remove the simulation (because you can't have the same app targeting the same collection)
Remove-CMDeployment -ApplicationName $Simulation.SoftwareName -CollectionName $Simulation.CollectionName -force

#create the deployment, based on information fromt he simulation
#This will create a deployment with a deadline 3 days from today at 8PM local time
Start-CMApplicationDeployment -CollectionName $Simulation.CollectionName -Name $Simulation.SoftwareName `
    -DeployAction Install -DeployPurpose Required -DeadlineDate (get-date).adddays(3).ToShortDateString() `
    -DeadlineTime "20:00" -TimeBaseOn LocalTime