windows 如何检测真正的Windows版本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/57124/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 05:15:36  来源:igfitidea点击:

How to detect true Windows version?

windowsdelphiwinapiversion

提问by gabr

I know I can call the GetVersionEx Win32 API function to retrieve Windows version. In most cases returned value reflects the version of my Windows, but sometimes that is not so.

我知道我可以调用 GetVersionEx Win32 API 函数来检索 Windows 版本。在大多数情况下,返回值反映了我的 Windows 版本,但有时并非如此。

If a user runs my application under the compatibility layer, then GetVersionEx won't be reporting the real version but the version enforced by the compatibility layer. For example, if I'm running Vista and execute my program in "Windows NT 4" compatibility mode, GetVersionEx won't return version 6.0 but 4.0.

如果用户在兼容层下运行我的应用程序,那么 GetVersionEx 将不会报告真实版本,而是由兼容层强制执行的版本。例如,如果我运行 Vista 并在“Windows NT 4”兼容模式下执行我的程序,GetVersionEx 将不会返回 6.0 版而是 4.0 版。

Is there a way to bypass this behaviour and get true Windows version?

有没有办法绕过这种行为并获得真正的 Windows 版本?

采纳答案by gabr

The best approach I know is to check if specific API is exported from some DLL. Each new Windows version adds new functions and by checking the existance of those functions one can tell which OS the application is running on. For example, Vista exports GetLocaleInfoExfrom kernel32.dll while previous Windowses didn't.

我知道的最好方法是检查是否从某个 DLL 导出了特定的 API。每个新的 Windows 版本都会添加新功能,通过检查这些功能是否存在,人们可以判断应用程序在哪个操作系统上运行。例如,Vista从 kernel32.dll导出GetLocaleInfoEx,而以前的 Windows 则没有。

To cut the long story short, here is one such list containing only exports from kernel32.dll.

长话短说,这里有一个这样的列表,其中只包含来自 kernel32.dll 的导出。

> *function: implemented in*  
> GetLocaleInfoEx:       Vista  
> GetLargePageMinimum:   Vista, Server 2003  
GetDLLDirectory:         Vista, Server 2003, XP SP1  
GetNativeSystemInfo:     Vista, Server 2003, XP SP1, XP  
ReplaceFile:             Vista, Server 2003, XP SP1, XP, 2000  
OpenThread:              Vista, Server 2003, XP SP1, XP, 2000, ME  
GetThreadPriorityBoost:  Vista, Server 2003, XP SP1, XP, 2000,     NT 4  
IsDebuggerPresent:       Vista, Server 2003, XP SP1, XP, 2000, ME, NT 4, 98   
GetDiskFreeSpaceEx:      Vista, Server 2003, XP SP1, XP, 2000, ME, NT 4, 98, 95 OSR2  
ConnectNamedPipe:        Vista, Server 2003, XP SP1, XP, 2000,     NT 4,                 NT 3  
Beep:                    Vista, Server 2003, XP SP1, XP, 2000, ME,       98, 95 OSR2, 95  

Writing the function to determine the real OS version is simple; just proceed from newest OS to oldest and use GetProcAddressto check exported APIs. Implementing this in any language should be trivial.

编写确定真实操作系统版本的函数很简单;只需从最新的操作系统到最旧的操作系统,然后使用GetProcAddress检查导出的 API。用任何语言实现它应该是微不足道的。

The following code in Delphi was extracted from the free DSiWin32library):

Delphi 中的以下代码摘自免费的DSiWin32库):

TDSiWindowsVersion = (wvUnknown, wvWin31, wvWin95, wvWin95OSR2, wvWin98,
  wvWin98SE, wvWinME, wvWin9x, wvWinNT3, wvWinNT4, wvWin2000, wvWinXP,
  wvWinNT, wvWinServer2003, wvWinVista);

function DSiGetWindowsVersion: TDSiWindowsVersion;
var
  versionInfo: TOSVersionInfo;
