Tag Archives: Windows

Understanding the ‘Correct’ File Version used for Intune Win32 App Detection Method

Depending on the developer for an application, various & differing version numbers can be added into the metadata of an application/executable/binary which can sometimes be confusing when creating manual detecton rules as part of an Intune Win32 App.

A good example of this is ‘CMTrace.exe’ from Microsoft. The screenshot below shows the ‘Details’ tab of ‘CMTrace.exe’ file properties with ‘File version’ highlighted:

You can see from the screenshot that the ‘File Version’ displayed is ‘5.0.9068.1000′ which is what I initially used for my Detection Rule as part of a CMTrace Win32 App in Intune:

Unfortunately this resulted in a continuous loop of ‘CMTrace.exe’ being reinstalled as it wasn’t being detected correctly by Intune – this was visible in the log file below:

C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\IntuneManagementExtension.log. 

Turns out that Intune actually uses a different property of the file metadata to determine the version number of a file. This is documented in the Microsoft article below:

https://learn.microsoft.com/en-us/mem/intune/apps/apps-win32-troubleshoot#detecting-the-win32-app-file-version-by-using-powershell

Two quick & easy ways to retrieve the correct ‘Version’ value to use in a Detection Rule are shown in the PowerShell commands below. Both commands are querying the same file in the same location on a reference computer i.e., ‘CMTrace.exe’ in the ‘C:\Windows’ directory:

[System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Windows\cmtrace.exe").FileVersion

(Get-Item -Path "C:\Windows\CMTrace.exe").VersionInfo.FileVersion

The value returned from these queries was ‘5.00.9068.1000′.

The additional zero in the version number was the difference that broke the configured Detection Rule.

Using the correct value returned by either of these two PowerShell commands (they are both returning the same information from .NET) will match the value retrieved by Intune when checking if the Win32 App is installed or not.

This will result in the Win32 App being installing once and then correctly being detected as installed thereafter i.e., the Detection Rule will now successfully work as expected.

/ JC

Registry Changes with PowerShell

It’s a common requirement to configure Registry values on an endpoint when building or configuring them.

I like to use PowerShell to do this as it’s easy to document and keep track of changes.

One issue with the standard PowerShell method (Set-ItemProperty) to do this is that you usually need a key to exist before you can add values into it. This usually means having to figure out if a key exists and if not, running several ‘New-Item’ commands to create the key (and potentially the tree/path to the key) itself first.

Fine for a few settings but not ideal when you have 10’s or even 100’s of registry settings to deploy.

Using a .REG file avoids this as it imports the key structure and the key values too. But this adds obfuscation into mix as you need to open each .REG file to see what it contains and that can be unintuitive sometimes.

The solution to this is to call registry changes directly using the “[Microsoft.Win32.Registry]::SetValue” .NET method as this behaves in the same way as importing .REG files in that it will create the key and path to the key regardless of whether the key/path already exists. Quick and easy (also highly performant!).

The format of these commands wasn’t initially obvious from Microsoft documentation but after a lot of trial and error, frustration and profuse swearing, I can provide the following examples for the most common types of Registry changes:

<#
.DESCRIPTION
    Script to configure Registry Items
.EXAMPLE
    Powershell.exe -ExecutionPolicy Bypass -File <ScriptName>.ps1
.NOTES
    VERSION     AUTHOR              CHANGE
    1.0         Jonathan Conway     Initial Script creation
    [Microsoft.Win32.Registry]::SetValue("keyName", "valueName", "value", [Microsoft.Win32.RegistryValueKind]::DWord)
    [Microsoft.Win32.Registry]::SetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Example", "ExampleValueName", "ExampleValue", [Microsoft.Win32.RegistryValueKind]::String)
    [Microsoft.Win32.Registry]::LocalMachine.DeleteSubKey("SOFTWARE\Example")
   
    Valid Root names are: "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE", "HKEY_CLASSES_ROOT", "HKEY_USERS", "HKEY_PERFORMANCE_DATA", "HKEY_CURRENT_CONFIG", and "HKEY_DYN_DATA".
    Valid "RegistryValueKind" values: "String", "ExpandString", "Binary", "DWord", "MultiString" and "QWord".
#>
# Binary Value
$ExampleBinaryValue = [byte[]](150, 18, 6, 230, 16, 0, 0, 0)
[Microsoft.Win32.Registry]::SetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Test", "BinaryExampleName", [byte[]]$ExampleBinaryValue, [Microsoft.Win32.RegistryValueKind]::Binary)
# Dword Value
[Microsoft.Win32.Registry]::SetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Test", "DwordExampleName", [int]"1", [Microsoft.Win32.RegistryValueKind]::DWord)
# String Value
[Microsoft.Win32.Registry]::SetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Test", "StringExampleName", [string]"ExampleValue", [Microsoft.Win32.RegistryValueKind]::String)
# MultiString Value
$MultiStringExampleValue = @(
    "ExampleValue1",
    "ExampleValue2",
    "ExampleValue3",
    "ExampleValue4"
)
[Microsoft.Win32.Registry]::SetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Test", "ExampleName", [string[]]$MultiStringExampleValue, [Microsoft.Win32.RegistryValueKind]::MultiString)

Posting this so I never have to go through the ordeal of getting these commands formatted correctly… And of course to benefit the community too! 😉

/ JC

Extract Content From MSI Files

To extract the contents of a Microsoft Software Installer (MSI) file you need to run the following command against the MSI that you are working with:

msiexec /a <FullPathToMSISourceFile> /qb TARGETDIR=<FullPathToExtractedContentFolder>

So a working example of this would be as follows:

msiexec /a "C:\Temp\Nutanix-VirtIO-1.2.3-x64.msi" /qb TARGETDIR="C:\Temp\Extract"

/ JC

Log Into Windows Locally Without Entering The Computername Prefix Every Time

If (like me) you need to log in locally to Windows machines quite a lot, it can be an annoyance to have to type in the Computername prefix every time you need to do so e.g “CLIENT1\Administrator”.

Luckily Microsoft have given us a shortcut way of doing this so we can save time. Just substitute the Computername for a “.\”

So “CLIENT1\Administrator” would become “.\Administrator”

Simples.

/ JC

How Many Activations Do I Have Left On My Licence Keys?

To find out this information you’d normally have to go through the pain in the arse that is “telephoning Microsoft”.

Far easier though is to import the keys into the Volume Activation Management Tool (VAMT) and use it to check online with Microsoft over the Interweb.

VAMT is part of the Windows Assessment and Deployment Kit (Windows ADK) and can be downloaded for nothing from:

http://www.microsoft.com/en-gb/download/details.aspx?id=39982

Simply import the relevant keys and use the “Refresh product key data online” to retrieve the number of activations left.

/ JC