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
How to detect true Windows version?
提问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 信息。