VersionNT MSI property on Windows 10

14,198

Solution 1

Here's my two cents....

I don't find the VersionNT property terribly useful. VersionNT64 is: VersionNT64 .... Not VersionNT64 to determine bitness.

This is a bit of a hack (they do this, we do that...) but desperate times call for desperate measures....

In all of the compatibility games MSFT is playing they only seem to be masking the Major and Minor but Build and revision. I've also worked out that on Win8 they mask it as 6.2 and on Win 10 they mask it as 6.3. So therefore I feel comfortable doing this:

<Property Id="WIN10FOUND">
  <DirectorySearch Id="searchSystem" Path="[SystemFolder]" Depth="0">
    <FileSearch Id="searchFile" Name="advapi32.dll" MinVersion="6.3.10000.0"/>
  </DirectorySearch>
</Property>

What I tend to do ask myself is "WHY" do I need Windows (FOO)? I then look for some registry entry or DLL that indicates that particular feature, component, API is present and use that for my test.

Microsoft has adopted an evergreen approach of "you don't need to know what version it is, you'll always have the latest and it'll always be called Windows 10" and to me this reinforces the approach I prefer to take. I know that a day will come that they are wrong and I do need to know otherwise I'll install and my application will fail and my users will complain and not know what version they have. (Sigh...)

Solution 2

Microsoft official answer:

When you install an .msi installation package on Windows 10 or Windows Server 2016, the VersionNT value is 603.

Source

Solution 3

Since msiexec.exe does not have Windows 10 compatibility in its manifest, and VersionNT is a private property, there is no clean way I'm aware of to make the execute sequence see VersionNT=1000. I would recommend one of these approaches:

  • copy VersionNT to another property during the UI sequence (some public property like REALVERSIONNT; be sure to list it in SecureCustomProperties like any other property you want to pass to the execute sequence),
  • pass in the real value from your bootstrapper (ditto), or
  • possibly set a registry key in your bootstrapper if you need the same information during maintenance or uninstallation, then pull its value into the installation with a system search.

