Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何检测真实的Windows版本?_Windows_Delphi_Winapi_Version - Fatal编程技术网

如何检测真实的Windows版本?

如何检测真实的Windows版本?,windows,delphi,winapi,version,Windows,Delphi,Winapi,Version,我知道我可以调用GetVersionEx Win32 API函数来检索Windows版本。在大多数情况下,返回的值反映了我的Windows版本,但有时情况并非如此 如果用户在兼容层下运行我的应用程序,那么GetVersionEx将不会报告真实版本,而是报告由兼容层强制执行的版本。例如,如果我运行Vista并在“WindowsNT4”兼容模式下执行我的程序,GetVersionEx将不会返回版本6.0,而是返回版本4.0 有没有办法绕过此行为并获得真正的Windows版本?WMI查询: "Sele

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

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

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

WMI查询:

"Select * from Win32_OperatingSystem"
编辑:实际上最好是:

"Select Version from Win32_OperatingSystem"
您可以在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;
函数操作系统显示名称:字符串;
函数GetWMIObject(const objectName:string):IDispatch;
变量
chEaten:整数;
BindCtx:IBindCtx;
名字:伊莫尼克尔;
开始
olcheck(CreateBindCtx(0,bindCtx));
olcheck(MkParseDisplayName(BindCtx、PChar(objectName)、chEaten、名字对象));
OleCheck(名字对象BindToObject(BindCtx,nil,IDispatch,Result));
结束;
函数VarToString(const值:OleVariant):字符串;
开始
如果变量STR(值),则开始
结果:=微调(值);
结束,否则开始
结果:='';
结束;
结束;
函数FullVersionString(const项:OleVariant):字符串;
变量
标题、ServicePack、版本、体系结构:字符串;
开始
标题:=VarToString(Item.Caption);
ServicePack:=VarToString(Item.csd版本);
版本:=VarToString(Item.Version);
架构:=架构显示名称(SystemArchitecture);
结果:=标题;
如果是ServicePack“”,则开始
结果:=结果+“”+ServicePack;
结束;
结果:=结果+',版本'+版本+','+架构;
结束;
变量
objWMIService:油变异体;
大肠菌群:油变异体;
项目:油变异体;
oEnum:IEnumvariant;
伊瓦鲁:长词;
开始
尝试
objWMIService:=GetWMIObject('winmgmts:\\localhost\root\cimv2');
colItems:=objWMIService.ExecQuery('SELECT Caption,CSDVersion,Version FROM Win32_OperatingSystem','WQL',0);
oEnum:=IUnknown(colItems.\u NewEnum)作为IEnumVariant;
如果oEnum.Next(1,项,值)=0,则开始
结果:=完整版本字符串(项目);
出口
结束;
除了
//是的,我知道这很糟糕,但是如果WMI代码失败,我可能想使用下面的回退代码
结束;
(*回退,依赖于不推荐使用的函数GetVersionEx,报告错误的值
清单不包含与执行系统*匹配的支持对象时*)
结果:=TOSVersion.ToString;
结束;

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

长话短说,这里有一个这样的列表,其中只包含来自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 >*功能:在* >GetLocaleInfo:Vista >GetLargePageMinimum:Vista,服务器2003 GetDLLDirectory:Vista,Server 2003,XP SP1 GetNativeSystemInfo:Vista、Server 2003、XP SP1、XP 替换文件:Vista,Server 2003,XP SP1,XP,2000 OpenThread:Vista、Server 2003、XP SP1、XP、2000、ME GetThreadPriorityBoost:Vista、Server2003、XPSP1、XP、2000、NT4 IsDebuggerPresent:Vista,Server2003,XPSP1,XP,2000,ME,NT4,98 GetDiskFreeSpaceEx:Vista,Server2003,XPSP1,XP,2000,ME,NT4,98,95OSR2 ConnectNamedPipe:Vista、Server 2003、XP SP1、XP、2000、NT 4、NT 3 哔哔声:Vista,Server 2003,XP SP1,XP,2000,ME,98,95 OSR2,95 编写确定真实操作系统版本的函数很简单;只需从最新的操作系统到最旧的操作系统,并使用检查导出的API即可。用任何语言实现这一点都应该是微不足道的

Delphi中的以下代码是从免费库中提取的):

TDSiWindowsVersion=(wvUnknown、wvWin31、wvWin95、wvWin95OSR2、wvWin98、,
wvWin98SE、wvWinME、wvWin9x、wvWinNT3、wvWinNT4、wvWin2000、wvWinXP、,
wvWinNT、wvWinServer2003、WVwinista);
函数DSiGetWindowsVersion:TDSiWindowsVersion;
变量
versionInfo:toversioninfo;
开始
versionInfo.dwOSVersionInfoSize:=SizeOf(versionInfo);
GetVersionEx(versionInfo);
结果:=wvUnknown;
案例版本info.dwPlatformID of
VER_PLATFORM_WIN32s:结果:=wvWin31;
版本平台WIN32 WINDOWS:
案例版本info.dwMinorVersion of
0:
如果Trim(versionInfo.szCSDVersion[1])='B',则
结果:=wvWin95OSR2
其他的
结果:wvWin95;
10:
如果Trim(versionInfo.szCSDVersion[1])='A',则
结果:=wvWin98SE
其他的
结果:=wvWin98;
90:
如果(versionInfo.dwBuildNumber=73010104),则
结果:=wvWinME;
其他的
结果:=wvWin9x;
结束//案例版本info.dwMinorVersion
版本平台\u WIN32\n NT:
案例版本info.dwmajor的版本
3:结果:=wvWinNT3;
4:结果:=wvWinNT4;
5:
案例版本info.dwMinorVersion of
0:结果:=WVW2000;
1:结果:=wvWinXP;
2:结果:=wvWinServer2003;
其他结果:=wvWinNT
结束//案例版本info.dwMinorVersion
6:结果:=wvWinVista;
结束//案例版本info.dwMajorVersion
结束//versionInfo.dwPlatformID
结束;{DSiGetWindowsVersion}
函数DSiGetTrueWindowsVersion:TDSiWindowsVersion;
函数ExportsAPI(模块:HMODULE;常量apiName:string):布尔;
开始
结果:=GetProcAddress(模块,PChar(apiName))nil;
结束;{ExportsAPI}
变量
hKernel32:HMODULE;
开始{DSiGetTrueWindowsVersion}
hKernel32:=GetModuleHandle('kernel32');
Win3
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 }
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion
  TWindowsVersion =
   (wvUnknown, wvWin95, wvWin95OSR2, wvWin98, wvWin98SE, wvWinME,
    wvWinNT31, wvWinNT35, wvWinNT351, wvWinNT4, wvWin2000, wvWinXP,
    wvWin2003, wvWinXP64, wvWin2003R2, wvWinVista, wvWinServer2008,
    wvWin7, wvWinServer2008R2);
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);
 TNtProductType =       (ptUnknown, ptWorkStation, ptServer, ptAdvancedServer,        
        ptPersonal, ptProfessional, ptDatacenterServer, 
        ptEnterprise, ptWebEdition);
function IsSupported:Boolean;
begin
  case GetWindowsVersion of
     wvVista:  result := false; 
    else
      result := true;
  end;
end;
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.
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;
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 = $0F;

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.