【问题标题】:Get Real HDD Serial Number with Delphi使用 Delphi 获取真实的硬盘序列号
【发布时间】:2012-10-24 07:42:24
【问题描述】:

我正在尝试制作 delphi 程序服务器和客户端,以便保护我的应用程序并确保所有用户都在控制之下,我应该给他们一个无法更改的唯一密钥以不丢失它们句柄,所以我认为应该是硬盘序列号+ Bios SN,但我记得移除主板电池时可以更改Bios,所以它不会工作。 所以我现在选择的是 HDD 真实序列号,我尝试使用下面的代码来获取它,但它没有用

    unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,WbemScripting_TLB,ActiveX;

type
  TForm4 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

function GetWMIstring (wmiHost, wmiClass, wmiProperty : string):string;
var  // These are all needed for the WMI querying process
  Locator:  ISWbemLocator;
  Services: ISWbemServices;
  SObject:  ISWbemObject;
  ObjSet:   ISWbemObjectSet;
  SProp:    ISWbemProperty;
  Enum:     IEnumVariant;
  Value:    Cardinal;
  TempObj:  OleVariant;
  SN: string;
begin
  try
  Locator := CoSWbemLocator.Create;  // Create the Location object
  // Connect to the WMI service, with the root\cimv2 namespace
   Services :=  Locator.ConnectServer(wmiHost, 'root\cimv2', '', '', '','', 0, nil);
  ObjSet := Services.ExecQuery('SELECT * FROM '+wmiClass, 'WQL',
    wbemFlagReturnImmediately and wbemFlagForwardOnly , nil);
  Enum :=  (ObjSet._NewEnum) as IEnumVariant;
  while (Enum.Next(1, TempObj, Value) = S_OK) do
  begin
    SObject := IUnknown(tempObj) as ISWBemObject;
    SProp := SObject.Properties_.Item(wmiProperty, 0);
    if VarIsNull(SProp.Get_Value) then
      result := ''
    else
    begin
      SN := SProp.Get_Value;
      result :=  SN;
    end;
  end;
  except // Trap any exceptions (Not having WMI installed will cause one!)
   on exception do
    result := '';
   end;
end;

procedure TForm4.Button1Click(Sender: TObject);
var
x:string;
Y:string;

begin


    X:=GetWMIstring('','Win32_BIOS','SerialNumber');
    Y:=GetWMIstring('','Win32_DiskDrive"','SerialNumber')     ;

    ShowMessage(x+';'+y);
end;

end.

*所以请任何人更正我的代码或给我另一个想法 最好的问候*

【问题讨论】:

    标签: delphi wmi


    【解决方案1】:

    您的代码不起作用,因为您在 WMI 类名中传递了双引号。

    更改此代码

    GetWMIstring('','Win32_DiskDrive"','SerialNumber');
    

    到这里

    GetWMIstring('','Win32_DiskDrive','SerialNumber');
    

    顺便说一句,如果你遵循这个问题的答案How can I improve the WMI performance using delphi? 的建议,你可以改进你的 WMI 函数 (GetWMIstring)。

    试试这个示例(此代码使用后期绑定,不需要WbemScripting_TLB 单元)

      uses
          ActiveX,
          ComObj;
    
        var
          FSWbemLocator : OLEVariant;
          FWMIService   : OLEVariant;
    
        function  GetWMIstring(const WMIClass, WMIProperty:string): string;
        const
          wbemFlagForwardOnly = $00000020;
        var
          FWbemObjectSet: OLEVariant;
          FWbemObject   : OLEVariant;
          oEnum         : IEnumvariant;
          iValue        : LongWord;
        begin;
          Result:='';
          FWbemObjectSet:= FWMIService.ExecQuery(Format('Select %s from %s',[WMIProperty, WMIClass]),'WQL',wbemFlagForwardOnly);
          oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
          if oEnum.Next(1, FWbemObject, iValue) = 0 then
    
      if not VarIsNull(FWbemObject.Properties_.Item(WMIProperty).Value) then
    
         Result:=FWbemObject.Properties_.Item(WMIProperty).Value;
    
        FWbemObject:=Unassigned;
        end;
    
        procedure TForm4.Button1Click(Sender: TObject);
        var
          x:string;
          Y:string;
        begin
          FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
          FWMIService   := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
    
          X:=GetWMIstring('Win32_BIOS','SerialNumber');
          Y:=GetWMIstring('Win32_PhysicalMedia','SerialNumber');
    
          ShowMessage(x+';'+y);
        end;
    

    【讨论】:

    • +1。好眼力!在您指出之前,很难发现额外的"。 :-)
    • 非常感谢您的快速响应,我已经从课程中删除了双引号,但我没有注意到它,但它仍然返回 not found 和 about,为我不知道的 delphi 控制台改进它如何将其转换为 delphi 应用程序
    • 也许您使用的是 Windows XP? MSDN documentation 关于这个属性(序列号)说..Windows Server 2003, Windows XP, Windows 2000, and Windows NT 4.0: This property is not available.
    • 是的,我是 :) 那我现在能做什么?
    • 改用Win32_PhysicalMedia WMI 类,但请修改您的函数以检索 WMI 数据,我刚刚在我的答案中发布了一个示例。
    【解决方案2】:

    您应该避免,当安装更多设备时,PHYSICALDRIVE0 不需要在数据库中排在第一位。 PHYSICALDRIVE1 是我的第一个。我添加了 where 进行查询,现在可以正常工作了。对于 Win32_DiskDrive 是属性名称 DeviceID,对于 Win32_PhysicalDrive 是属性名称 Tag。这里更改了部分:

    function  GetWMIstring(const WMIClass, WMIProperty, WMIWhere:string): string;
    ...
      qry:='SELECT '+WMIProperty+' FROM '+WMIClass;
      if WMIWhere<>'' then qry:=qry + ' WHERE '+WMIWhere;
      FWbemObjectSet:= FWMIService.ExecQuery(qry,'WQL',wbemFlagForwardOnly);
    ...
      x:=GetWMIstring('Win32_DiskDrive','SerialNumber','DeviceID="\\\\.\\PHYSICALDRIVE0"'));
      y:=GetWMIstring('Win32_PhysicalMedia','SerialNumber','Tag="\\\\.\\PHYSICALDRIVE0"'));
    

    / 之前不要忘记调用 CoInitialize !!!

    【讨论】:

    • 你能编辑你的答案更清楚吗? “首先是我”是什么意思?如果你告诉调用“CoInitialize”,如果没有它,你的代码(第二行和第六行的三个点对我来说真的很奇怪)怎么能工作?
    猜你喜欢
    • 2014-02-08
    • 2011-05-04
    • 2016-06-10
    • 2011-05-10
    • 2010-11-24
    • 2014-12-31
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    相关资源
    最近更新 更多