如何在Delphi中获取Windows版本,区分Vista及以上和XP?

3

有没有办法知道我们正在使用哪个版本的Windows?

我需要在Windows XP中将图像设置为TBitButton,而在Windows 7中不需要图像。应该自动完成。


1
你需要进行一个Windows api调用,具体来说,是调用GetVersionEx。快速搜索可以找到这个有关从Delphi调用Windows api的教程:http://www.blong.com/Conferences/BorConUK97/WinAPI/Api.htm - VoidStar
1
@VoidStar:不需要。:) Delphi会自动完成这个操作——在SysUtils单元中设置了几个变量,您可以读取各个版本号的不同部分。只有当您想要查找更多详细信息,例如您正在使用哪个版本(专业版、家庭版、服务器版等)时,才需要使用GetVersionEx - Ken White
另一个回答(Ken)告诉您如何区分Windows Vista及更高版本和Windows 7之间的差异。要了解确切的Windows版本,并区分服务器版本和桌面版本,请查看此问题:https://dev59.com/enVD5IYBdhLWcg3wL4mM - Warren P
2个回答

10

检查 SysUtils.Win32MajorVersion (在 Delphi 7 中,如果还没有添加 SysUtils 到你的 uses 子句中,你需要手动添加 - 更高版本会自动添加)。最简单的方法是像通常一样在IDE中分配 Glyph,如果运行在 Vista 或更高版本上,则将其清除:

if SysUtils.Win32MajorVersion >= 6 then // Windows Vista or higher
  BitBtn1.Glyph := nil;

有关检测特定 Windows 版本和版本的更多信息,请参见此帖子。它尚未更新到最新的 Windows 版本和版本,但可以让您入门。您还可以搜索 SO 中的[delphi] GetVersionEx以查看其他示例。


3
这是检测Vista/2008及以上版本的方法。要注意相关的CheckWin32Version函数,因为在至少D6中它是不正确的。虽然已经修复了,但我不确定D7是否也有这个问题。 - David Heffernan

0
这实际上是我的一个小项目 - 一个可插拔的组件,提供操作系统的信息,并且可以在设计时预览它...
unit JDOSInfo;

interface

uses
  Classes, Windows, SysUtils, StrUtils, Forms, Registry;

type
  TJDOSInfo = class(TComponent)
  private
    fReg: TRegistry;
    fKey: String;
    fMinor: Integer;
    fMajor: Integer;
    fBuild: Integer;
    fPlatform: Integer;
    fIsServer: Bool;
    fIs64bit: Bool;
    fProductName: String;
    function GetProductName: String;
    procedure SetProductName(Value: String);
    procedure SetMajor(Value: Integer);
    procedure SetMinor(Value: Integer);
    procedure SetBuild(Value: Integer);
    procedure SetPlatform(Value: Integer);
    procedure SetIs64Bit(const Value: Bool);
    procedure SetIsServer(const Value: Bool);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Major: Integer read fMajor write SetMajor;
    property Minor: Integer read fMinor write SetMinor;
    property Build: Integer read fBuild write SetBuild;
    property Platf: Integer read fPlatform write SetPlatform;
    property ProductName: String read GetProductName write SetProductName;
    property IsServer: Bool read fIsServer write SetIsServer;
    property Is64Bit: Bool read fIs64bit write SetIs64Bit;
  end;

function IsWOW64: Boolean; 
function GetOSInfo: TOSVersionInfo;


procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('JD Custom', [TJDOSInfo]);
end;

function GetOSInfo: TOSVersionInfo;
begin
  FillChar(Result, SizeOf(Result), 0);
  Result.dwOSVersionInfoSize := SizeOf(Result);
  if not GetVersionEx(Result) then
    raise Exception.Create('Error calling GetVersionEx');
end;

function IsWOW64: Boolean;
type
  TIsWow64Process = function( // Type of IsWow64Process API fn
    Handle: THandle;
    var Res: BOOL): BOOL; stdcall;
var
  IsWow64Result: BOOL;              // result from IsWow64Process
  IsWow64Process: TIsWow64Process;  // IsWow64Process fn reference
begin
  // Try to load required function from kernel32
  IsWow64Process:= GetProcAddress(GetModuleHandle('kernel32'),'IsWow64Process');
  if Assigned(IsWow64Process) then
  begin
    // Function is implemented: call it
    if not IsWow64Process(GetCurrentProcess, IsWow64Result) then
      raise Exception.Create('Bad process handle');
    // Return result of function
    Result := IsWow64Result;
  end else
    // Function not implemented: can't be running on Wow64
    Result:= False;
