Application Detection Methods

by jennyfer at 2013-04-24 16:32:17

I am trying to find something online for direction about using PowerShell as a detection method for ConfigMgr 2012 applications.
I wrote this to generate a true or false result to try to detect that this path does not exsit. I couldn’t use the built in folder detection method because it only allows me to says "The file system setting must exist on the target system to indicate presence of this application". I actually want the opposite. If the folder does not exist I want the application to show as installed.
$path = "C:\Windows\options\websense"
if(!(Test-Path -Path $path))
{
$true
}
else
{
$false
}


The output I get from running this command manually on a computer is:

PS C:> $path = "C:\Windows\options\websense"
if(!(Test-Path -Path $path))
{
$true
}
else
{
$false
}
False


So it looks to me that the output is "False" so that would mean that the application is not installed and the deployment should run.
When I push the application to the computer that has this result, the Software Center is showing this application as "installed"
I’m confused why it’s showing this way if my Powershell script is generating false. I think I might be going about this the wrong way and just need some direction on how to set this up. Is the $true / $false the wrong way? Any help or links to documentation you can provide would be helpful.
by Bpmorris at 2013-04-24 18:11:16
Hi Jennyfer,

I thought I would take a quick stab at your question before attempting my first PowerShell scripting games event. Also as a quick disclaimer, the environment I run is still CM07 so I took this as a opportunity research how to do application detection in CM12 so please keep that in mind when reading and testing my advice.

My very first comment would be to ensure you have PS script execution set to something like ‘remotesigned’ or ‘unrestricted’ on any machine you intent to use PowerShell scripts. You can easily check this with ‘Get-ExecutionPolicy’. Without this no PS code will run and ConfigMgr will never tell you this is the cause in any web report.

Secondly your code does not appear to work when run within the ISE as your $True$False objects contain nothing and produce errors for me. Also as you have NOT (!) before your IF test script block so also I think you might have been expecting the true and false to occur in different places. Personally I would not have have used a NOT as reading double negatives always confuse me. :slight_smile: I am also not sure why you had a ‘false’ on the end line of your script, this straight away produced an error for me and I had to immediately # it out to troubleshoot further.

From what I can see from the linked TechNet article the PS code must BOTH complete successfully with an exit code of 0 AND return a result to screen which the CM12 agent will read just like a human being would. Generally so long as your PS code is syntactically correct I would expect it always complete with an exit code 0 so don’t stress about this requirement. That just leaves a requirement to write a result to screen if the application IS INSTALLED. My understanding is that you need to be testing if the application is installed, not is it missing.

So with that said I would try one of two things, either change your code to:

$path = "C:\Windows\options\websense"
if((Test-Path -Path $path))
{
Write-host "Installed"
}
else
{
}

Note: I have deliberately not returned anything to screen when the folder does not exist as this could be interpreted as a installed result.

Or reuse the other linked example]

$testfile = Get-ChildItem -Path C:\Windows\options\websense
$testfile.Exists

The second code snipet will always error out unless the folder exists, when it does exist it will just write ‘TRUE’ to the screen which CM will read as the application is installed.

My last tip would be to install PowerShell v3 and use the ISE editior that comes with as for simple little scripts like this I find it extremely clean and easy to use.

The official word from MS on doing this]
http://technet.microsoft.com/en-us/libr … BKMK_Step4

An example blog showing working code you could copy directly]
http://sccmfaq.wordpress.com/2013/03/19 … e-signing/

I hope the above is useful in someway, lucky for you I had to figure out how to do something similar for the first time in CM07 DCM detection rules with PowerShelll yesterday so I assume CM12 is very similar in behavior.

Good luck! let us all know how you go.
by jennyfer at 2013-04-25 18:03:40
Thanks for your reponse. I tried what you said here but I reversed it:

$path = "C:\Windows\options\websense"
if((Test-Path -Path $path))
{

}
else
{
Write-host "Installed"
}


This returns the following in the AppDiscovery.log

