如何确定操作系统

12

如何实现一个能够返回操作系统名称的函数?检测程序运行的环境?

例如:win2000/xp/vista/win7等。


3
我认为发帖者获得了比他曾经梦想的更多的信息! :) - Andreas Rejbrand
7个回答

20

类似这样:

function osver: string;
begin
  result := 'Unknown (Windows ' + IntToStr(Win32MajorVersion) + '.' + IntToStr(Win32MinorVersion) + ')';
  case Win32MajorVersion of
    4:
      case Win32MinorVersion of
        0: result := 'Windows 95';
        10: result := 'Windows 98';
        90: result := 'Windows ME';
      end;
    5:
      case Win32MinorVersion of
        0: result := 'Windows 2000';
        1: result := 'Windows XP';
      end;
    6:
      case Win32MinorVersion of
        0: result := 'Windows Vista';
        1: result := 'Windows 7';
        2: result := 'Windows 8';
        3: result := 'Windows 8.1';
      end;
    10:
      case Win32MinorVersion of
        0: result := 'Windows 10';
      end;
  end;
end;

其实没有必要调用GetVersionEx,因为SysUtils.pas 在其initialization子句中有一个InitPlatformID。因此全局常量Win32MajorVersionWin32MinorVersion(以及其它)已经被填充了。


非常小心处理不同的主/次版本号。请参阅http://blogs.msdn.com/b/oldnewthing/archive/2004/02/13/72476.aspx。 - Daniel Earwicker
@Daniel Earwicker:是的,我知道这不是完整的故事(这就是为什么我写了“类似于此”)。但这绝对是一个很好的开始。 - Andreas Rejbrand
这个也缺少服务器操作系统检测。 - Warren P
@Warren P:是的,我知道这不是完整的故事(这就是为什么我写了“类似于此”)。但这绝对是一个很好的开始。 - Andreas Rejbrand
1
@PureScience:“Win32”是Windows API的名称,即使操作系统是64位。 - Andreas Rejbrand

11
作为 Win32 API 的替代方案,您可以使用 WMI Win32_OperatingSystem 类。您可以编写类似以下代码的简单函数来检索操作系统的版本名称。
function  GetWin32_OSName:string;
var
  objWMIService : OLEVariant;
  colItems      : OLEVariant;
  colItem       : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;

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

begin
  objWMIService := GetWMIObject('winmgmts:\\localhost\root\cimv2');
  colItems      := objWMIService.ExecQuery('SELECT Caption FROM Win32_OperatingSystem','WQL',0);
  oEnum         := IUnknown(colItems._NewEnum) as IEnumVariant;
  if oEnum.Next(1, colItem, iValue) = 0 then
  Result:=colItem.Caption; //The caption property return an  string  wich includes the operating system version. For example, "Microsoft Windows XP Professional Version = 5.1.2500". 
end;

此外,您可以使用Win32_OperatingSystem类的其他属性来检索有关Windows版本的更多信息。

请检查此代码

program GetWMI_Win32_OperatingSystem;

{$APPTYPE CONSOLE}

uses
  SysUtils
  ,ActiveX
  ,ComObj
  ,Variants;


Procedure  GetWin32_OperatingSystem;
var
  objWMIService : OLEVariant;
  colItems      : OLEVariant;
  colItem       : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;

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

begin
  objWMIService := GetWMIObject('winmgmts:\\localhost\root\cimv2');
  colItems      := objWMIService.ExecQuery('SELECT * FROM Win32_OperatingSystem','WQL',0);
  oEnum         := IUnknown(colItems._NewEnum) as IEnumVariant;
  if oEnum.Next(1, colItem, iValue) = 0 then
  begin
    Writeln('Caption        '+colItem.Caption);
    Writeln('Version        '+colItem.Version);
    Writeln('BuildNumber    '+colItem.BuildNumber);
    Writeln('BuildType      '+colItem.BuildType);
    Writeln('CodeSet        '+colItem.CodeSet);
    Writeln('CountryCode    '+colItem.CountryCode);
    Writeln('BootDevice     '+colItem.BootDevice);
    Writeln;
  end;
end;


function  GetWin32_OSName:string;
var
  objWMIService : OLEVariant;
  colItems      : OLEVariant;
  colItem       : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;

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

begin
  objWMIService := GetWMIObject('winmgmts:\\localhost\root\cimv2');
  colItems      := objWMIService.ExecQuery('SELECT Caption FROM Win32_OperatingSystem','WQL',0);
  oEnum         := IUnknown(colItems._NewEnum) as IEnumVariant;
  if oEnum.Next(1, colItem, iValue) = 0 then
  Result:=colItem.Caption;
end;

begin
 try
    CoInitialize(nil);
    try
      GetWin32_OperatingSystem;
      //Writeln(GetWin32_OSName);
      Readln;
    finally
    CoUninitialize;
    end;
 except
    on E:Exception do
    Begin
        Writeln(E.Classname, ': ', E.Message);
        Readln;
    End;
  end;
end.

GetWin32_OSName是我自从2000年以来一直在寻找的 :) 简短而且最好。感谢您挽救了我的一天。 - Zen Of Kursat
请注意,此功能仅支持Vista或更高版本。 - Javid

4

我在我的程序中使用这个:

