Skip to content
⌘ NSIS Forum Archive

Detect windows 10

29 posts

mrjohn#

Detect windows 10

I' use code from there


but windows 10 it is detected as 8.1,tested on Oracle VM VirtualBox with iso downloaded from MS site,v10 build 10240

has anyone any fix?
thanks
Anders#
The next NSIS Beta will be released in a couple of days with better Win10 support.

In the meantime, if you are using NSIS 3 you can add "ManifestSupportedOS Win7 Win8 Win8.1 {8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" to your script and use ${WinVerGetMajor} in WinVer.nsh, it will report 10 on Windows 10.

If you want to stick with NSIS 2.4x then you need to use something like http://nsis.sourceforge.net/Using_!packhdr
LoRd_MuldeR#
mrjohn,

starting with Windows 8.1, Microsoft has intentionally broken the version getter API of the system! Now this API will not report the Windows version we are actually running on, but the Windows versions that "the application probably wants to hear" (thinks Microsoft). In particular, the version API now reports the Windows version that your application is compatible with - as indicated by application Manifest. You can add compatibility Manifest for all existing Windows versions - by the time you compiled your application - but you obviously you cannot add compatibility Manifest for "future" Windows versions. So you will never be able to correctly detect any "future" Windows versions...

It's important to understand that the solution implemented in NSIS 3 is only a temporary solution. It adds compatibility Manifest for Windows 8.1 and 10, which fixes things for Windows 8.1/10 for now. But things will be broken again, for any future Windows version (provided there'll be one)! So, for every Windows version that will be released from now on, you will (a) have to wait for the NSIS developers to implement the required workaround, (b) re-compile your installer with the "fixed" NSIS and (c) roll out the updated installer to your customers! Okay, step (a) will not necessarily be required, as you can also manually enter a custom compat GUID, but there'll be no way around (b) and (c). So it's an infinite circle of Microsoft breaking things, developers implementing the required workarounds and Microsoft breaking things once again.

My attempt to implement a version getter function, that actually does what you'd expect (on Windows 8.1+) from such function, is here:



(Please don't understand this post as a critique to the NSIS guys. It's all Microsoft's fault, which created this mess, clearly!)
Anders#
I thought we had this discussion already?

Since Windows 11 does not exist yet there is no problem functionality wise if you just treat it as Windows 10. After all, if you could code for Windows 11 today, would you treat it differently compared to 10? IMHO, detecting Windows 10 is also rather pointless, just pretend it's 8.1.

The only issue is with providing version information in logs and/or your UI, they will be wrong since Windows lies to you.
LoRd_MuldeR#
Originally Posted by Anders View Post
I thought we had this discussion already?
Yes. Still, as we see in this thread, programmers are persistently running into big trouble, because Microsoft has broken the version API in Windows 8.1. So I think it's important to explain what is actually going on here! People might get the false idea that just adding the proper GUID will "fix" the function and restore the old (correct) behavior, while in fact it does not. The behavior of the version API has changed fundamentally, from a function that would faithfully return the Windows version that we are running on, to something the pretty much just echos the info written into the calling binary's manifest. The fact that you can get Windows 10 to report correctly as Windows 10 by adding the required GUI is not a proper solution to the underlying problem, but merely a symptom of the new (pointless) behavior.

Also, it cannot be emphasized enough, that the whole GUID method is totally inapplicable to library code. That's because, as a library developer, you don't know what application is going to call your library. And you have zero control over what GUID's might happen to be included that application's Manifest (or not), if any. So, even if your requirement was to distinguish only those Windows versions that existed by the time you compiled your library code, you have a serious problem now! What is Microsoft's answer for this?


Originally Posted by Anders View Post
Since Windows 11 does not exist yet there is no problem functionality wise if you just treat it as Windows 10. After all, if you could code for Windows 11 today, would you treat it differently compared to 10? IMHO, detecting Windows 10 is also rather pointless, just pretend it's 8.1.
I think we leave it up to the application developer to decide what he or she does with the version info, once received correctly 😉

Consequently, the purpose of a system function is to return the correct/desired result to the application, according to the functions specification. And here I mean the "original" specification of the version API. The one that actually made sense. The purpose of a system function certainly is not to make wild guesses on what the application might be doing with the return value. Or, even worse, manipulate the result in order to force the application's behavior into the direction that is desired by the system developer.


Originally Posted by Anders View Post
The only issue is with providing version information in logs and/or your UI, they will be wrong since Windows lies to you.
That's one striking example, yes!
JasonFriday13#
Originally Posted by Anders View Post
The next NSIS Beta will be released in a couple of days with better Win10 support.
Awesome. I just upgraded my laptop from 8.1 to 10, having a new beta that supports 10 is great. Or I could just grab the trunk version right now, their basically the same 😉.
Mircea M#
Using !packhdr

Hi,

I tried the latest 3.0b2 version and it works great getting the correct version in Windows 10. Unfortunately it would be a complicated process to "validate" NSIS 3 (especially since it is still in beta) in my company and therefore I need to stick to 2.46 and use !packhdr (or something else).
The trouble is I don't know how exactly to get the version of the OS. Is there a new version of WinVer.nsh that I can use in 2.46? I tried the one from 3.0 and it gives some errors. Is there something else that I need to do?
What I need to achieve is have something like being able to use ${IsWin10}.

Thanks,
Mircea
LoRd_MuldeR#
Originally Posted by Mircea M View Post
Hi,

I tried the latest 3.0b2 version and it works great getting the correct version in Windows 10. Unfortunately it would be a complicated process to "validate" NSIS 3 (especially since it is still in beta) in my company and therefore I need to stick to 2.46 and use !packhdr (or something else).
The trouble is I don't know how exactly to get the version of the OS. Is there a new version of WinVer.nsh that I can use in 2.46? I tried the one from 3.0 and it gives some errors. Is there something else that I need to do?
What I need to achieve is have something like being able to use ${IsWin10}.

Thanks,
Mircea

I suggest you read this again:
* http://forums.winamp.com/showpost.ph...46&postcount=4
* http://forums.winamp.com/showpost.ph...65&postcount=6


tl;dr

It's not a matter of updating "WinVer.nsh" (which of course needs to be done too, if you want a ${IsWin10} macro), but a matter of the underlying operating system function being broken! The temporary workaround of adding a "compatibility manifest" for Windows 10 is only possible with NSIS 3, because NSIS 2.x simply didn't support that. Well, perhaps you could add the required Manifest "manually", by using !packhdr, but it still doesn't solve the underlying problem. You can have a look at GetRealOSVersion, if you don't mind using a plug-in.
Anders#
To detect Win10 with WinVer.nsh in NSIS 2.4x you need to:
  1. Update WinVer.nsh

    Copy the two lines with "_10" and one line with " 10" from here and paste them into the correct place. This should allow code using ${IsWin10} to compile (but will not work when actually running because Windows lies).

  2. Use the !packhdr workaround to update the manifest.

    You might have to fix the packhdr code to include the {8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a} GUID.




NSIS 3 might still be in beta but that is just a label, it is very stable and I would recommend using it.
Mircea M#
Hi,

I tried the StdUtils and they also work well. I finally talked to the person responsible with validating new software versions for our team and I will in the end use 3.0 (not such a big amount of work after all 🙂).

Thanks all!
stass#
This code, in Win 10 - on the HDD is operating normally, but with USB in Win10 - does not work !
Why is that ?

OutFile "WMI_OS_Info.exe" 
!include "LogicLib.nsh" 
!macro IWbemClassObject->Get NameObject OUT
    System::Call "*(i,i,i)i.R4"
    System::Call "$R3->4(w'${NameObject}',i0,iR4,i0,i0)"
    System::Call "*$R4(i.R6,i,i.R5)"
    StrCmp $R6 3 0 +2
    IntFmt $R5 %u $R5
    StrCmp $R6 8 0 +2
    !ifdef NSIS_UNICODE
      IntFmt $R5 %s $R5
    !else
      IntFmt $R5 %S $R5
    !endif
    System::Call "ole32::VariantClear(iR4)"
    System::Free $R4
    StrCpy ${OUT} $R5
!macroend
Section
   System::Call "ole32::CoInitializeEx(i0,i2)"
   System::Call "ole32::CoCreateInstance(g'{4590f811-1d3a-11d0-891f-00aa004b2e24}',i0,i1,g'{dc12a687-737f-11cf-884d-00aa004b2e24}',*i.R0)i.R7"
   ${If} $R7 == 0
      System::Call "ole32::CoInitializeSecurity(i0,i-1,i0,i0,i2,i3,i0,i0,i0)"
      System::Call "$R0->3(w'root\CIMV2',i0,i0,i0,i0,i0,i0,*i.R1)i.R7"
      ${If} $R7 == 0
         System::Call "$R1->20(w'WQL', w'SELECT * FROM Win32_OperatingSystem',i48,i0,*i.R2)i.R7"
         System::Call "$R2->4(i0xffffffff,i1,*i.R3,*i)i.R7"
         ${If} $R7 == 0
              
        !insertmacro IWbemClassObject->Get "Caption" $7
        MessageBox MB_OK "Caption=$7"
        !insertmacro IWbemClassObject->Get "Version" $7
        MessageBox MB_OK "Version=$7"
                             
               System::Call "$R0->2()"
               System::Call "$R1->2()"
               System::Call "$R2->2()"
               System::Call "$R3->2()"
         ${Else}
            System::Call "$R0->2()"
            System::Call "$R1->2()"
            System::Call "$R2->2()"
         ${EndIf}
      ${Else}
        System::Call "$R0->2()"
        System::Call "$R1->2()"
      ${EndIf}
  ${EndIf}
SectionEnd 
Anders#
Originally Posted by stass View Post
This code, in Win 10 - on the HDD is operating normally, but with USB in Win10 - does not work !
Why is that ?
You should DetailPrint the return value of each call ($R7 in most cases) so you can tell where it fails and why. You could also try moving CoInitializeSecurity before CoCreateInstance.
stass#
Here :
System::Call "$R2->4(i0xffffffff,i1,*i.R3,*i)i.R7"
in the $ R7 returns - not zero

Anders
You could also try moving CoInitializeSecurity before CoCreateInstance.
It does not work ...

How to fix the code ? Tell me please.
Anders#
Yes, we know it is not zero but that is not helpful is it? We need to know the actual value. Once you figure that out you can see if it is listed @ https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

Also, you never check that IWbemServices::ExecQuery ($R1->20 ?) worked!
stass#
This code works fine with USB devices - in Win7 and in Win8.
But this same code - does not work in Win10...
Unsolved mystery ...
stass#
Can not understand anything... In W7 and W8 - the code works when run from USB devices. In W10 - it does not work ...
Or Nsis can not determine the version of the W10 - with USB device ?
stass#
Please tell me - what is the correct syntax for the function RtlGetVersion ?
The RtlGetVersion routine returns version information about the currently running operating system.


System::Call 'ntdll::RtlGetVersion ???
Anders#
Originally Posted by stass View Post
Please tell me - what is the correct syntax for the function RtlGetVersion ?
The RtlGetVersion routine returns version information about the currently running operating system.


System::Call 'ntdll::RtlGetVersion ???
While I work on that, maybe you can tell us the WMI error code you are getting?
stass#
Anders
Error code I do not get ...
I'm quite confused with WMI code ... Knowledge is not enough to understand ...
Anders#
Originally Posted by stass View Post
Anders
Error code I do not get ...
I'm quite confused with WMI code ... Knowledge is not enough to understand ...
Before the ${If} $R7 == 0 that fails, just do DetailPrint $R7
Anders#
Try this:
!define CLSID_WbemLocator {4590f811-1d3a-11d0-891f-00aa004b2e24}
!define IID_IWbemLocator {dc12a687-737f-11cf-884d-00aa004b2e24}
!define RPC_C_AUTHN_LEVEL_DEFAULT   0
!define RPC_C_IMP_LEVEL_IMPERSONATE 3
!define WBEM_S_NO_ERROR 0
!define WBEM_FLAG_FORWARD_ONLY 0x20
!define WBEM_FLAG_RETURN_IMMEDIATELY 0x10
!define WBEM_INFINITE 0xffffffff
!include LogicLib.nsh
!ifndef IUnknown::Release ; Mini Win\COM.nsh replacement for 2.46
!define IUnknown::Release "!insertmacro NSISCOMCALL 2 ()i "
!macro NSISCOMCALL vtblidx decl ptr params
System::Call `${ptr}->${vtblidx}${decl}${params}`
!macroend
!endif
Function CreateWbemLocatorInstance
Push $0
Push $1
; OleInitialize not called, it is initialized by NSIS
System::Call 'OLE32::CoInitializeSecurity(i0,i-1,i0,i0,i${RPC_C_AUTHN_LEVEL_DEFAULT},i${RPC_C_IMP_LEVEL_IMPERSONATE},i0,i0,i0.r1)i.r0'
DetailPrint DBG:CoInitializeSecurity:$0
${If} $0 >= 0
${OrIf} $0 = 0x80010119 ; RPC_E_TOO_LATE
    System::Call 'OLE32::CoCreateInstance(g"${CLSID_WbemLocator}",i0,i1,g"${IID_IWbemLocator}",*i0r1)i.r0'
    DetailPrint DBG:CoCreateInstance:$0($1)
${EndIf}
Exch $1
Exch
Exch $0
FunctionEnd
Function WbemClassObject_Get
Exch $0
Exch
Exch $1
Push $2
System::Call '*(&i2,&i6,&i8)i.r2'
${If} $2 <> 0
    System::Call "$1->4(wr0,i0,ir2,i0,i0)i.r0" ; WbemClassObject->Get
    DetailPrint DBG:WbemClassObject->Get:$0
    StrCpy $1 "" ; Default data on error
    ${If} $0 = ${WBEM_S_NO_ERROR}
        Push $3
        System::Call '*$2(&i2.r3)'
        System::Call 'OLEAut32::VariantChangeType(ir2,ir2,i4,i8)i.r0'
        DetailPrint DBG:VariantChangeType($3->8):$0
        Pop $3
        ${IfThen} $0 = 0 ${|} System::Call "*$2(i,i,w.r1)" ${|}
        System::Call 'OLEAut32::VariantClear(ir2)'
    ${EndIf}
    System::Free $2
${Else}
    StrCpy $0 0x8007000E ; OOM
${EndIf}
Pop $2
Exch $1
Exch
Exch $0
FunctionEnd
!macro IWbemClassObject->Get IWbemClassObject Name Out_ErrCode Out_Data
Push ${IWbemClassObject}
Push "${Name}"
Call WbemClassObject_Get
Pop ${Out_ErrCode}
Pop ${Out_Data}
DetailPrint "DBG:WbemClassObject_Get(${Name}):${Out_ErrCode}(${Out_Data})"
!macroend
Section
Call CreateWbemLocatorInstance
Pop $0
Pop $1
${IfThen} $0 < 0 ${|} Abort ${|}
System::Call '$1->3(w"root\CIMV2",i0,i0,i0,i0,i0,i0,*i.r2)i.r0' ; IWbemLocator->ConnectServer
${IUnknown::Release} $1 "" ; Release IWbemLocator
DetailPrint DBG:IWbemLocator->ConnectServer:$0($2)
${IfThen} $0 <> ${WBEM_S_NO_ERROR} ${|} Abort ${|}
System::Call '$2->20(w"WQL",w"SELECT * FROM Win32_OperatingSystem",i${WBEM_FLAG_FORWARD_ONLY}|${WBEM_FLAG_RETURN_IMMEDIATELY},i0,*i0r3)i.r0'
DetailPrint DBG:IWbemServices->ExecQuery:$0($1)
${IUnknown::Release} $2 "" ; Release IWbemServices
${IfThen} $0 <> ${WBEM_S_NO_ERROR} ${|} Abort ${|}
System::Call '$3->4(i${WBEM_INFINITE},i1,*i.r4,*i.r5)i.r0' ; IEnumWbemClassObject->Next
${IUnknown::Release} $3 "" ; Release IEnumWbemClassObject
DetailPrint DBG:IEnumWbemClassObject->Next:$0($4,$5)
${IfThen} $0 <> ${WBEM_S_NO_ERROR} ${|} Abort ${|}
!insertmacro IWbemClassObject->Get $4 "Caption" $0 $6
!insertmacro IWbemClassObject->Get $4 "Version" $0 $6
${IUnknown::Release} $4 "" ; Release IWbemClassObject
SectionEnd 
stass#
Anders
Thank you step by step detail of the code.
When you run from a USB device, code execution stops at:


DBG:CoInitializeSecurity:-2147417831
DBG:CoCreateInstance:0(6444760)
DBG:IWbemLocator->ConnectServer:0(6543336)
DBG:IWbemServices->ExecQuery:0(6444760)
DBG:IEnumWbemClassObject->Next:-2147217405(0,0)
And - Stop Code...

When you start with hdd - everything is OK :

DBG:CoInitializeSecurity:0
DBG:CoCreateInstance:0(6825920)
DBG:IWbemLocator->ConnectServer:0(6768880)
DBG:IWbemServices->ExecQuery:0(6825920)
DBG:IEnumWbemClassObject->Next:0(6885616,1)
DBG:WbemClassObject->Get:0
DBG:VariantChangeType(8->8):0
DBG:WbemClassObject_Get(Caption):0(Майкрософт Windows 10 Pro)
DBG:WbemClassObject->Get:0
DBG:VariantChangeType(8->8):0
DBG:WbemClassObject_Get(Version):0(10.0.10240)
Completed
stass#
demiller9

This error code in my script ? If so, why this error is obtained only on Win10 (on different machines, have different users, with different USB devices)?
How to fix it ?
Anders#
The call to CoInitializeSecurity also fails, that is strange. You should focus on that first.

Maybe this thread might help. You could try using something other than RPC_C_AUTHN_LEVEL_DEFAULT (maybe RPC_C_AUTHN_LEVEL_NONE(1)), try CLSID_WbemAdministrativeLocator and try passing SOLE_AUTHENTICATION_INFO to CoInitializeSecurity.