In-line script returned error output: Get-ChildItem : Cannot find path ‘C:\Windows\options\websense’ because it does
not exist.
At C:\Windows\CCM\SystemTemp\ecff494c-b4d3-4ea3-82f9-9c43834b4b75.ps1:1 char:9
+ $path = Get-ChildItem -Path C:\Windows\options\websense
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Windows\options\websense:Str
ing) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetCh
ildItemCommand

Test-Path : Cannot bind argument to parameter ‘Path’ because it is null.
At C:\Windows\CCM\SystemTemp\ecff494c-b4d3-4ea3-82f9-9c43834b4b75.ps1:2 char:21
+ if((Test-Path -Path $path))
+ ~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Test-Path], ParameterBindingVa
lidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
icrosoft.PowerShell.Commands.TestPathCommand

AppDiscovery 4/25/2013 5:59:14 PM 524 (0x020C)
A script execution error has occurred. The script has no output in stdout and an error message in stderr. AppDiscovery 4/25/2013 5:59:14 PM 524 (0x020C)
Script Execution returned error message: Get-ChildItem : Cannot find path ‘C:\Windows\options\websense’ because it does
not exist.
At C:\Windows\CCM\SystemTemp\ecff494c-b4d3-4ea3-82f9-9c43834b4b75.ps1:1 char:9
+ $path = Get-ChildItem -Path C:\Windows\options\websense
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Windows\options\websense:Str
ing) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetCh
ildItemCommand

Test-Path : Cannot bind argument to parameter ‘Path’ because it is null.
At C:\Windows\CCM\SystemTemp\ecff494c-b4d3-4ea3-82f9-9c43834b4b75.ps1:2 char:21
+ if((Test-Path -Path $path))
+ ~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Test-Path], ParameterBindingVa
lidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
icrosoft.PowerShell.Commands.TestPathCommand

, ExitCode: 4294967295 AppDiscovery 4/25/2013 5:59:14 PM 524 (0x020C)
Script Execution Returned :4294967295, Error Message: Get-ChildItem : Cannot find path ‘C:\Windows\options\websense’ because it does
not exist.
At C:\Windows\CCM\SystemTemp\ecff494c-b4d3-4ea3-82f9-9c43834b4b75.ps1:1 char:9
+ $path = Get-ChildItem -Path C:\Windows\options\websense
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Windows\options\websense:Str
ing) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetCh
ildItemCommand

Test-Path : Cannot bind argument to parameter ‘Path’ because it is null.
At C:\Windows\CCM\SystemTemp\ecff494c-b4d3-4ea3-82f9-9c43834b4b75.ps1:2 char:21
+ if((Test-Path -Path $path))
+ ~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Test-Path], ParameterBindingVa
lidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
icrosoft.PowerShell.Commands.TestPathCommand

. [AppDT Id: ScopeId_8E1BCE4D-882B-4016-A08B-F2CB15B50D86/DeploymentType_37826149-4d1b-4c1c-af92-612fe520ef13, Revision: 6] AppDiscovery 4/25/2013 5:59:14 PM 524 (0x020C)
CScriptHandler::DiscoverApp failed (0x87d00329). AppDiscovery 4/25/2013 5:59:14 PM 524 (0x020C)
Deployment type detection failed with error 0x87d00329. AppDiscovery 4/25/2013 5:59:14 PM 524 (0x020C)
Failed to perform detection of app deployment type Delete Websense Directory(Delete Websense Directory, revision 6) for user. Error 0x87d00329 AppDiscovery 4/25/2013 5:59:14 PM 524 (0x020C)
Entering ExecQueryAsync for query "select * from CCM_AppDeliveryType where (AppDeliveryTypeId = "ScopeId_8E1BCE4D-882B-4016-A08B-F2CB15B50D86/DeploymentType_909ed274-845a-4db0-97c9-ce79aeb66ecc" AND Revision = 6)" AppDiscovery 4/25/2013 5:59:14 PM 524 (0x020C)
Performing detection of app deployment type Delete Startup Key(ScopeId_8E1BCE4D-882B-4016-A08B-F2CB15B50D86/DeploymentType_909ed274-845a-4db0-97c9-ce79aeb66ecc, revision 6) for user. AppDiscovery 4/25/2013 5:59:14 PM 524 (0x020C)
+++ Discovered application [AppDT Id: ScopeId_8E1BCE4D-882B-4016-A08B-F2CB15B50D86/DeploymentType_909ed274-845a-4db0-97c9-ce79aeb66ecc, Revision: 6] AppDiscovery 4/25/2013 5:59:15 PM 524 (0x020C)
+++ Detected app deployment type Delete Startup Key(ScopeId_8E1BCE4D-882B-4016-A08B-F2CB15B50D86/DeploymentType_909ed274-845a-4db0-97c9-ce79aeb66ecc, revision 6) for S-1-5-21-1572248175-486741157-3386894362-8207. AppDiscovery 4/25/2013 5:59:15 PM 524 (0x020C)


