Introduction

This blog post explains how you can use a Powershell script in an SCCM detection method to detect file content.

My detection method scenario

I came across a customer scenario where configuration files were replaced in the installation directory during application installation using a script. Since a configuration line was different in the different files, this had to be checked during the application detection after the installation.

The easy way out would have been to detect the configuration file’s existence, but I also wanted to make sure the file’s content was correct.

How to use SCCM detection methods

When configuring SCCM detection methods, you want the Detection Method to be as granular as possible.

Some out-of-the-box Detection Methods which work very well:

  • MSI
  • Registry keys
  • File version

Detection Methods are one of the main culprits when dealing with application deployment issues.

Sometimes the Detection Method is misconfigured, and the SCCM client does not detect the application as installed, or a Detection Method is configured as non-granular.

An example of this is adding to a script that a text file is to be created and then use it to detect if the application is installed. This is not the right way to configure detection methods in SCCM.

Read more about Powershell Detection Methods here: Microsoft Docs – Introduction to Application Management.

Powershell script detection methods in SCCM

How Powershell script detection methods work

When creating Powershell detection methods in SCCM, you need to understand how they work. Understanding how the Powershell detection method works include understanding how SCCM interprets your Powershell detection method’s output.

The below table from Microsoft Docs shows how the script output defines the result:

Script exit codeData read from STDOUTData read from STDERRScript resultApplication detection state
0EmptyEmptySuccessNot installed
0EmptyNot emptyFailureUnknown
0Not emptyEmptySuccessInstalled
0Not emptyNot emptySuccessInstalled
Non-zero valueEmptyEmptyFailureUnknown
Non-zero valueEmptyNot emptyFailureUnknown
Non-zero valueNot emptyEmptyFailureUnknown
Non-zero valueNot emptyNot emptyFailureUnknown

My Powershell SCCM detection method solution

Introduction

This solution uses Powershell to parse a text file, which in my example is a configuration file. The Powershell script returns a result upon string discovery.

You can use this solution as an example if you want to look for other strings in text files.

How to implement the Powershell detection method solution

Step 1 – Create the application

Start by going to the Software Library and press Create Application.

Select Manually specify the application information.

Enter the information about the application.

Input any additional information about the application.

Step 2 – Create the deployment type

On the next step, press Add to add a new Deployment Type.

Select Manually specify the deployment type information.

Enter the Name of the Deployment Type. The Deployment Type name can be anything.

Powershell detection methods

Enter the installation instructions of the application according to your requirements.

Powershell detection methods

Step 3 – Create the Powershell detection method

Now we are the main subject of this blog post, namely SCCM detection methods using a Powershell script.

Select Use a custom script to detect the presence of the deployment type. Press Edit.

SCCM detection method
Modify the Powershell script

Modify the below script to suit your needs. The example below will look at strings in 3 different files. You will need to make the following modifications:

  • String variables
  • String<number>Location variables

Change Script type to Powershell and enter the code below this screenshot in the text box. You will, of course, need to modify it to suit your needs.

Powershell detection methods
Powershell detection method example
#Define strings and their location. Also include the filename.
$String1 = ""
$String1Location = ""
$String2 = ""
$String2Location = ""
$String3 = ""
$String3Location = ""
# Detect presence of String1 in String1 Location
try {
    $String1Exists = Get-Content $String1Location -ErrorAction Stop
}
catch {
}
# Detect presence of String2 in String2 Location
try {
    $String2Exists = Get-Content $String2Location -ErrorAction Stop
}
catch {
}
# Detect presence of String3 in String3 Location
try {
    $String3Exists = Get-Content $String3Location -ErrorAction Stop
}
catch {
}
if (($String1Exists -match $String1) -and ($String2Exists -match $String2) -and ($String3Exists -match $String3)) {
    Write-Host "Installed"
}
else {
}

Step 4 – Finalize the application

Once you have added the Detection Method, you will need to go through the rest of the wizard to finalize the process.

Step 5 – Distribute and deploy the application

End by Distributing and Deploying the application to users or devices, depending on your environment.

Conclusion

Powershell Detection Methods are powerful to use when you cannot use the default MSI, registry, or file version detections. However, they are a bit more complicated and getting your head around how the script work’s return logic might take some time.

For all scenarios, when you can use a built-in Detection Method, use that, but in all other custom cases, you can use Powershell Detection Methods.

References

Related posts

6 COMMENTS

  1. Hi Daniel
    Can we have the full detection script somewhere? The bottom few lines are missing from the screenshot
    Regards
    Andy

  2. Hi Daniel!

    I followed your detection example and created my own:

    $String1 = “tnsnames.ora”
    $String1Location = “C:\app\$username\product\11.2.0\client_1\network\admin\”

    try {
    $String1Exists = Get-Content $String1Location -ErrorAction Stop
    }
    catch {
    }

    if (($String1Exists -match $String1) ) {
    Write-Host “Installed”
    }
    else {
    }

    However, it is still not able to detect the file, however it there.

    Would you please let me know what is missing?

    Thank you!

    Divna

  3. @Divna I did the same thing you did and then paid closer attention to the script. You need to declare the file name in $String1Location too, plus all the extra parenthesis aren’t needed since it’s just one compare. I added output for testing:

    #Define strings and their location. Also include the filename.

    $String1 = “file.exe”
    $String1Location = “C:\folder\foo\file.exe”

    # Detect presence of String1 in String1 Location
    try {
    $String1Exists = Get-Content $String1Location -ErrorAction Stop
    }
    catch {
    }

    if ($String1Exists -match $String1) {
    Write-Host “Installed”
    }
    else {
    Write-Host “FAILSAUCE”
    }

  4. Hi Daniel!

    I followed your detection example and created my own:

    #Define files and their location. Also include the filename in the path location.

    $File1 = “tnsnames.ora”
    $Path1Location = “C:\app\$user\product\11.2.0\client_2\network\admin\tnsnames.ora”

    # Detect presence of File1 in Path1 Location

    try {
    $Path1Exists = Get-Content $Path1Location -ErrorAction Stop
    }
    catch {
    }

    # Detect presence of File1 in Path1 Location

    if ($Path1Exists -match $File1) {
    Write-Host “Installed”
    }
    else {
    Write-Host “Not Installed”
    }

    The file installs successfully but the detection fails. Running the script manually on the computer outputs “Not Installed”

    $File1 show a value of tnsnames.ora but $Path1Exists outputs the contents of the tnsname.ora file

    What am I missing?

  5. Good Morning,

    THank you for this, it is very useful.

    Nevertheless, how can i create a Detection Method for an application like zoom where the updates should be automatically installed, the registry code is always changing and the version as well.

    I was trying the following DM but i am getting some errors:

    [CmdletBinding()]
    param()
    # Update the product name for detection here
    $exists = [version](gcim win32_product| ? caption -match ‘Zoom’).version -ge [version]’5.8.1736′

    if($exists){
    Write-Output $true
    }

    THanks and regards.

    Yamael

LEAVE A REPLY

Please enter your comment!
Please enter your name here