begin
  versionInfo.dwOSVersionInfoSize := SizeOf(versionInfo);
  GetVersionEx(versionInfo);
  Result := wvUnknown;
  case versionInfo.dwPlatformID of
    VER_PLATFORM_WIN32s: Result := wvWin31;
    VER_PLATFORM_WIN32_WINDOWS:
      case versionInfo.dwMinorVersion of
        0:
          if Trim(versionInfo.szCSDVersion[1]) = 'B' then
            Result := wvWin95OSR2
          else
            Result := wvWin95;
        10:
          if Trim(versionInfo.szCSDVersion[1]) = 'A' then
            Result := wvWin98SE
          else
            Result := wvWin98;
        90:
          if (versionInfo.dwBuildNumber = 73010104) then
             Result := wvWinME;
           else
             Result := wvWin9x;
      end; //case versionInfo.dwMinorVersion
    VER_PLATFORM_WIN32_NT:
      case versionInfo.dwMajorVersion of
        3: Result := wvWinNT3;
        4: Result := wvWinNT4;
        5:
          case versionInfo.dwMinorVersion of
            0: Result := wvWin2000;
            1: Result := wvWinXP;
            2: Result := wvWinServer2003;
            else Result := wvWinNT
          end; //case versionInfo.dwMinorVersion
        6: Result := wvWinVista;
      end; //case versionInfo.dwMajorVersion
    end; //versionInfo.dwPlatformID
end; { DSiGetWindowsVersion }

function DSiGetTrueWindowsVersion: TDSiWindowsVersion;

  function ExportsAPI(module: HMODULE; const apiName: string): boolean;
  begin
    Result := GetProcAddress(module, PChar(apiName)) <> nil;
  end; { ExportsAPI }

var
  hKernel32: HMODULE;

begin { DSiGetTrueWindowsVersion }
  hKernel32 := GetModuleHandle('kernel32');
  Win32Check(hKernel32 <> 0);
  if ExportsAPI(hKernel32, 'GetLocaleInfoEx') then
    Result := wvWinVista
  else if ExportsAPI(hKernel32, 'GetLargePageMinimum') then
    Result := wvWinServer2003
  else if ExportsAPI(hKernel32, 'GetNativeSystemInfo') then
    Result := wvWinXP
  else if ExportsAPI(hKernel32, 'ReplaceFile') then
    Result := wvWin2000
  else if ExportsAPI(hKernel32, 'OpenThread') then
    Result := wvWinME
  else if ExportsAPI(hKernel32, 'GetThreadPriorityBoost') then
    Result := wvWinNT4
  else if ExportsAPI(hKernel32, 'IsDebuggerPresent') then  //is also in NT4!
    Result := wvWin98
  else if ExportsAPI(hKernel32, 'GetDiskFreeSpaceEx') then  //is also in NT4!
    Result := wvWin95OSR2
  else if ExportsAPI(hKernel32, 'ConnectNamedPipe') then
    Result := wvWinNT3
  else if ExportsAPI(hKernel32, 'Beep') then
    Result := wvWin95
  else // we have no idea
    Result := DSiGetWindowsVersion;
end; { DSiGetTrueWindowsVersion }

--- updated 2009-10-09

--- 更新 2009-10-09

