VersionNT MSI property on Windows 10
Asked Answered
I

5

9

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?

Ics answered 11/8, 2015 at 3:18 Comment(1)
G
20

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...)

Girvin answered 13/8, 2015 at 14:25 Comment(8)
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...Ics
@Ics 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.Cupidity
Agreed. I actually just did several in place Win 8.1 to 10 upgrades and they went surprisingly well.Girvin
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.Girvin
I am still happy with the opinion piece at the bottom of the answer.Girvin
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.Compton
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.Girvin
This is the most stable, cleanest hack I've found for this problem. Thanks!Unknow
E
5

Microsoft official answer:

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

Source

Emir answered 12/3, 2017 at 2:31 Comment(1)
Microsoft said that, but practically it's not true on Windows 10.Aqaba
C
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.)

Cupidity answered 11/8, 2015 at 12:16 Comment(6)
I appreciate the suggestions. Unfortunately, #1 doesn't work for a silent install, and #2 & #3 don't work for running the MSI directly...Ics
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.)Cupidity
My two cents provided below.Girvin
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.Girvin
The WindowsBuild and MsiWin32AssemblySupport properties are lies also!Girvin
@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?Fabaceous
P
2

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

Pyrex answered 22/11, 2016 at 15:31 Comment(0)
C
0

For installers that do not have a bootstrapper, I've found that creating an immediate custom action that calls GetVersionEx() and sets a property for the rest of the installer to use is also a good alternative. I've sequenced my custom action to occur after AppSearch, and it was enough to condition components with it.

Crescendo answered 17/8, 2015 at 14:49 Comment(6)
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/…Ics
@Ics - 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.Crescendo
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.Irs
@MikeKaganski, custom actions are run by rundll32.exe. Does it have the manifest?Crescendo
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.Irs
I ran into the same problem, although C++ custom action that uses RtlGetVersion API reports 6.3, C# custom action which uses Environment.OSVersion.Version reports the correct Windows 10 version.Yogi

© 2022 - 2024 — McMap. All rights reserved.