[UPDATE] Looking for more #PowerShell + #ConfigMgr awesomeness , Check out my compiled list of posts --> www.dexterposh.com/p/collection-of-all-my-configmgr.html
Earlier I blogged about using PowerShell to create an Application from MSI but wait am just warming up to what Configuration Manager has to offer with PowerShell :D
If you haven't configured Virtual Memory (Page File Size) manually then the System manages it for you. So is the case with all the Systems in my Lab.
This is a cool script and if you are looking for something similar to do in your environment then please go through it , I am sure you will learn quite a few bits from it. I know I did :)
Apart from the Module I need 2 more Scripts to Set the VM size and Unset it. I know I could have copied functions from the Module in these 2 PS1 and gone that way too. But let's stick with the Module Approach. Store all three (2 PS1 + 1 PSM1 files in a Shared path probably where all your Packages go in SCMM )
set_VM_Size.ps1
Second file : Unset_VM_size.ps1
Earlier I blogged about using PowerShell to create an Application from MSI but wait am just warming up to what Configuration Manager has to offer with PowerShell :D
In this post we will be creating an Application having a deployment type which will run PowerShell Scripts (Install / Uninstall). Detect if the Script needs to be run on the Client (using PowerShell code) this is something called Script Detection Method in ConfigMgr.
Let me put this in simple layman terms we will be deploying Scripts to clients and executing them using Configuration Manager Infrastructure.
Let me put this in simple layman terms we will be deploying Scripts to clients and executing them using Configuration Manager Infrastructure.
Scenario:
If you haven't configured Virtual Memory (Page File Size) manually then the System manages it for you. So is the case with all the Systems in my Lab.
So I want to deploy a PS1 Script which will set this (install) and another PS1 Script which will revert this setting to System managed if required (uninstall).
Well that's not all.....just to be clear will be doing all of this using PowerShell (Aah! you knew that already :P !) So let's get the party started <:-p<:-p <:-p <:-p
The Application creation & deployment process will follow the same Steps of :
The Application creation & deployment process will follow the same Steps of :
- Creating the Application
- Adding a Deployment Type
- Distributing the Content to the DP Group
- Creating a Collection & Add members to it
- Deploy the Application to the Collection
The PowerShell Script:
Well I already have the Script from Technet Gallery which serves my requirement (why re-invent the wheel, right ?? ) It's a good idea to search Technet Gallery for any Scripts before you start, maybe you won't find the exact one but it will serve as a good starting point.
This Script is a PowerShell Module which has 2 functions defined inside it.
Set-OSCVirtualMemory and Set-PageFileSize .
One needs to test the Scripts before using them in Applications because it may not work sometime. I have tested it locally on my Machine and after knowing that it works am ready to setup an Application and finally deploy it.
By default the OS manages the PageFile for the System which is evident by the property AutomaticManagedPageFile on WMI Class Win32_ComputerSystem
Below is what I see on my machine right now which means the System manages page file on my machine (DexterDC).
Below is what I see on my machine right now which means the System manages page file on my machine (DexterDC).
PS> (Get-CimInstance -ClassName Win32_ComputerSystem).AutomaticManagedPageFile True
The Script takes above into account disables it and sets the PageFile Size which you specify and also later you can revert back to the setting where System manages it.
This is a cool script and if you are looking for something similar to do in your environment then please go through it , I am sure you will learn quite a few bits from it. I know I did :)
Apart from the Module I need 2 more Scripts to Set the VM size and Unset it. I know I could have copied functions from the Module in these 2 PS1 and gone that way too. But let's stick with the Module Approach. Store all three (2 PS1 + 1 PSM1 files in a Shared path probably where all your Packages go in SCMM )
set_VM_Size.ps1
Second file : Unset_VM_size.ps1
Create Application
Now once we have the Scripts & the Module ready. Let's go ahead with the Application creation. We will go with the same steps which were taken to create a MSI application ....but we will have to specify a lot of information manually here in this case.
Create the Application Object
This will create the Application you can set whole lot of properties on this Object using Set-CMApplication cmdlet. I am gonna move forward. For sake of convenience let me store the Application name in a variable do this:
Now with ConfigMgr 2012 we have various detection methods which detect if the application is already installed. In this case let's define a here-string containing our PS1 code which detects if the Virtual Memory is already configured as per our needs. Before you go on and criticize usage of write-host see this post here .
So now we have a Script code which will detect if the PowerShell Script which we deploy is at all needed to run on the machine to configure the Virtual Memory.
After this let's create the deployment type, it's a very big expression so am gonna use splatting. If you don't know about splatting then you have to do some reading :-B read the about_Splatting article in PowerShell.
Below is my splatting variable and the Key Values come from the various parameter names in the cmdlet Add-CMDeployment type ...see the comments in the same line too which attempt to explain it.
Note - the above $ScriptDetection variable is used below.
Is it me or these are a lot of parameters /sweat
Once we have parameters Now time to execute the code...we will use our Splatting variable here:
Now after this you should be seeing a Application created in the ConfigMgr Console and the deployment type too.
We can go ahead and verify all the properties in the ConfigMgr Console but to show why we used here-string above to set up the Script detection method earlier, below is a Screenshot showing the Detection Method for the Deployment Type.
When we click on the "Edit" button the Script Editor opens up which has our code B-)
After this let me move this Application under the PowerShell folder. You can read my earlier post on using Folders to organize in SCCM on how this works.
#Distribute the Content to the DP Group
Create the Application Object
New-CMApplication -Name "PowerShell Set PageFile" -Description "The Script will set the Page File Size to Initial 1024 and 2048 maximum" -SoftwareVersion "1.0" -AutoInstall $true
This will create the Application you can set whole lot of properties on this Object using Set-CMApplication cmdlet. I am gonna move forward. For sake of convenience let me store the Application name in a variable do this:
$Applicationname = "PowerShell Set PageFile"
Now with ConfigMgr 2012 we have various detection methods which detect if the application is already installed. In this case let's define a here-string containing our PS1 code which detects if the Virtual Memory is already configured as per our needs. Before you go on and criticize usage of write-host see this post here .
$scriptDetection = @' $pagefile = Get-WmiObject -Class Win32_PageFileSetting $AutomaticManagePageFile = Get-WmiObject -Class Win32_ComputerSystem if (($pagefile.InitialSize -eq 1024) -and ($pagefile.MaximumSize -eq 2048) -and ($AutomaticManagePageFile.AutomaticManagedPagefile -eq $false)) { Write-host "Installed" } else { } '@
So now we have a Script code which will detect if the PowerShell Script which we deploy is at all needed to run on the machine to configure the Virtual Memory.
After this let's create the deployment type, it's a very big expression so am gonna use splatting. If you don't know about splatting then you have to do some reading :-B read the about_Splatting article in PowerShell.
Below is my splatting variable and the Key Values come from the various parameter names in the cmdlet Add-CMDeployment type ...see the comments in the same line too which attempt to explain it.
Note - the above $ScriptDetection variable is used below.
$DeploymentTypeHash = @{ ManualSpecifyDeploymentType = $true #Yes we are going to manually specify the Deployment type Applicationname = "$ApplicationName" #Application Name DeploymentTypeName = "POSH Set PageFile" #Name given to the Deployment Type DetectDeploymentTypeByCustomScript = $true # Yes deployment type will use a custom script to detect the presence of this ScriptInstaller = $true # Yes this is a Script Installer ScriptType = 'PowerShell' # yep we will use PowerShell Script ScriptContent =$scriptDetection # Use the earlier defined here string AdministratorComment = "This will set and reset the VM(pagefile) size" ContentLocation = "\\dexsccm\Packages\PS1_SetVMSize" # NAL path to the package InstallationProgram ='powershell.exe -file ".\Set_VM_Size.ps1"' #Command line to Run for install UninstallProgram ='powershell.exe -file ".\Unset_VM_size.ps1"' #Command line to Run for un-Install RequiresUserInteraction = $false #Don't let User interact with this InstallationBehaviorType = 'InstallForSystem' # Targeting Devices here InstallationProgramVisibility = 'Hidden' # Hide the PowerShell Console }
Is it me or these are a lot of parameters /sweat
Once we have parameters Now time to execute the code...we will use our Splatting variable here:
Add-CMDeploymentType @DeploymentTypeHash
Now after this you should be seeing a Application created in the ConfigMgr Console and the deployment type too.
We can go ahead and verify all the properties in the ConfigMgr Console but to show why we used here-string above to set up the Script detection method earlier, below is a Screenshot showing the Detection Method for the Deployment Type.
When we click on the "Edit" button the Script Editor opens up which has our code B-)
After this let me move this Application under the PowerShell folder. You can read my earlier post on using Folders to organize in SCCM on how this works.
$Application = Get-CMApplication -Name $Applicationname $POSHFolder = Get-CimInstance -ClassName "SMS_ObjectContainerNode" -Filter "Name='PowerShell'" -ComputerName DexSCCM -Namespace root/SMS/Site_DEX -Verbose Invoke-CimMethod -ClassName SMS_ObjectContainerItem -MethodName MoveMembersEx -Arguments @{InstanceKeys=[string[]]$Application.ModelName;ContainerNodeID=[System.UInt32]0;TargetContainerNodeID=[System.UInt32]($POSHFolder.ContainerNodeID);ObjectTypeName="SMS_ApplicationLatest"} -Namespace root/sms/site_DEX -ComputerName DexSCCM -VerboseSo now we are ready with our Application and the deployment type, let's distribute the content to the Boundary Group in my LAB.
#Distribute the Content to the DP Group
Start-CMContentDistribution -ApplicationName "$ApplicationName" -DistributionPointGroupName "Dex LAB DP group" -Verbose
After this let me create a Device Collection to hold the Members for the deployment of this Application.
#create the Device Collection
Now to stress the importance of Folders a bit in ConfigMgr, I had gone and created Folders below the "Device Collections" using PowerShell ;) to reflect the same structure as that under Applications making it easy for me :
You can move the newly created Device Collection under the PowerShell folder too to be consistent with what we are doing.
Enough :D Let's add a member to the Collection and deploy the Application to it.
After this wait for some time or refresh machine policy on the client (can use Invoke-CMClientNotification cmdlet ) to see the Application appear up in the Software Center.
But even after waiting for a while it doesn't shows up then..... ???
There's a gotcha here if you haven't set the Execution Policy (for PowerShell) in the Client Settings then you would see something like this in the AppDiscovery.log on the Client side.
Bottom line is--> To use PowerShell Script as a detection method we need to have deployed proper Client Settings on the Clients to set the Execution Policy.
So you should either create a Custom Client settings and deploy it to the Collection with the Members where the Application using Script Detection will be used or change your default client settings (not advised).
In ConfigMgr 2012 you can create Custom Client Settings and deploy those to Collections. I did blog about doing that with PowerShell too Check it out Here
So once the appropriate Client settings are deployed to the Client, you need to initiate the Application manager Machine Policy Action so that the Application gets discovered. You can do this with PowerShell to on the Client:
After this you will see in the AppDiscovery.log that the Script Detection works fine and the application shows up in Software Center
Click on Install and it gets installed.
Let's verify that the System doesn't manage Page file anymore and the Page File Settings did get changed.
Note : after Clicking on Install you can see the AppEnforce.log for some interesting entries ;)
That's it for the first part. Will be back with more awesomeness in next one.
/wahaha /bye
#create the Device Collection
New-CMDeviceCollection -Name "$ApplicationName" -Comment "All the Machines where $ApplicationName is sent to" -LimitingCollectionName "All Systems" -RefreshType Periodic -RefreshSchedule (New-CMSchedule -Start (get-date) -RecurInterval Days -RecurCount 7)
You can move the newly created Device Collection under the PowerShell folder too to be consistent with what we are doing.
Enough :D Let's add a member to the Collection and deploy the Application to it.
#Add the Direct Membership Rule to add a Resource as a member to the Collection Add-CMDeviceCollectionDirectMembershipRule -CollectionName "$ApplicationName" -Resource (Get-CMDevice -Name "DexterDC") -Verbose #start the Deployment Start-CMApplicationDeployment -CollectionName "$ApplicationName" -Name "$ApplicationName" -DeployAction Install -DeployPurpose Available -UserNotification DisplayAll -AvaliableDate (get-date) -AvaliableTime (get-date) -TimeBaseOn LocalTime -Verbose
After this wait for some time or refresh machine policy on the client (can use Invoke-CMClientNotification cmdlet ) to see the Application appear up in the Software Center.
But even after waiting for a while it doesn't shows up then..... ???
There's a gotcha here if you haven't set the Execution Policy (for PowerShell) in the Client Settings then you would see something like this in the AppDiscovery.log on the Client side.
Bottom line is--> To use PowerShell Script as a detection method we need to have deployed proper Client Settings on the Clients to set the Execution Policy.
So you should either create a Custom Client settings and deploy it to the Collection with the Members where the Application using Script Detection will be used or change your default client settings (not advised).
In ConfigMgr 2012 you can create Custom Client Settings and deploy those to Collections. I did blog about doing that with PowerShell too Check it out Here
So once the appropriate Client settings are deployed to the Client, you need to initiate the Application manager Machine Policy Action so that the Application gets discovered. You can do this with PowerShell to on the Client:
Invoke-CimMethod -ClassName SMS_Client -MethodName TriggerSchedule -Arguments @{sScheduleID='{00000000-0000-0000-0000-000000000121}'} -Namespace root/ccm
After this you will see in the AppDiscovery.log that the Script Detection works fine and the application shows up in Software Center
Click on Install and it gets installed.
Let's verify that the System doesn't manage Page file anymore and the Page File Settings did get changed.
Note : after Clicking on Install you can see the AppEnforce.log for some interesting entries ;)
That's it for the first part. Will be back with more awesomeness in next one.
/wahaha /bye