{$J+}
TYPE
  TOperatingSystemClass = (osUntested,osUnknown,osWin95,osWin98,osWinME,osWinNT,osWin2000,osWinXP,osWinXPSP1,osWinXPSP2,osWinXPSP3,osWin2003,osWinVista,osWinVistaSP1,osWinVistaSP2,osWinVistaSP3,osWin7,osWin7SP1,osWin7SP2,osWin7SP3,osHigher);

FUNCTION OperatingSystemClass : TOperatingSystemClass;
  CONST
    OSClass     : TOperatingSystemClass = osUntested;

  VAR
    Info        : OSVERSIONINFOEX;
    OldInfo : OSVERSIONINFO ABSOLUTE Info;

  BEGIN
    IF OSClass=osUntested THEN BEGIN
      FillChar(Info,SizeOf(Info),0);
      Info.dwOSVersionInfoSize:=SizeOf(Info); OSClass:=osUnknown;
      IF NOT GetVersionEx(OldInfo) THEN BEGIN
        FillChar(OldInfo,SizeOf(OldInfo),0);
        OldInfo.dwOSVersionInfoSize:=SizeOf(OldInfo);
        GetVersionEx(OldInfo)
      END;
      CASE Info.dwPlatformId OF
        VER_PLATFORM_WIN32_WINDOWS      : CASE Info.dwMajorVersion OF
                                              3 : OSClass:=osWin95;
                                              4 : CASE Info.dwMinorVersion OF
                                                     0 : OSClass:=osWin95;
                                                    10 : OSClass:=osWin98
                                                  ELSE // OTHERWISE //
                                                    OSClass:=osWinME
                                                  END
                                          END;
        VER_PLATFORM_WIN32_NT           : CASE Info.dwMajorVersion OF
                                              5 : CASE Info.dwMinorVersion OF
                                                    0 : OSClass:=osWin2000;
                                                    1 : OSClass:=osWinXP;
                                                    2 : OSClass:=osWin2003
                                                  END;
                                              6 : IF Info.dwMinorVersion=0 THEN
                                                    OSClass:=osWinVista
                                                  ELSE IF Info.dwMinorVersion=1 THEN
                                                    OSClass:=osWin7
                                                  ELSE
                                                    OSClass:=osHigher
                                            END
      END;
      IF (OSClass IN [osWinXP,osWinVista,osWin7]) AND (Info.wServicePackMajor>0) THEN
        INC(OSClass,MAX(Info.wServicePackMajor,3))
    END;
    Result:=OSClass
  END;

在哪里

type
  OSVERSIONINFOEX = packed record
    dwOSVersionInfoSize: DWORD;
    dwMajorVersion: DWORD;
    dwMinorVersion: DWORD;
    dwBuildNumber: DWORD;
    dwPlatformId: DWORD;
    szCSDVersion: Array [0..127 ] of Char;
    wServicePackMajor: WORD;
    wServicePackMinor: WORD;
    wSuiteMask: WORD;
    wProductType: BYTE;
    wReserved: BYTE;
  End;
  TOSVersionInfoEx = OSVERSIONINFOEX;
  POSVersionInfoEx = ^TOSVersionInfoEx;

FYI:缺少Windows Server操作系统。 - Warren P

4

2
自从 Delphi XE2 版本以来,你可以使用 TOSVersion 记录。请注意,它是一个全局记录,你不能创建 TOSVersion 对象。
例如:
lblVersion.Caption := TOSVersion.ToString;

您可以使用以下几个记录属性:MinorMajorBuildArchitecture,以及一起提供的Platform,您可以使用它们来确保操作系统是 Windows。
要将当前系统版本与定义的版本进行比较,请使用Check版本。

1

JCL 包含了这个枚举类型:

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

它包含这个函数和其他函数:

function GetWindowsVersion: TWindowsVersion;

这里有文档

更好的是,当新版本的Windows发布时,有人会更新JCL,您就不必自己扩展此代码。 此外,在所有回答中,只有JCL处理Windows Server操作系统检测,除了通常的Windows终端用户版本。


0
function OS_IsWindowsXP: Boolean;
begin
 Result:= (Win32MajorVersion= 5) AND (Win32MinorVersion= 1);
end;

function OS_IsWindowsXPUp: Boolean;
begin
 Result:= ((Win32MajorVersion = 5) AND (Win32MinorVersion>= 1))
        OR (Win32MajorVersion>= 6);
end;



function OS_IsWindowsVista: Boolean;
begin
 Result:= (Win32MajorVersion= 6) AND (Win32MinorVersion= 0);
end;

function OS_IsWindowsVistaUp: Boolean;
begin
 Result:= (Win32MajorVersion>= 6);
end;



function OS_IsWindows7: Boolean;
begin
 Result:= (Win32MajorVersion= 6) AND (Win32MinorVersion= 1);
end;

function OS_IsWindows7Up: Boolean;
begin
 Result:= ((Win32MajorVersion = 6) AND (Win32MinorVersion>= 1))   { Any version 6 equal and above Win7 }
        OR (Win32MajorVersion>= 7);                               { Any version above 6 }
end;



function OS_IsWindows8: Boolean;
begin
 Result:= (Win32MajorVersion = 6) AND (Win32MinorVersion= 2);
end;

function OS_IsWindows8Up: Boolean;
begin
 Result:= ((Win32MajorVersion = 6) AND (Win32MinorVersion>= 2))
        OR (Win32MajorVersion>= 7);
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接