It turns out that it gets very hard to do an "undocumented" OS detection on Vista SP1 and higher. A look at the API changesshows that all Windows 2008 functions are also implemented in Vista SP1 and that all Windows 7 functions are also implemented in Windows 2008 R2. Too bad :(

事实证明,在 Vista SP1 及更高版本上进行“未记录的”操作系统检测变得非常困难。对API 更改的查看表明,所有 Windows 2008 功能也在 Vista SP1 中实现,所有 Windows 7 功能也在 Windows 2008 R2 中实现。太糟糕了 :(

--- end of update

--- 更新结束

FWIW, this is a problem I encountered in practice. We (the company I work for) have a program that was not really Vista-ready when Vista was released (and some weeks after that ...). It was not working under the compatibility layer either. (Some DirectX problems. Don't ask.)

FWIW,这是我在实践中遇到的一个问题。我们(我工作的公司)有一个程序,当 Vista 发布时(以及几周后……),该程序还没有真正支持 Vista。它也不能在兼容层下工作。(一些 DirectX 问题。不要问。)

We didn't want too-smart-for-their-own-good users to run this app on Vista at all - compatibility mode or not - so I had to find a solution (a guy smarter than me pointed me into right direction; the stuff above is not my brainchild). Now I'm posting it for your pleasure and to help all poor souls that will have to solve this problem in the future. Google, please index this article!

我们根本不希望太聪明的用户在 Vista 上运行这个应用程序——无论是否兼容模式——所以我不得不找到一个解决方案(一个比我聪明的人给我指明了正确的方向;上面的东西不是我的心血结晶)。现在我发布它是为了让您高兴,并帮助所有将来必须解决这个问题的可怜人。谷歌,请索引这篇文章!

If you have a better solution (or an upgrade and/or fix for mine), please post an answer here ...

如果您有更好的解决方案(或我的升级和/或修复),请在此处发布答案...

回答by EBGreen

WMI QUery:

WMI 查询:

"Select * from Win32_OperatingSystem"

EDIT: Actually better would be:

编辑:实际上更好的是:

"Select Version from Win32_OperatingSystem"

You could implement this in Delphi like so:

你可以像这样在 Delphi 中实现它:

function OperatingSystemDisplayName: string;

  function GetWMIObject(const objectName: string): IDispatch;
  var
    chEaten: Integer;
    BindCtx: IBindCtx;
    Moniker: IMoniker;
  begin
    OleCheck(CreateBindCtx(0, bindCtx));
    OleCheck(MkParseDisplayName(BindCtx, PChar(objectName), chEaten, Moniker));
    OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
  end;

  function VarToString(const Value: OleVariant): string;
  begin
    if VarIsStr(Value) then begin
      Result := Trim(Value);
    end else begin
      Result := '';
    end;
  end;

  function FullVersionString(const Item: OleVariant): string;
  var
    Caption, ServicePack, Version, Architecture: string;
  begin
    Caption := VarToString(Item.Caption);
    ServicePack := VarToString(Item.CSDVersion);
    Version := VarToString(Item.Version);
    Architecture := ArchitectureDisplayName(SystemArchitecture);
    Result := Caption;
    if ServicePack <> '' then begin
      Result := Result + ' ' + ServicePack;
    end;
    Result := Result + ', version ' + Version + ', ' + Architecture;
  end;

var
  objWMIService: OleVariant;
  colItems: OleVariant;
  Item: OleVariant;
  oEnum: IEnumvariant;
  iValue: LongWord;

begin
  Try
    objWMIService := GetWMIObject('winmgmts:\localhost\root\cimv2');
    colItems := objWMIService.ExecQuery('SELECT Caption, CSDVersion, Version FROM Win32_OperatingSystem', 'WQL', 0);
    oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;
    if oEnum.Next(1, Item, iValue)=0 then begin
      Result := FullVersionString(Item);
      exit;
    end;
  Except
    // yes, I know this is nasty, but come what may I want to use the fallback code below should the WMI code fail
  End;

  (* Fallback, relies on the deprecated function GetVersionEx, reports erroneous values
     when manifest does not contain supportedOS matching the executing system *)
  Result := TOSVersion.ToString;
end;

回答by botismarius

How about obtaining the version of a system file?

如何获取系统文件的版本?

The best file would be kernel32.dll, located in %WINDIR%\System32\kernel32.dll.

最好的文件是 kernel32.dll,位于 %WINDIR%\System32\kernel32.dll。

There are APIs to obtain the file version. eg: I'm using Windows XP -> "5.1.2600.5512 (xpsp.080413-2111)"

有 API 可以获取文件版本。例如:我使用的是 Windows XP -> "5.1.2600.5512 (xpsp.080413-2111)"

回答by botismarius

Another solution:

另一种解决方案:

read the following registry entry:

阅读以下注册表项:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName

or other keys from

或其他键

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion

回答by Victor Fedorenkov

real version store on PEB block of process information.

真实版本存储在进程信息的 PEB 块上。

Sample for Win32 app (Delphi Code)

Win32 应用程序示例(Delphi 代码)

unit RealWindowsVerUnit;

interface

uses
  Windows;

var
  //Real version Windows
  Win32MajorVersionReal: Integer;
  Win32MinorVersionReal: Integer;

implementation

type
  PPEB=^PEB;
  PEB = record
    InheritedAddressSpace: Boolean;
    ReadImageFileExecOptions: Boolean;
    BeingDebugged: Boolean;
    Spare: Boolean;
    Mutant: Cardinal;
    ImageBaseAddress: Pointer;
    LoaderData: Pointer;
    ProcessParameters: Pointer; //PRTL_USER_PROCESS_PARAMETERS;
    SubSystemData: Pointer;
    ProcessHeap: Pointer;
    FastPebLock: Pointer;
    FastPebLockRoutine: Pointer;
    FastPebUnlockRoutine: Pointer;
    EnvironmentUpdateCount: Cardinal;
    KernelCallbackTable: PPointer;
    EventLogSection: Pointer;
    EventLog: Pointer;
    FreeList: Pointer; //PPEB_FREE_BLOCK;
    TlsExpansionCounter: Cardinal;
    TlsBitmap: Pointer;
    TlsBitmapBits: array[0..1] of Cardinal;
    ReadOnlySharedMemoryBase: Pointer;
    ReadOnlySharedMemoryHeap: Pointer;
    ReadOnlyStaticServerData: PPointer;
    AnsiCodePageData: Pointer;
    OemCodePageData: Pointer;
    UnicodeCaseTableData: Pointer;
    NumberOfProcessors: Cardinal;
    NtGlobalFlag: Cardinal;
    Spare2: array[0..3] of Byte;
    CriticalSectionTimeout: LARGE_INTEGER;
    HeapSegmentReserve: Cardinal;
    HeapSegmentCommit: Cardinal;
    HeapDeCommitTotalFreeThreshold: Cardinal;
    HeapDeCommitFreeBlockThreshold: Cardinal;
    NumberOfHeaps: Cardinal;
    MaximumNumberOfHeaps: Cardinal;
    ProcessHeaps: Pointer;
    GdiSharedHandleTable: Pointer;
    ProcessStarterHelper: Pointer;
    GdiDCAttributeList: Pointer;
    LoaderLock: Pointer;
    OSMajorVersion: Cardinal;
    OSMinorVersion: Cardinal;
    OSBuildNumber: Cardinal;
    OSPlatformId: Cardinal;
    ImageSubSystem: Cardinal;
    ImageSubSystemMajorVersion: Cardinal;
    ImageSubSystemMinorVersion: Cardinal;
    GdiHandleBuffer: array [0..33] of Cardinal;
    PostProcessInitRoutine: Cardinal;
    TlsExpansionBitmap: Cardinal;
    TlsExpansionBitmapBits: array [0..127] of Byte;
    SessionId: Cardinal;
  end;

//Get PEB block current win32 process
function GetPDB: PPEB; stdcall;
asm
  MOV EAX, DWORD PTR FS:[30h]
end;

initialization
  //Detect true windows wersion
  Win32MajorVersionReal := GetPDB^.OSMajorVersion;
  Win32MinorVersionReal := GetPDB^.OSMinorVersion;
end.

回答by Remy Lebeau

The following works for me in Windows 10 without the Windows 10 GUID listed in the application manifest:

以下在 Windows 10 中适用于我,而没有在应用程序清单中列出的 Windows 10 GUID:

uses
  System.SysUtils, Winapi.Windows;

type
  NET_API_STATUS = DWORD;

  _SERVER_INFO_101 = record
    sv101_platform_id: DWORD;
    sv101_name: LPWSTR;
    sv101_version_major: DWORD;
    sv101_version_minor: DWORD;
    sv101_type: DWORD;
    sv101_comment: LPWSTR;
  end;
  SERVER_INFO_101 = _SERVER_INFO_101;
  PSERVER_INFO_101 = ^SERVER_INFO_101;
  LPSERVER_INFO_101 = PSERVER_INFO_101;

const
  MAJOR_VERSION_MASK = 
function GetWinVersion: string;
var
  Buffer: PServerInfo101;
begin
  Buffer := nil;
  if NetServerGetInfo(nil, 101, Pointer(Buffer)) = NO_ERROR then
  try
     Result := <Build You Version String here>(
      Buffer.sv101_version_major,
      Buffer.sv101_version_minor,
      VER_PLATFORM_WIN32_NT // Save since minimum support begins in W2K
      );
  finally
    NetApiBufferFree(Buffer);
  end;
end;
F; function NetServerGetInfo(servername: LPWSTR; level: DWORD; var bufptr): NET_API_STATUS; stdcall; external 'Netapi32.dll'; function NetApiBufferFree(Buffer: LPVOID): NET_API_STATUS; stdcall; external 'Netapi32.dll'; type pfnRtlGetVersion = function(var RTL_OSVERSIONINFOEXW): LONG; stdcall; var Buffer: PSERVER_INFO_101; ver: RTL_OSVERSIONINFOEXW; RtlGetVersion: pfnRtlGetVersion; begin Buffer := nil; // Win32MajorVersion and Win32MinorVersion are populated from GetVersionEx()... ShowMessage(Format('GetVersionEx: %d.%d', [Win32MajorVersion, Win32MinorVersion])); // shows 6.2, as expected per GetVersionEx() documentation @RtlGetVersion := GetProcAddress(GetModuleHandle('ntdll.dll'), 'RtlGetVersion'); if Assigned(RtlGetVersion) then begin ZeroMemory(@ver, SizeOf(ver)); ver.dwOSVersionInfoSize := SizeOf(ver); if RtlGetVersion(ver) = 0 then ShowMessage(Format('RtlGetVersion: %d.%d', [ver.dwMajorVersion, ver.dwMinorVersion])); // shows 10.0 end; if NetServerGetInfo(nil, 101, Buffer) = NO_ERROR then try ShowMessage(Format('NetServerGetInfo: %d.%d', [Buffer.sv101_version_major and MAJOR_VERSION_MASK, Buffer.sv101_version_minor])); // shows 10.0 finally NetApiBufferFree(Buffer); end; end.

Update: NetWkstaGetInfo()would probably also work, similar to 'NetServerGetInfo()`, but I have not try it yet.

更新NetWkstaGetInfo()可能也可以工作,类似于“NetServerGetInfo()”,但我还没有尝试过。

回答by Ivry Gates

One note about using NetServerGetInfo(), which does work still on Windows 10 (10240.th1_st1)...

关于使用 NetServerGetInfo() 的一个注意事项,它在 Windows 10 (10240.th1_st1) 上仍然有效......

https://msdn.microsoft.com/en-us/library/windows/desktop/aa370903%28v=vs.85%29.aspx

https://msdn.microsoft.com/en-us/library/windows/desktop/aa370903%28v=vs.85%29.aspx

sv101_version_major

The major version number and the server type.

The major release version number of the operating system is specified in the least significant 4 bits. The server type is specified in the most significant 4 bits. The MAJOR_VERSION_MASK bitmask defined in the Lmserver.h header {0x0F} should be used by an application to obtain the major version number from this member.

sv101_version_major

主要版本号和服务器类型。

操作系统的主要发布版本号在最低有效 4 位中指定。服务器类型以最高有效 4 位指定。应用程序应使用 Lmserver.h 标头 {0x0F} 中定义的 MAJOR_VERSION_MASK 位掩码从该成员获取主要版本号。

In other words, (sv101_version_major & MAJOR_VERSION_MASK).

换句话说,(sv101_version_major & MAJOR_VERSION_MASK)。

回答by FredS

Essentially to answer duplicate Q: Getting OS major, minor, and build versions for Windows 8.1 and up in Delphi 2007

基本上是为了回答重复的问题:在 Delphi 2007 中获取 Windows 8.1 及更高版本的操作系统主要版本、次要版本和构建版本

Starting with W2K you can use NetServerGetInfo. NetServerGetInfo returns the correct info on W7 and W8.1, unable to test on W10..

从 W2K 开始,您可以使用NetServerGetInfo。NetServerGetInfo 在 W7 和 W8.1 上返回正确信息,无法在 W10 上测试。

  TWindowsVersion =
   (wvUnknown, wvWin95, wvWin95OSR2, wvWin98, wvWin98SE, wvWinME,
    wvWinNT31, wvWinNT35, wvWinNT351, wvWinNT4, wvWin2000, wvWinXP,
    wvWin2003, wvWinXP64, wvWin2003R2, wvWinVista, wvWinServer2008,
    wvWin7, wvWinServer2008R2);

回答by Warren P

Note:Gabr is asking about an approach that can bypass the limitations of GetVersionEx. JCL code uses GetVersionEx, and is thus subject to compatibility layer. This information is for people who don't need to bypass the compatibility layer, only.

注意:Gabr 正在询问一种可以绕过GetVersionEx. JCL 代码使用 GetVersionEx,因此受兼容层的约束。此信息仅适用于不需要绕过兼容层的人员。

Using the Jedi JCL, you can add unit JclSysInfo, and call function GetWindowsVersion. It returns an enumerated type TWindowsVersion.

使用 Jedi JCL,您可以添加单元 JclSysInfo,并调用函数GetWindowsVersion. 它返回一个枚举类型 TWindowsVersion。

Currently JCL contains all shipped windows versions, and gets changed each time Microsoft ships a new version of Windows in a box:

目前,JCL 包含所有已发布的 Windows 版本,并且每次 Microsoft 在一个盒子中发布新版本的 Windows 时都会更改:

TWindowsEdition =
   (weUnknown, weWinXPHome, weWinXPPro, weWinXPHomeN, weWinXPProN, weWinXPHomeK,
    weWinXPProK, weWinXPHomeKN, weWinXPProKN, weWinXPStarter, weWinXPMediaCenter,
    weWinXPTablet, weWinVistaStarter, weWinVistaHomeBasic, weWinVistaHomeBasicN,
    weWinVistaHomePremium, weWinVistaBusiness, weWinVistaBusinessN,
    weWinVistaEnterprise, weWinVistaUltimate, weWin7Starter, weWin7HomeBasic,
    weWin7HomePremium, weWin7Professional, weWin7Enterprise, weWin7Ultimate);

If you want to know if you're running 64-bit windows 7 instead of 32-bit, then call JclSysInfo.IsWindows64.

如果您想知道您运行的是 64 位 Windows 7 而不是 32 位,请调用JclSysInfo.IsWindows64.

Note that JCL allso handles Editions, like Pro, Ultimate, etc. For that call GetWindowsEdition, and it returns one of these:

请注意,JCL 也处理版本,如 Pro、Ultimate 等。对于该调用 GetWindowsEdition,它返回以下之一:

 TNtProductType =? ? ? ?(ptUnknown, ptWorkStation, ptServer, ptAdvancedServer,? ? ? ? 
        ptPersonal, ptProfessional, ptDatacenterServer, 
        ptEnterprise, ptWebEdition);

For historical interest, you can check the NT-level edition too with the NtProductType function, it returns:

出于历史兴趣,您也可以使用 NtProductType 函数检查 NT 级别版本,它返回:

function IsSupported:Boolean;
begin
  case GetWindowsVersion of
     wvVista:  result := false; 
    else
      result := true;
  end;
end;

Note that "N editions" are detected above. That's an EU (Europe) version of Windows, created due to EU anti-trust regulations. That's a pretty fine gradation of detection inside the JCL.

请注意,上面检测到“N 个版本”。这是欧盟(欧洲)版本的 Windows,根据欧盟反垄断法规创建。这是 JCL 内部非常精细的检测等级。

Here's a sample function that will help you detect Vista, and do something special when on Vista.

这是一个示例函数,可帮助您检测 Vista,并在 Vista 上执行一些特殊操作。

##代码##

Note that if you want to do "greater than" checking, then you should just use other techniques. Also note that version checking can often be a source of future breakage. I have usually chosen to warn users and continue, so that my binary code doesn't become the actual source of breakage in the future.

请注意,如果您想做“大于”检查,那么您应该只使用其他技术。另请注意,版本检查通常可能是未来损坏的来源。我通常选择警告用户并继续,这样我的二进制代码就不会成为将来破坏的实际来源。

Recently I tried to install an app, and the installer checked my drive free space, and would not install, because I had more than 2 gigabytes of free space. The 32 bit integer signed value in the installer became negative, breaking the installer. I had to install it into a VM to get it to work. Adding "smart code" often makes your app "stupider". Be wary.

最近我尝试安装一个应用程序,安装程序检查了我的驱动器可用空间,但不会安装,因为我有超过 2 GB 的可用空间。安装程序中的 32 位整数有符号值变为负数,从而破坏了安装程序。我必须将它安装到 VM 中才能使其工作。添加“智能代码”通常会使您的应用程序变得“愚蠢”。警惕。

Incidentally, I found that from the command line, you can run WMIC.exe, and type path Win32_OperatingSystem(The "Select * from Win32_OperatingSystem" didn't work for me). In future perhaps JCL could be extended to use the WMI information.

顺便说一句,我发现从命令行,您可以运行 WMIC.exe,然后键入path Win32_OperatingSystem(“从 Win32_OperatingSystem 中选择 *”对我不起作用)。将来也许可以扩展 JCL 以使用 WMI 信息。