Update:
Updated the script to only accept 1 variable and thats DestinationPath, the rest its now automated in the script so no need to specify Siteserver or SiteCode any more but you need to run the script locally on your Siteserver, the script is also now available on Technet.
So the other day at the office i needed to use and create a detection script for a new application and before i started to write it i had a pretty good understanding on how i wanted it to look like and in that moment i thought “wait a minute, i think i have written something like this before for another application. Lets just reuse that one!”
Perfect idea! Only one problem tho…. I couldn’t for the life of me remember which application it was (typical me) . So in the hope of that it would be my lucky day i took a few minutes to randomly trying to go through some of the applications and see if i could find it manually in SCCM. And no, lady luck wasn’t on my side that day.
So i turned to my old friend Powershell and made script that would help me out.
What do we want to achieve?
We want to be able to get the Application name and the Powershell detection script for every application that uses powershell as detection scripts. When we have that information we out put it to a file which is named after the application and output the detection script in to the file.
The Script
<# .NOTES =========================================================================== Created on: 12/06/2016 Modified on: 3/31/2017 Created by: Timmy Andersson Contact: @Timmyitdotcom =========================================================================== .DESCRIPTION A description of the file. #> [CmdletBinding(DefaultParameterSetName = 'DestinationPath')] param ( [Parameter(Mandatory = $true, Position = 1)] $DestinationPath ) BEGIN { [String]$Filepath = $DestinationPath $SiteCodeObjs = Get-WmiObject -Namespace "root\SMS" -Class SMS_ProviderLocation -ComputerName $env:COMPUTERNAME -ErrorAction Stop foreach ($SiteCodeObj in $SiteCodeObjs) { if ($SiteCodeObj.ProviderForLocalSite -eq $true) { $SiteCode = $SiteCodeObj.SiteCode } } $SitePath = $SiteCode + ":" Import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0, $Env:SMS_ADMIN_UI_PATH.Length - 5) + '\ConfigurationManager.psd1') } PROCESS { if (-not (Test-Path $DestinationPath)) { new-item -Path $DestinationPath -ItemType Directory -Force } Set-location $SitePath $Apps = (Get-CMApplication) foreach ($App in $Apps) { $Script = ([Microsoft.ConfigurationManagement.ApplicationManagement.Serialization.SccmSerializer]::DeserializeFromString($App.SDMPackageXML)).DeploymentTypes[0].Installer if ($Script.DetectionScript -ne $Null) { $PSscript = ([Microsoft.ConfigurationManagement.ApplicationManagement.Serialization.SccmSerializer]::DeserializeFromString($App.SDMPackageXML)).DeploymentTypes[0].Installer.DetectionScript if ($PSscript.Language -like "PowerShell") { Out-File -FilePath "$Filepath$($App.LocalizedDisplayName).ps1" -InputObject $PSscript.Text } } } } END { }
Example
Made this youtube video showing of how the script works
Until next time, cheers Timmy !
You can find me over at
[twitter-follow screen_name=’Timmyitdotcom’]
Old post, but just found this today.
Thanks, this is great.
One thing I changed was to pipe get-cmapplication directly into a foreach-object, instead of using a variable and foreach(), only because in my environment it takes a very, *very* long time to get all those applications, and by piping I start seeing results almost immediately.
Another change was to handle LocalizedDisplayName with characters not allowed in filenames. Too many app names like “blah w/ plugins”
A final change was to use Set-Content rather than Out-File. I was worried that Out-File’s default 80-column line-truncation feature could give unexpected, undesired results, say for very long registry hives, and it seemed wrong to kludge it by using a very long line length.
Thanks again for this great script!
~~James
Thanks for your input ! Always appreciated to hear other ppls opinion and how they solved things.