Get BIOS serial number

sorry. it's a repeated question;

I want to get bios serial number.
I had a code, and it worked, but unfortunatlly NOT now!
maybe because of new version of delphi (7), or WindowsXP, or my hardware! I don't know.
here is my code:

function GetBiosInfoAsText: string;
var
  P, Q: PAnsiChar;
begin
  Q := nil;
  P := PChar(Ptr($FE000));
  repeat
    if Q <> nil then begin
      if not (P^ in [#10, #13, #32..#126, #169, #184]) then begin
        if (P^ = #0) and (P - Q >= 8) then begin
          Result := Result + TrimRight(string(Q)) + #13#10;
        end;
        Q := nil;
      end;
    end else
      if P^ in [#33..#126, #169, #184] then
        Q := P;
    Inc(P);
  until P > PChar(Ptr($FFFFF));
  Result := TrimRight(Result);
end;

I will thank you for your attention.
mehdi_mAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

LRHGuyCommented:
I tried your code here with Delphi7 on Win ME and it works fine!
0
esoftbgCommented:
I tested your code with Delphi 7 under Windows XP, SP2 and it raises an exception:
Access violation at address 00450D20 in module 'Q_21192399.exe'. Read of address 000FE000.
I think about it succeed or not depends on the hardware ....
0
Wim ten BrinkSelf-employed developerCommented:
uses
  ActiveX, WbemScripting_TLB;

function GetSerialNumber: string;
const
  sQuery = 'select SerialNumber from Win32_BIOS';
var
  Item: SWbemObject;
  NumProp: LongWord;
  ObjectSet: ISWbemObjectSet;
  OleProperty: OleVariant;
begin
  ObjectSet := CoSWbemLocator.Create.ConnectServer( '', 'root\cimv2', '', '', '', '', 0, nil ).ExecQuery( sQuery, 'WQL', wbemFlagBidirectional, nil );
  if Succeeded( (ObjectSet._NewEnum as IEnumVariant).Next( 1, OleProperty, NumProp ) ) and ( NumProp > 0 ) and Succeeded( IDispatch( OleProperty ).QueryInterface( SWBemObject, Item ) ) then begin
    Result := VarToStr( Item.Properties_.Item( 'SerialNumber', 0 ) );
  end else begin
    Result := '<Not found>';
  end;
end;

WMI is so powerful to get this kind of information... :-)

http://www.workshop-alex.org/sources/WbemScripting_TLB/WbemScripting_TLB.html or http://www.workshop-alex.org/sources/WbemScripting_TLB/WbemScripting_TLB.pas for that WMI unit for Delphi 7 if you don't want to create it yourself...

The method you've chosen might or might not work but it sure does violate the rules of decent programming by just viewing the contents of a fixed memory address. On some systems, the BIOS information might not even be at that location to begin with. Especially on WinXP which does NOT allow those kinds of hacks...
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

mehdi_mAuthor Commented:
Dear Workshop_Alex

I tried it. but the result of function is just one space (Result := ' ')

Could you help me why?
0
Wim ten BrinkSelf-employed developerCommented:
Weird. Maybe that really is the serial number of the BIOS. Do you have any way to check the BIOS number in some other way?
0
Wim ten BrinkSelf-employed developerCommented:
I tried the code on my system at work, using Delphi 5. It could be that this makes a difference. I've created a VBScript version of the query which looks like this:

'----------------------<Start>----------------------
Dim refWMIService
Dim colBIOS
Dim refItem
Set refWMIService = GetObject( "winMgmts:" )
set colBIOS = refWMIService.ExecQuery( "select SerialNumber from Win32_BIOS" )
for each refItem in colBIOS
  WScript.echo "Serial number: " & refItem.SerialNumber
Next
'----------------------<Stop>----------------------

The above code should display the right serial number. If this too is a space then I think your BIOS serial number is indeed a space. On my system, I get a value of SerialNumber = SYS-1234567890 which is a pretty typical number too.
You could replace "Win32_BIOS" in the query with "CIM_BIOSElement" but I just get the same value. So, thinking there might be a flaw in this, I just used 'Computer Management' to check the serial number there. But on W2K I don't see any serial number there.

If you want to use some BIOS value as part of some copy-security, maybe you should use SMBIOSBIOSVersion or BIOSVersion (requires XP) instead of the SerialNumber.
0
mehdi_mAuthor Commented:
Thank you very much, you may right that my SerialNumber is ' '.
Can you help me on how to check it in 'Computer Management' ?

As a matter of fact I just need an unique code. when I use SMBIOSBIOSVersion or BIOSVersion in your previous delphi code, it raised an exception EVariantTypeCastError with message 'Could not convert variant of type (Dispatch) into type (String)'.
and when I use "CIM_BIOSElement" istead of "Win32_BIOS" it raised exception EOleException with message 'Invalid query'.

It would be very good for me to do the operation in Delphi instead of VBScript. or is there anyway to run VBScript in Delphi? I don't know.

0
mehdi_mAuthor Commented:
Thank you very much, you may right that my SerialNumber is ' '.
Can you help me on how to check it in 'Computer Management' ?
Is this value: "Coputer Managment\Servises and Applications\WMI Control\Properties\Root\CIMV2\ms_409" my serial number?

As a matter of fact I just need an unique code. when I use SMBIOSBIOSVersion or BIOSVersion in your previous delphi code, it raised an exception EVariantTypeCastError with message 'Could not convert variant of type (Dispatch) into type (String)'.
and when I use "CIM_BIOSElement" istead of "Win32_BIOS" it raised exception EOleException with message 'Invalid query'.

It would be very good for me to do the operation in Delphi instead of VBScript. or is there anyway to run VBScript in Delphi? I don't know.
0
mehdi_mAuthor Commented:
:) excuse me of twise sending . please read the second one (11/05/2004 02:48AM )
0
Wim ten BrinkSelf-employed developerCommented:
Well, the VBScript example is just a test to see what it would return. The Delphi WMI code I posted just does the same. I just added the script so you could check if the error is related to Delphi or not.

I've searched in my own Computer management for the BIOS serial number and didn't find it. Apparantly MS doesn't consider it important enough. I can't access the branch you've mentioned either, except through some WMI enumeration tool I've once written. Apparantly "root\CIMV2\ms_409" is NOT where the serial number is stored.

But if you want to get the whole BIOS information just for an unique value, you could use this code:

function SerialNumber: string;
const
  sQuery = 'select SerialNumber from Win32_BIOS';
var
  Item: SWbemObject;
  NumProp: LongWord;
  ObjectSet: ISWbemObjectSet;
  OleProperty: OleVariant;
begin
  ObjectSet := CoSWbemLocator.Create.ConnectServer( '', 'root\cimv2', '', '', '', '', 0, nil ).ExecQuery( sQuery, 'WQL', wbemFlagBidirectional, nil );
  if Succeeded( ( ObjectSet._NewEnum as IEnumVariant ).Next( 1, OleProperty, NumProp ) ) and ( NumProp > 0 ) and Succeeded( IDispatch( OleProperty ).QueryInterface( SWBemObject, Item ) ) then begin
    Result := Item.Path_.RelPath;
  end
  else begin
    Result := '<Unknown>';
  end;
end;

In this case it returns the whole path for the BIOS information. On my system, this path is:
> Win32_BIOS.Name="Default System BIOS",SoftwareElementID="Default System BIOS",SoftwareElementState=3,TargetOperatingSystem=0,Version="Award Modular BIOS v6.0"
Not too unique, though...

Or use:

function SerialNumber: string;
const
  sQuery = 'select SerialNumber from Win32_BIOS';
var
  Item: SWbemObject;
  NumProp: LongWord;
  ObjectSet: ISWbemObjectSet;
  OleProperty: OleVariant;
begin
  ObjectSet := CoSWbemLocator.Create.ConnectServer( '', 'root\cimv2', '', '', '', '', 0, nil ).ExecQuery( sQuery, 'WQL', wbemFlagBidirectional, nil );
  if Succeeded( ( ObjectSet._NewEnum as IEnumVariant ).Next( 1, OleProperty, NumProp ) ) and ( NumProp > 0 ) and Succeeded( IDispatch( OleProperty ).QueryInterface( SWBemObject, Item ) ) then begin
    Result := Item.GetObjectText_(0);
  end
  else begin
    Result := '<Unknown>';
  end;
end;

In which case you get:
------------------------------------------------------------------
instance of Win32_BIOS
{
      Name = "Default System BIOS";
      SerialNumber = "SYS-1234567890";
      SoftwareElementID = "Default System BIOS";
      SoftwareElementState = 3;
      TargetOperatingSystem = 0;
      Version = "Award Modular BIOS v6.0";
};
------------------------------------------------------------------

There could also be a problem with your WMI version, though. It's a bit version-dependant and strongly related to the Internet Explorer version you use and the Windows version you use. And the hardware might have it's effects too. It's sometimes just a bit of trial-and-error. It could also be an access rights problem, with the administrator denying some users access to WMI, but that's unlikely.

I'm not sure why you get the 'Could not convert variant of type (Dispatch) into type (String)' message unless you forget to typecast the SerialNumber property to string by using "VarToStr( Item.Properties_.Item( 'SerialNumber', 0 ) );". The VarToStr is very important here.

But try to use the "Result := Item.GetObjectText_(0);" solution I posted above and tell me what it's result is. That might help.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mehdi_mAuthor Commented:
Dear Alex

Sorry to answer you so late, and thank you for your help. 'm now sure that my BIOS SerialNumber is just a space. and your two above codes worked well.

thank you.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.