(I'm torn about the registry key option, as it can go stale if the OS is upgraded in the future. Note as well that all of these options are likely to be only as correct as the manifest on your bootstrap in a theoretical future version of Windows.)

Solution 4

I found that a very easy and robust way of detecting Windows 10 is by calling the built-in WMIC command and parsing the output from it:

wmic os get Name,Version,BuildNumber /VALUE

it'll return exactly the info you need to determine which OS you're on:

BuildNumber=14393

Version=10.0.14393

http://helpnet.flexerasoftware.com/installshield22helplib/helplibrary/whats_newIS2015.htm

On systems with Windows 10, the Windows Installer properties VersionNT and VersionNT64 indicate 603, which was originally introduced as the version number of Windows 8.1. Therefore, it is not possible to create conditions in an .msi package that specifically target Windows 10.

Since Windows Installer 5.0 and Windows 7, DLL custom actions in .msi packages are shimmed to block obtaining the operating system version; the APIs GetVersion, GetVersionEx, and RtlGetVersion return a Windows version of 6.0.6000, which was originally the version number of Windows Vista. Therefore, it is also not possible to obtain the actual version number of Windows from a DLL custom action or from an InstallScript custom action (which is implemented as a DLL).

Because of the aforementioned behavior in Windows Installer, it is not easily possible to detect what version of Windows on which an .msi package is running

Share:
14,198
jbudreau
Author by

jbudreau

I'm a software engineer that currently works developing Windows installers.

Updated on June 07, 2022

Comments

  • jbudreau
    jbudreau almost 2 years

    I'm finding that when I update the manifest for my bootstrapper to support Windows 10 compatability, the InstallUISequence of the MSI will correctly set VersionNT=1000, but the InstallExecuteSequence will set VersionNT=603.

    How do I make the InstallExecuteSequence also set VersionNT=1000?

  • jbudreau
    jbudreau over 8 years
    I appreciate the suggestions. Unfortunately, #1 doesn't work for a silent install, and #2 & #3 don't work for running the MSI directly...
  • Michael Urman
    Michael Urman over 8 years
    Since you need to support all those usage patterns, um, best of luck to you! I think the answer is currently that it's impossible. There may be other artifacts to look for, but Microsoft has clearly decided that they don't want people detecting Windows 10 in Windows Installer packages. (I just wish they'd update the docs on VersionNT accordingly.)
  • Christopher Painter
    Christopher Painter over 8 years
    My two cents provided below.
  • jbudreau
    jbudreau over 8 years
    I think this makes sense (or at least is the best we've got to go with). Our installer currently keys off the VersionNT property to populate a database table in a client machine so that the server machine can read the data and display to the user what each of their clients are (in a list). We'll have to find something meaningful to key off of going forward...
  • Michael Urman
    Michael Urman over 8 years
    @jbudreau It seems like only doing this in the installation would leave you with inaccurate data when those who installed your program on Windows 7 or higher upgrade Windows without a fresh install. If you move that to the app, you solve both problems simultaneously.
  • Christopher Painter
    Christopher Painter over 8 years
    Agreed. I actually just did several in place Win 8.1 to 10 upgrades and they went surprisingly well.
  • jbudreau
    jbudreau over 8 years
    I'm not sure I want to go this route. From the MSDN page, the very first sentence is "[GetVersionEx may be altered or unavailable for releases after Windows 8.1. Instead, use the Version Helper APIs]" - msdn.microsoft.com/en-us/library/windows/desktop/…
  • shpuktzy
    shpuktzy over 8 years
    @jbudreau - you're right. If your custom action is written in C++, then by all means use the Version Helper APIs. However, they're not available by P/Invoke from .NET custom actions. Anyway, whatever the custom action's implementation may be, the point is that custom actions are not run in compatibility mode and thus can help in determining the OS's version.
  • Christopher Painter
    Christopher Painter over 8 years
    I am not happy with this answer and it should not be trusted. Kernel32 doesn't exist in SYSWOW64 for a 32bit install and other dll's such as advapi32.dll are having their version numbers masked interfering with AppSearch. There is more to this that I don't seem to know yet.
  • Christopher Painter
    Christopher Painter over 8 years
    They should update AppSearch also. I did a search for a advapi32.dll with minversion 10.0.0.0 and it's not detected. Drop the minvision to 6.0.0.0 and it's detected. Explorer says it's version is 10.0.10240.16384.
  • Christopher Painter
    Christopher Painter over 8 years
    I am still happy with the opinion piece at the bottom of the answer.
  • Christopher Painter
    Christopher Painter over 8 years
    The WindowsBuild and MsiWin32AssemblySupport properties are lies also!
  • PhilDW
    PhilDW over 8 years
    One of the reasons Microsoft does this is so that users can test their products on newer versions of Windows without having to rebuild them all because of restrictive OS tests. They also prefer that you test for the required functionality rather than depend on the OS version, especially on server systems that might pass the VersionNT test but don't have the OS feature or component installed.
  • Christopher Painter
    Christopher Painter over 8 years
    Which is the approach I personally like to take. Still it would be nice to be able to write a X=Y or X>=Y condition and have it work as you'd expect.
  • lcsondes
    lcsondes over 6 years
    This is the most stable, cleanest hack I've found for this problem. Thanks!
  • Stein Åsmul
    Stein Åsmul about 6 years
    @Michael Urman - Chris and Michael: this issue has me quite concerned about my advice here (I never saw your answers here before I wrote the linked answer a while back). How is WindowsBuild a lie Chris? When I ran it, it seemed to report the latest build version? I ask because I am almost sure you are right, and I am missing something. Microsoft might suddenly shut the door, even if it is currently working. One build it is working, and the next it is not?
  • Mike Kaganski
    Mike Kaganski over 5 years
    How could this custom action succeed? The custom action runs in the context of the calling process, which is msiexec.exe, which doesn't have a manifest for Win10, and thus the GetVersion(Ex) API returns the same 6.3 result.
  • shpuktzy
    shpuktzy over 5 years
    @MikeKaganski, custom actions are run by rundll32.exe. Does it have the manifest?
  • Mike Kaganski
    Mike Kaganski over 5 years
    No, custom actions are run by msiexec.exe, and they therefore have access to the installer context, including installer properties (available for this type of action - e.g., deferred) etc.
  • Riz
    Riz over 3 years
    Microsoft said that, but practically it's not true on Windows 10.