end;

constructor TJDOSInfo.Create(AOwner: TComponent);
var
  Info: TOSVersionInfo;
  Str: String;
begin
  inherited Create(AOwner);
  fReg:= TRegistry.Create(KEY_READ);
  fReg.RootKey:= HKEY_LOCAL_MACHINE;
  fKey:= 'Software\Microsoft\Windows NT\CurrentVersion';  
  fReg.OpenKey(fKey, False);
  Info:= GetOSInfo;
  fMajor:= Info.dwMajorVersion;
  fMinor:= Info.dwMinorVersion;
  fBuild:= Info.dwBuildNumber;
  fIsServer:= False;
  fIs64bit:= False;
  fPlatform:= Info.dwPlatformId;
  if fMajor >= 5 then begin
    //After 2000
    if fReg.ValueExists('ProductName') then
      Str:= fReg.ReadString('ProductName')
    else begin
      Str:= 'Unknown OS: '+IntToStr(fMajor)+'.'+IntToStr(fMinor)+'.'+
        IntToStr(fBuild)+'.'+IntToStr(fPlatform);
    end;      
    if fReg.ValueExists('InstallationType') then begin
      if UpperCase(fReg.ReadString('InstallationType')) = 'SERVER' then
        fIsServer:= True;
    end;
    fIs64bit:= IsWOW64;
    if fIs64bit then
      Str:= Str + ' 64 Bit';
  end else begin
    //Before 2000
    case fMajor of
      4: begin
        case fMinor of
          0: Str:= 'Windows 95';
          10: Str:= 'Windows 98';
          90: Str:= 'Windows ME';
        end;
      end;
      else begin
        Str:= 'Older than 95';
      end;
    end;
  end;
  Self.fProductName:= Str;
end;

destructor TJDOSInfo.Destroy;
begin
  if assigned(fReg) then begin
    if fReg.Active then
      fReg.CloseKey;
    fReg.Free;
  end;
  inherited Destroy;
end;

function TJDOSInfo.GetProductName: String;
begin
  Result:= Self.fProductName;
end;

procedure TJDOSInfo.SetProductName(Value: String);
begin
  //Do Nothing Here!
end;

procedure TJDOSInfo.SetMinor(Value: Integer); 
begin
  //Do Nothing Here!
end;

procedure TJDOSInfo.SetMajor(Value: Integer); 
begin
  //Do Nothing Here!
end;

procedure TJDOSInfo.SetBuild(Value: Integer);  
begin
  //Do Nothing Here!
end;

procedure TJDOSInfo.SetPlatform(Value: Integer); 
begin
  //Do Nothing Here!
end;

procedure TJDOSInfo.SetIs64Bit(const Value: Bool);
begin
  //Do Nothing Here!
end;

procedure TJDOSInfo.SetIsServer(const Value: Bool);
begin
  //Do Nothing Here!
end;

end.

3
无法检测到 NT。这段代码感觉很奇怪。如果已经赋值就释放?直接调用 Free 即可。空属性设置器有什么作用? - David Heffernan
不确定NT是否检测到,原始代码是我找到的其他代码的碎片。我总是(而且我的意思是总是)在释放它们之前检查是否创建了东西,以防万一(任何事情都可以防止访问冲突)。空属性设置器允许在设计时显示属性。至少在Delphi 7中,您无法发布只读属性。我相信其他较新版本允许,但这是一个只读技巧。 - Jerry Dodge
1
你可以在空对象引用上调用“Free”。因此,在调用“Free”之前,实际上不需要检查是否已分配某些内容。 - David Heffernan
2
好的,你有机会在这里学到一些东西。实际上,错误在于析构函数中对fReg的方法调用。需要在该代码周围加上if Assigned(fReg)检查,但仅调用Free时则不需要,而且这样做是很糟糕的风格。 - David Heffernan
1
是的,我在我最后一条评论中承认了那个 bug。请让我再说清楚一点:我在一年多以前制作了这个组件,很少使用它,从未完成过它,并且从未打算将其作为任何最终产品。实际上,我忘记了它没有完成。我只是复制/粘贴代码到这里来演示问题。很抱歉它不完美,但它可以工作。感谢您指出缺陷,我会为未来修复它们。 - Jerry Dodge
显示剩余3条评论

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