I’m sure everyone reading this has deployed many applications within Intune using the win32 format and most likely used an MSI code or a file/registry detection method to monitor for a completed install (and why wouldn’t you, they work perfectly)
Sometimes however, you might come across an application which is more tricky to detect, or you want to look for two things before you’re confident it’s installed ok. This is where a custom detection script comes into play.
As with my previous post on Proactive Remediations, Intune is looking for specific outputs for the script to return a success code.
In this case, it is looking for BOTH an exit with a 0 code and output on STDOUT. For those of you rapidly opening a new tab to google STDOUT, basically, it needs output of some sort, a simple:
write-output "hello world"
exit 0
Will work fine, so that is what we need the script to return at the end in order for it to be marked as successful.
Passing an exit code 1 or even an exit 0 without any output will flag as an install failure.
Important Note: Detection scripts ONLY work in the System context so if detecting at the user level, you need to enumerate the logged in user. Check the final example to see how.
Now for some examples:
A basic file check (in case you’re feeling scripty)
$File = "C:\windows\system32\notepad.exe"
if (Test-Path $File) {
write-output "Notepad detected, exiting"
exit 0
}
else {
exit 1
}
A registry key (checking both it exists and the value is correct, good for versioning)
$Path = "HKLM:\SOFTWARE\7-Zip"
$Name = "Path"
$Type = "STRING"
$Value = "C:\Program Files\7-Zip\"
Try {
$Registry = Get-ItemProperty -Path $Path -Name $Name -ErrorAction Stop | Select-Object -ExpandProperty $Name
If ($Registry -eq $Value){
Write-Output "Detected"
Exit 0
}
Exit 1
}
Catch {
Exit 1
}
Now for the ones it can’t do out of the box!
Check if a service exists
$service = get-service -name "MozillaMaintenance"
if ($service) {
write-output "MozillaMaintenance detected, exiting"
exit 0
}
else {
exit 1
}
Service exists and is running:
$service = get-service -name "MozillaMaintenance"
if ($service.Status -eq "Running") {
write-output "MozillaMaintenance detected and running, exiting"
exit 0
}
else {
exit 1
}
Both file and service exist
$File = "C:\windows\system32\notepad.exe"
$service = get-service -name "MozillaMaintenance"
if (($service) -and (Test-Path $File)) {
write-output "MozillaMaintenance and Notepad detected, exiting"
exit 0
}
else {
exit 1
}
File is of a certain version
$fileversion = (Get-Command C:\Windows\System32\notepad.exe).Version
$build = 19041
$detectedbuild = $fileversion.Build
if ($detectedbuild -eq $build) {
write-output "Detected"
exit 0
}
else {
exit 1
}
Or even the file was last modified today
$filedate = (Get-Item C:\Windows\System32\notepad.exe).LastWriteTime
if ($filedate -gt (Get-Date).AddDays(-1)) {
write-output "Detected"
exit 0
}
else {
exit 1
}
When looking at logged in user, we need to find their details so for this I have a new function:
function getloggedindetails() {
##Find logged in username
$user = Get-WmiObject Win32_Process -Filter "Name='explorer.exe'" |
ForEach-Object { $_.GetOwner() } |
Select-Object -Unique -Expand User
##Find logged in user's SID
##Loop through registry profilelist until ProfileImagePath matches and return the path
$path= "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*"
$sid = (Get-ItemProperty -Path $path | Where-Object { $_.ProfileImagePath -like "*$user" }).PSChildName
$return = $sid, $user
return $return
}
Running this will give you the username and SID. For our 7-zip registry example:
$loggedinuser = getloggedindetails
##Set key
$sid = $loggedinuser[0]
$Path = "Registry::HKU\$sid\SOFTWARE\7-Zip"
$Name = "Path"
$Type = "STRING"
$Value = "C:\Program Files\7-Zip\"
Try {
$Registry = Get-ItemProperty -Path $Path -Name $Name -ErrorAction Stop | Select-Object -ExpandProperty $Name
If ($Registry -eq $Value){
Write-Output "Detected"
Exit 0
}
Exit 1
}
Catch {
Exit 1
write-host "not detected"
write-host $path
}
Or for a file at the user level:
$username = $loggedinuser[1]
$File = "C:\users\$username\AppData\Local\Microsoft\Teams\update.exe"
if (Test-Path $File) {
write-output "Teams Update detected, exiting"
exit 0
}
else {
exit 1
}
I hope that makes them easier to understand! Happy scripting…
Hey Andrew,
Great Post. I’m new to scripting. Need to detect multiple approved antivirus solutions like bitdefender, malwarebytes etc running on windows & mac devices. Could you help me with some starting point?
Hi,
Multiple across different devices or on the same device? I would probably start with looking at the services, every AV will have a service running
I’ve created a small detection script, to test for the existence of another script (file) and a registry path. The remediation creates or update the signature.ps1 file and sets a few entries in the registry.
$logonScriptPath = “C:\Windows\System32\GroupPolicy\User\Scripts\Logon\signature.ps1”
$policyRegPath = “HKCU:\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon\0\0”
IF ((Test-Path -Path $policyRegPath) -and
(test-path -Path $logonScriptPath) -and
(-not (Test-Path -Path $logonScriptPath -OlderThan (Get-Date).AddDays(-10))))
{
write-output “Outlook signature present and updated”
EXIT 0
}
ELSE
{
write-output “Outlook signature not present or outdated”
EXIT 1
}
The thing is, that in Intune, it always returns “Outlook signature present and updated” and detection status “without issues”. But when i run the script on a computer in powershell as system, it returns the opposite. Obviously, since the file and registry keys are missing. Am I just missing some understanding of the detection process?
I think the issue you are having is mixing user and device. Your logon script path can only be accessed with the system account, but the policy is in the users profile.
You’re going to need to run as system and navigate to the users registry hive via their SID, I have a function further down the page which should help
That would be a logical conclusion. However, when I remove the user hive, and variables from the script, I get the same result:
IF (
(test-path -Path “C:\Windows\System32\GroupPolicy\User\Scripts\Logon\signature.ps1”) -and
(!(Test-Path -Path “C:\Windows\System32\GroupPolicy\User\Scripts\Logon\signature.ps1” -OlderThan (Get-Date).AddDays(-10))))
{
write-output “Outlook signature script present and updated”
EXIT 0
}
ELSE
{
write-output “Outlook signature script not present or outdated”
EXIT 1
}
Still results in EXIT 1, when run in a system powershell, but EXIT 0 when run as detection script.
Running in the system context, 64-bit?
If might be worth splitting them out for testing and then you can see which is failing
$errorstatus = 0
$output = @()
IF (test-path -Path “C:\Windows\System32\GroupPolicy\User\Scripts\Logon\signature.ps1”) {
##Do nothing
}
ELSE {
$errorstatus++
$output += “Outlook signature script not present”
}
if (!(Test-Path -Path “C:\Windows\System32\GroupPolicy\User\Scripts\Logon\signature.ps1” -OlderThan (Get-Date).AddDays(-10)))
{
$errorstatus++
$output += “Outlook signature script outdated”
}
if ($errorstatus -gt 0)
{
write-output $output
exit 1
}
else
{
exit 0
}
Well, the problem seems to be quite mundane. Even though C:\Windows\System32\GroupPolicy\User\Scripts\Logon\signature.ps1 isn’t hidden, the path C:\Windows\System32\GroupPolicy is. And apparently the Test-Path in the detection script can’t traverse this barrier. Bummer.
Hello Andrew, firstly great article.
Now I have a question, what if I have an App which I need to re-install, but the App content (as example Folder/.exe is the same), App Version is the same. I just need to re-install it.
What detection rule should I use?
because I can’t use the File/Folder exists or Version Number is also the same, so i can’t use it for detection.
Hi,
That’s a tricky one. I would probably manually install on a test machine which already has the app installed on. Then look at the app directory and see if any files have a new modified date. You can then use that for your detection, modified after the date you deploy for example
Just check for the presence of a witness file. Put it in, say, \ProgramData\OrgName\AppName\witness.file and test for its presence. If it’s not present, reinstall, if it is, do nothing.
Hello,
I have to check a firewall rule, I’ve wrote this detection script :
$FirewallRule = get-NetFirewallRule -DisplayName MyRule
if ($FirewallRule.Enabled) {
exit 0
} else {
exit 1
}
Intune Status Details : 0x80070001
Any thoughts?
The script looks correct, sometimes that error just means it is processing. How long have you left it?
Thank you for your reply.
Reading the other comments, I tried something that solved my issue.
$FirewallRule = get-NetFirewallRule -DisplayName “My Rule” | Select-Object -first 1
$status = ($FirewallRule.Enabled).ToString()
if ($status) {
write-output “Rule exists”
exit 0
} else {
write-output “No Rule”
exit 1
}
I have requirement to detect the removal of the app under the below two paths via detection script. but always a failure. Can you please help me?
Registry
Key path: HKLM\SOFTWARE\Classes\Installer\Products\1EFA14817AB44D447800A6FC68A0E81D1
Value name: ProductIcon
Detection method: Value does not exist.
File
Path: %ProgramFiles (x86)%\Trend Micro\Endpoint Basecamp
File or folder: EndpointBasecamp.exe
Detection method: File or folder does not exist.
If you’re using PowerShell, just reverse a normal detection script so instead of returning true if it’s found, return false
Please check below.. Its only running registry
# File path to check
$fileToCheck = “${env:ProgramFiles(x86)}\Trend Micro\Endpoint Basecamp\EndpointBasecamp.exe”
# Registry entries and value names to check
$registryEntries = @(
@{ KeyPath = “HKLM:\SOFTWARE\Classes\Installer\Products\{1EFA14817AB44D447800A6FC68A0E81D1}”; ValueName = “ProductIcon” }
)
# Function to check registry entry existence
function Check-RegistryEntry {
param (
[string]$KeyPath,
[string]$ValueName
)
try {
$value = Get-ItemProperty -Path $KeyPath -Name $ValueName -ErrorAction Stop
Write-Output “RegEdit Exist: Registry entry ‘$ValueName’ exists in ‘$KeyPath’.”
Exit 0
} catch {
Write-Output “RegEdit doesn’t exist: Registry entry ‘$ValueName’ does not exist in ‘$KeyPath’.”
Exit 1
}
}
# Function to check file existence
function Check-File {
param (
[string]$FilePath
)
if (Test-Path -Path $FilePath) {
Write-Output “File Exist: File ‘$FilePath’ exists.”
Exit 0
} else {
Write-Output “File doesn’t exist: File ‘$FilePath’ does not exist.”
Exit 1
}
}
# Check registry entries
foreach ($entry in $registryEntries) {
Check-RegistryEntry -KeyPath $entry.KeyPath -ValueName $entry.ValueName
}
# Check file
Check-File -FilePath $fileToCheck
What if the file we use to detect the removal of an app is in current user’s folder?
Example:
$TestFile = “C:\Users\$env:USERNAME\AppData\Local\Google\Chrome\Application\chrome.exe”
if (Test-Path -Path $TestFile) {
exit 1
}
else {
exit 0
}
What are our options in this case? Choose to run it under user context maybe? But then it won’t have system’s privileges…
If you use this function I created:
https://github.com/andrew-s-taylor/public/blob/main/Powershell%20Scripts/Intune/function-getloggedindetails.ps1
That can be run in the system context and will give you the current logged in users username
Hi Andrew, thank for the super useful article.
I have one question – do you have an idea how often will Intune go and check if (for example) a file has appeared so it executes or not the (un)install?
It’s Intune time, could be anything from 20 minutes to a few hours. If you sync the device or restart the IME service, that normally nudges it along
Great article, used it to base my attempt at a script if anyone is interested.
Will check:
App not installed – Install
App installed but older – Install
App installed and the same as the installer – do nothing
app installed and newer than installer – do nothing
# Enter App and min version to check
$software = 'Software Name'
$minVer = "1.23.456"
$currentVer = "" # Used to check it installed
# Check installed version
$product = gwmi win32_product -filter "Name LIKE '%$software%'"
$currentVer = $product.Version
If ($currentVer.Length -gt 1)
{
If([System.Version]$minVer -lt [System.Version]$currentVer)
{
Write-Output "Newer version installed - do nothing"
exit 0
}
ElseIF ([System.Version]$minVer -eq [System.Version]$currentVer)
{
Write-Output "Min and Current version the same - do nothing"
exit 0
}
Else
{
Write-Output "Upgrade to Newer version - Install"
exit 1
}
}
Else
{
Write-Output "App not found - Install"
exit 1
}
Thanks for your article. It help me for Office installation.
All my detection scripts seem to fail with the below in the logs:
[Win32App][WinGetApp][WinGetAppDetectionExecutor] Exception occurred when performing detection for app with id: feb3636f-dffb-4b1d-b121-374f40f506f9. The exception is Win32AppPlugin Agent Executor Controller Error.
Exception: Microsoft.Management.Clients.IntuneManagementExtension.Win32AppPlugIn.AgentExecutorControllerException: Failed to query user token for session: 2
at Microsoft.Management.Clients.IntuneManagementExtension.Win32AppPlugIn.AgentExecutorController`1.StartAgentExecutor(Int32 sessionId, Int32 timeoutInSeconds, Boolean elevateIfPossible)
at Microsoft.Management.Clients.IntuneManagementExtension.Win32AppPlugIn.WinGetAppDetectionExecutor.EvaluateAppDetection(DetectionExecutorParameters detectionExecutorParameters).
Any suggestions? I cnat find much about theese errors at all
Can you share the script? It looks like it’s failing to do something at the user level
Hi Andrew,
I have been trying to write a script to detect a folder or even a .exe file on the users Desktop. I was wondering if there was a custom detection script to detect the folder or file on any users Desktop once installed?
Tried using %username% and %userprofile% but it does not detect the folder/file any way I do it?
Hi,
Absolutely, if it’s a file, you just want to loop through the users and send the exit code if you find it. Obviously this is a bit more risky as that doesn’t necessarily mean it’s on all desktops.
Something like this:
# Define the file name to search for
$fileName = "file.exe"
# Get all user profiles on the machine
$userProfiles = Get-ChildItem -Path "C:\Users" -Directory
# Loop through each user profile and search for the file on their desktop
foreach ($userProfile in $userProfiles) {
$desktopPath = Join-Path -Path $userProfile.FullName -ChildPath "Desktop"
$filePath = Join-Path -Path $desktopPath -ChildPath $fileName
if (Test-Path $filePath) {
Write-Output "File found on $($userProfile.Name)'s desktop: $filePath"
exit 0
}
}
If you want to check everyone has it, count the number of profiles and then use a counter to compare:
# Define the file name to search for
$fileName = "file.exe"
# Get all user profiles on the machine
$userProfiles = Get-ChildItem -Path "C:\Users" -Directory
$totalprofiles = $userProfiles.Count
##Set a blank count
$found = 0
# Loop through each user profile and search for the file on their desktop
foreach ($userProfile in $userProfiles) {
$desktopPath = Join-Path -Path $userProfile.FullName -ChildPath "Desktop"
$filePath = Join-Path -Path $desktopPath -ChildPath $fileName
if (Test-Path $filePath) {
Write-Output "File found on $($userProfile.Name)'s desktop: $filePath"
$found++
}
}
if ($found -eq $totalprofiles) {
Write-Output "File found on all user profiles"
exit 0
} else {
Write-Output "File not found on all user profiles"
exit 0
}
I hope this helps
Hi Andrew,
First off, really well writte article.
Im having a problem with a detection script and was wondering if you could check it out.
#Set Path to check SAP install
$SAPinstallPath = “C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe”
# Set the registry key path and value name
$keyPath = “HKCU:\SOFTWARE\SAP\General”
$valueName = “BrowserControl”
$Value = 0x00000001
if (Test-Path $SAPinstallPath) {
# Check if the registry key exists
if (Test-Path $keyPath) {
# Get the value of the DWORD
$dwordValue = (Get-ItemProperty $keyPath -Name $valueName).$valueName
# Convert the $Value variable to a hexadecimal string
$hexValue = $Value.ToString(“X8”)
# Check if the DWORD value is set to 1
if ($dwordValue -eq $hexValue) {
Write-Output “SAP was intalled successfully”
exit 0
} else {
exit 2
}
}
else {
exit 3
}
}
else {
exit 1
}
I tried everything I know but for the life of me I cant get intune to detect the installation. When I run the script locally it works as intended.
Hi,
I can see a few possible issues there:
1) Your users may not be able to query the Program Files directory
2) Exit codes should be 0 or 1
3) Detection scripts run in the system context so can’t query HKCU
Try this:
function getloggedindetails() {
<# .SYNOPSIS This function is used to find the logged in user SID and username when running as System .DESCRIPTION This function is used to find the logged in user SID and username when running as System .EXAMPLE getloggedindetails Returns the SID and Username in an array .NOTES NAME: getloggedindetails Written by: Andrew Taylor (https://andrewstaylor.com) #>
##Find logged in username
$user = Get-WmiObject Win32_Process -Filter "Name='explorer.exe'" |
ForEach-Object { $_.GetOwner() } |
Select-Object -Unique -Expand User
##Find logged in user's SID
##Loop through registry profilelist until ProfileImagePath matches and return the path
$path= "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*"
$sid = (Get-ItemProperty -Path $path | Where-Object { $_.ProfileImagePath -like "*$user" }).PSChildName
$return = $sid, $user
return $return
}
$loggedinuser = getloggedindetails
$sid = $loggedinuser[0]
$user = $loggedinuser[1]
#Set Path to check SAP install
$SAPinstallPath = "C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe"
# Set the registry key path and value name
$keyPath = "Registry::HKU\$sid\SOFTWARE\SAP\General"
$valueName = "BrowserControl"
$Value = 0x00000001
##Set a counter
$check = 0
if (Test-Path $SAPinstallPath) {
##Executable found
$check++
}
# Check if the registry key exists
if (Test-Path $keyPath) {
# Get the value of the DWORD
$dwordValue = (Get-ItemProperty $keyPath -Name $valueName).$valueName
# Convert the $Value variable to a hexadecimal string
$hexValue = $Value.ToString("X8")
# Check if the DWORD value is set to 1
if ($dwordValue -eq $hexValue) {
##Reg correct
$check++
}
}
if ($check -eq 2) {
write-host "Install successful"
exit 0
}
else {
write-host "Install failed"
exit 1
}
Hi Andrew,
thanks for your response it worked.
I just edited the script to account for the fact that multiple users may be signed in to the device.
Updated Script:
function Get-LoggedInDetails {
# Find logged-in user details
$loggedInUsers = Get-WmiObject Win32_Process -Filter “Name=’explorer.exe'” |
ForEach-Object {
$_.GetOwner() | Select-Object User, Domain
} | Select-Object -Unique
# Find logged-in user’s SID for each user
$loggedInUsers | ForEach-Object {
$user = $_.User
$domain = $_.Domain
$path = “HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*”
$sid = (Get-ItemProperty -Path $path | Where-Object { $_.ProfileImagePath -like “*\$user” }).PSChildName
[PSCustomObject]@{
SID = $sid
User = “$domain\$user”
}
}
}
# Get data from the function
$loggedInUsers = Get-LoggedInDetails
# Set Path to check SAP install
$SAPinstallPath = “C:\Program Files (x86)\SAP\FrontEnd\SAPgui\saplogon.exe”
# Set the registry key value name
$valueName = “BrowserControl”
$Value = 0x00000001
# Iterate through each logged-in user
foreach ($userDetails in $loggedInUsers) {
$sid = $userDetails.SID
$user = $userDetails.User
# Set a counter
$check = 0
if (Test-Path $SAPinstallPath) {
# Executable found
$check++
}
# Check if the registry key exists
$keyPath = “Registry::HKU\$sid\SOFTWARE\SAP\General”
if (Test-Path $keyPath) {
# Get the value of the DWORD
$dwordValue = (Get-ItemProperty $keyPath -Name $valueName).$valueName
# Convert the $Value variable to a hexadecimal string
$hexValue = $Value.ToString(“X8”)
# Check if the DWORD value is set to 1
if ($dwordValue -eq $hexValue) {
# Registry correct
$check++
}
}
if ($check -eq 2) {
Write-Host “Install successful”
Exit 0
}
}
Write-Host “Install failed”
Exit 1
Really cant express how thankful I am, I was stuck on this for too long :).
hi Oliver, Andrew (May need your help and input)
I might need your assistance and input on this.
The current script isn’t effectively checking the SAP version on user computers. If a user has version 7.70 installed, how will it upgrade to version 8.0? My goal is to upgrade from the older version.
If the user already has version 8.0, the installation should be skipped. Do you have any suggestions for improving the detection script?
Thanks
Tank
Hi,
For something like that, you need to change detection to look for version 8.0, then anyone who doesn’t have it, will have the latest version installed
Great article, distilling the matter into immediately usable information. “Demystifying” indeed, well done!
Glad it was helpful 🙂
Very nice post, extremely helpful. I am trying to use the detection script during the requirements phase of my Intune Win32 app deployment. Identify if a service exists, and if not exit code 1 and proceed with install. Then use the same script with exit code 0 to verify that the service now exists. However, my application does not appear to be installing with these conditions. Any thoughts?
$Service = Get-Service -Name “FakeService”
If ($Service) {
Write-Output “FakeService detected, exiting.”
Exit 0
}
Else {
Write-Output “FakeService not detected, installing.”
Exit 1
}
Hi Glenn,
Requirements scripts work slightly differently so in this case you would want something like
$service = get-service -name “FakeService”
$status = ($service.status).tostring()
Then in the requirements, you want to look for a string which NOT equals Running (or stopped, disabled, whatever status the service should be in)
That will only install on machines without the service.
Then afterwards you want a detection script which matches what you have to confirm the app is installed
Hopefully this makes sense
Great article – thank you! Question for you –
We make Visual Studio Code available in the software center as a user install. Visual Studio Code installs into the user’s profile. I’ve found that the detection rules run as the system and cannot be used to detect a user-based install. My expectation from Intune is that the company portal will display whether an app is installed for the user or not, but I can’t seem to get it to work. Any clues for a user-app detection method?
Hi,
You’re going to need to get creative with PowerShell.
One option would be to enumerate the logged on user and populate that into the path.
If they are single user devices, a simpler option would just be to search c:\users and the visual studio code executable. This one means if the path changes, it doesn’t matter, but obviously only works if there is only one user.
Or combine the two and search the logged on users profile.
If you need any help with the script, let me know
Hey Can i Check multiple files in one script and if they are all missing i get the output?
You can check for multiple files, but the output will always only be either Detected or Not Detected. If you add some logging into your script, you could use that to show you what was missing though
What would the JSON be for the following script you posted for a Custom Compliance Script?
$File = “C:\windows\system32\notepad.exe”
$service = get-service -name “MozillaMaintenance”
if (($service) -and (Test-Path $File)) {
write-output “MozillaMaintenance and Notepad detected, exiting”
exit 0
}
else {
exit 1
}
I’d split it into two so you can give the users a better reason for it, otherwise they’ll have to guess which it is:
Powershell:
$File = “C:\windows\system32\notepad.exe”
$service = get-service -name “MozillaMaintenance”
if ($service) {
$mozillamaintenance = “True”
}
else {
$mozillamaintenance = “False”
}
if ($File) {
$fileexists = “True”
}
else {
$fileexists = “False”
}
$hash = @{
Mozilla = $mozillamaintenance
Notepad = $fileexists
}
return $hash | ConvertTo-Json -Compress
JSON:
{
“Rules”:[
{
“SettingName”:”Notepad”,
“Operator”:”IsEquals”,
“DataType”:”String”,
“Operand”:”True”,
“MoreInfoUrl”:”https://google.com”,
“RemediationStrings”:[
{
“Language”: “en_US”,
“Title”: “Notepad Missing”,
“Description”: “Notepad is Missing”
}
]
},
{
“SettingName”:”Mozilla”,
“Operator”:”IsEquals”,
“DataType”:”String”,
“Operand”:”True”,
“MoreInfoUrl”:”https://google.com”,
“RemediationStrings”:[
{
“Language”: “en_US”,
“Title”: “Mozilla”,
“Description”: “Mozilla Maintenance Service is Missing”
}
]
}
]
}
Is there a way to reverse the detection to mark an installation as successful if the file path tested returns not existent?
Yes, absolutely, if it’s a filepath instead of if (test-path $file) you would use if (!test-path $file)
Same for any others like that, the ! is a NOT command
What context do the scripts run in ? I have a couple of installers that will run in user space. Does the custom detection script follow the install context (System / User)
They will run in the same context at the app install itself
Thank you Andrew for this invaluable information.
How about in a scenario where we are trying to update a Dell WD19 docking station firmware through Endpoint manager. In this scenario, the dock needs to be directly connected to the device and detected before it installs the firmware package.
How can I create a simple custom detection rule in powershell, that would show either “yes” the docking station is attached proceed with the installation or “no” its not attached-and install when detected.
Hi,
If you can get the hardware ID for the dock, something like this should work:
$dock = get-pnpdevice | where-object InstanceId -eq “USB\VID_14B0&PID_0184\5&21F3FF01&0&5”
if ($status -eq “OK”) {
##Dock attached
}
else {
##Not attached
}
Replace the hardware ID with whatever you find for the dock, that’s just a random one I grabbed from device manager
Thank you Andrew,
Very helpfull post, explained in a very clear way.
Glad you found it useful!
For the Version Check, would it be more beneficial to check the registered entry in the registry?
Im thinking something like this:
$APPINSTALL = Get-ItemProperty “HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*” | where {$_.DisplayName -like “*APPNAME*”}
IF(Test-Path “$APPINSTALL .PSPath”)
{
IF($APPINSTALL .DisplayVersion -ge “3.0.279”)
{
write-host “Install Success”
exit 0
}
ELSE
{
Write-Host “Installed Version Not Match, Upgrade Failed”
exit 1
}
}
ELSEIF(!(Test-Path “$APPINSTALL .PSPath”))
{
Write-Host “Install failed!”
exit 1
}
Absolutely, that’s another great example. I queried the file to demonstrate how to do so at the file level (and I’ve seen some terrible installers in my time!)
We are trying to have a appx dependency and msix installing via powershell in a win32 app. How would I detect these are installed and correct version? Dont really see and folders. They are modern apps.
They should be in c:\Program Files\WindowsApps (you’ll need to be elevated to see it)
You could also use get-appxpackage and get-apppackage if needed as well
Just a note. This code:
$File = “C:\windows\system32\notepad.exe”
if ($file) {
write-output “Notepad detected, exiting”
exit 0
}
else {
exit 1
}
Does not check for the existance of a file. The $File string will always be true.
You need:
if (Test-Path $File) {…
Well spotted, thank you. Have updated it now