It is running but giving an error because the path does not exist. It looks like I’m still missing something here. The script should be returning no results, but the log is showing an error.
by Bpmorris at 2013-04-25 18:47:22
I think you have your ‘Installed’ response in the wrong script block. I belive CM needs the script output to indicate when an app is installed. Try the below code or the other two liner in my earlier response which I stole from the blog I linked too. If that still doesnt work if I have time over the weekend I will duplicate on my test server.

if((Test-Path -Path $path))
{
Write-host "Installed"
}

Cheers

Ben
by jennyfer at 2013-04-29 16:04:26
Thank you for your comments, they really helped me find the solution. I found the erorr I posted earlier was due the application itself not running properly. I fixed that issue and found I was still getting errors properly detecting the application was "installed" (or in my case, not present). I found that the PowerShell script was throwing errors when it couldn’t resolve the path:


In-line script returned error output: Get-ChildItem : Cannot find path ‘C:\Windows\options\websense’ because it does
not exist.
At C:\Windows\CCM\SystemTemp\10f62033-0e41-433d-b4fe-05790d98d945.ps1:1 char:9
+ $path = Get-ChildItem -Path C:\Windows\options\websense
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\Windows\options\websense:Str
ing) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetCh
ildItemCommand


I rewrote the PowerShell detection script to suppress errors (because in this case it doesn’t matter). I had to also add another if statement if the "$path -ne $null". I had to do this because if the $path was null I was getting another error that would make the script throws errors when SCCM tried to use it.
In the end, I have three working PowerShell detection scripts:

Detects if this path exists. In my case, I wanted the application to show installed if the path does not exist.
$path = Get-ChildItem -Path C:\Windows\options\websense -ErrorAction SilentlyContinue
if ($path -ne $null) {
if((Test-Path -Path $path))
{
}
else
{
Write-Host "Installed"
}
} else {
Write-Host "Installed"
}


Detects if this registry key exists, In my case, I wanted the application to show installed if the registry key does not exist.
$path = "HKLM:\SOFTWARE\Microsoft\Shared Tools\MSConfig\startupreg\Websense"
if((Test-Path -Path $path))
{

}
else
{
Write-Host "Installed"
}


Detects the SCCM Cache size. I have several application (that will only deploy to a handful of users) that require approx. 20 GB of space to install (they are huge). I wanted to make a dependency program to only increase the cache size on the clients that were installing these large applications. This script will detect if the cache size is greater than 20 GB, if not, it will run the script to increase the cache.
$cache = Get-WmiObject -Namespace root\ccm\softmgmtagent -class cacheconfig
if ($cache.size -gt 20000) {
Write-Host "Installed"
}
if ($cache.size -lt 20000) {
}


Ben, thanks for your ideas and comments. You were right that there should be no output if it’s not installed.
Thank you!
by Bpmorris at 2013-04-30 04:15:30
Hi Jennyfer

Glad you had a successful outcome, it was in interesting learning exercise for me too.

Cheers

Ben