Lazarus

Programming => Operating Systems => Windows => Topic started by: vfclists on May 06, 2014, 05:27:24 pm

Title: Does FreePascal have a WMI Query library?
Post by: vfclists on May 06, 2014, 05:27:24 pm
Does FreePascal have a WMI Query , Windows Management instrumentation library?
Title: Re: Does FreePascal have a WMI Query library?
Post by: taazz on May 06, 2014, 05:41:07 pm
As far as I know there isn't any wmi specific lirary and I don't think it is needed. Use this http://code.google.com/p/wmi-delphi-code-creator/ (http://code.google.com/p/wmi-delphi-code-creator/) download binaries from http://theroadtodelphi.wordpress.com/wmi-delphi-code-creator/ (http://theroadtodelphi.wordpress.com/wmi-delphi-code-creator/)
Title: Re: Does FreePascal have a WMI Query library?
Post by: Jurassic Pork on July 29, 2015, 12:37:49 am
Hello,
i have made a function to get System Infos with WMI request (wmi only in Windows)  :
Code: [Select]
Function GetWMIInfo(const WMIClass: string ; const WMIProperty:tstringList;
                     const Condition: string = ''):tlist;

WMIClass : Class in which to find infos   example : Win32_NetworkAdapter
WMIProperty : a list of properties to get   example : Name,MACAddress
Condition : a Condition to limit results example : WHERE NETENABLED = TRUE

The result is a list of Properties list.

Usage example to get all the active network cards and their MACAddresses :
Code: [Select]
procedure TForm1.Button3Click(Sender: TObject);
var ResultatWMI : TList;
    Infos : TStringList;
  i,j       : Integer;
begin
  Memo1.Clear;
  Infos := TstringList.Create;
  // Prepare Infos to get  in a Name-Value StringList
  Infos.CommaText:='Name=,MACAddress=';
  ResultatWMI := GetWMIInfo('Win32_NetworkAdapter',Infos,'WHERE NETENABLED = TRUE');
   for i := 0 to ResultatWMI.Count-1 do
    begin
     Memo1.Lines.add('================================================');
     for j := 0 to Infos.Count-1 do
         begin
         Memo1.Lines.add(TstringList(ResultatWMI[i]).Names[j]+' : '+
         TstringList (ResultatWMI[i]).ValueFromIndex[j]);
         end;
    end;
  // Nettoyage   - Cleaning
    for i := 0 to ResultatWMI.Count-1 do
         begin
           TstringList(ResultatWMI[i]).Free;
         end;
    Infos.Free;
end;
Function is in the utilwmi unit  ( attachment )

hope help some people with this. If you see errors or optimizations in source code , say it to me.
To be continued if useful.

Friendly, J.P
Title: Re: Does FreePascal have a WMI Query library?
Post by: Jurassic Pork on January 03, 2016, 01:42:53 am
hello,
a new version of the unit has been released. Thanks to Molly for the improvements : 

Quote
// 0.1  Jurassic Pork Juillet 2015
// 0.2  Molly  Janvier 2016 : improvement : fpc 3.0 compatibility + usage of  TFPObjectList
 
// Changes 2016-jan-02 (Mol)
// - updated/corrected comments
// - Introduction of variable nrValue.
// - Generic solution for variable nr, using nrValue (inc. pointer assignment)
// - re-introduction of calling ShowMessage() when exception occurs (code only
//   active when USE_DIALOG is defined) + reorganized defines


example of use :

Code: Pascal  [Select][+][-]
  1. uses contnrs,utilwmi,
  2. ...
  3. procedure TForm1.Button1Click(Sender: TObject);
  4. var
  5.   WMIResult         : TFPObjectList;
  6.   i                 : Integer;
  7.   PropNamesIndex    : Integer;
  8.   PropNames         : Array[0..2] of String = ( 'Name','MACAddress','NetConnectionId' );
  9. begin
  10.   WMIResult := GetWMIInfo('Win32_NetworkAdapter', PropNames,'WHERE NETENABLED = TRUE');
  11.   for i := 0 to Pred(WMIResult.Count) do
  12.   begin
  13.     Memo1.Append('================================================');
  14.     for PropNamesIndex := Low(PropNames) to High(PropNames) do
  15.     begin
  16.       Memo1.Append(TStringList(WMIResult[i]).Names[PropNamesIndex] + ' : ' +
  17.               TStringList(WMIResult[i]).ValueFromIndex[PropNamesIndex]);
  18.     end;
  19.   end;
  20.   // Clean up
  21.   WMIResult.Free;
  22. end;                    
  23.  

Edit : oops , sorry  :-[   in the example , something was wrong (Win32_NetwokAdapter to check exception handling). Now it is OK with Win32_NetworkAdapter.
Friendly J.P
Title: Re: Does FreePascal have a WMI Query library?
Post by: chineselzh on March 18, 2016, 01:52:20 pm
thank you very much!

hello,
a new version of the unit has been released. Thanks to Molly for the improvements : 

Quote
// 0.1  Jurassic Pork Juillet 2015
// 0.2  Molly  Janvier 2016 : improvement : fpc 3.0 compatibility + usage of  TFPObjectList
 
// Changes 2016-jan-02 (Mol)
// - updated/corrected comments
// - Introduction of variable nrValue.
// - Generic solution for variable nr, using nrValue (inc. pointer assignment)
// - re-introduction of calling ShowMessage() when exception occurs (code only
//   active when USE_DIALOG is defined) + reorganized defines


example of use :

Code: Pascal  [Select][+][-]
  1. uses contnrs,utilwmi,
  2. ...
  3. procedure TForm1.Button1Click(Sender: TObject);
  4. var
  5.   WMIResult         : TFPObjectList;
  6.   i                 : Integer;
  7.   PropNamesIndex    : Integer;
  8.   PropNames         : Array[0..2] of String = ( 'Name','MACAddress','NetConnectionId' );
  9. begin
  10.   WMIResult := GetWMIInfo('Win32_NetworkAdapter', PropNames,'WHERE NETENABLED = TRUE');
  11.   for i := 0 to Pred(WMIResult.Count) do
  12.   begin
  13.     Memo1.Append('================================================');
  14.     for PropNamesIndex := Low(PropNames) to High(PropNames) do
  15.     begin
  16.       Memo1.Append(TStringList(WMIResult[i]).Names[PropNamesIndex] + ' : ' +
  17.               TStringList(WMIResult[i]).ValueFromIndex[PropNamesIndex]);
  18.     end;
  19.   end;
  20.   // Clean up
  21.   WMIResult.Free;
  22. end;                    
  23.  

Edit : oops , sorry  :-[   in the example , something was wrong (Win32_NetwokAdapter to check exception handling). Now it is OK with Win32_NetworkAdapter.
Friendly J.P
Title: Re: Does FreePascal have a WMI Query library?
Post by: christensen on June 10, 2016, 06:13:49 pm
Hi,

I've been working on a project for long time which is using this WMI library, now i'm trying to reinstall the system after my HDD fail and lost everything.
So from backup of my source code i'm trying to recover as much i can.

When i'm trying to compile i got this error on WMI lib:

Quote
utilwmi.pas(47,37) Error: Call by var for arg no. 3 has to match exactly: Got "Pointer" expected "LongWord"


with other warning as well:

Quote
Messages, Warnings: 1
Exit code 1, Errors: 1, Warnings: 5
utilwmi.pas(41,15) Warning: Implicit string type conversion from "AnsiString" to "WideString"
utilwmi.pas(43,15) Warning: Implicit string type conversion from "AnsiString" to "WideString"
utilwmi.pas(47,37) Error: Call by var for arg no. 3 has to match exactly: Got "Pointer" expected "LongWord"
utilwmi.pas(53,22) Warning: Implicit string type conversion from "AnsiString" to "WideString"
utilwmi.pas(56,36) Warning: Symbol "SysToUTF8" is deprecated: "Use the function in LazUTF8 unit"
utilwmi.pas(61,67) Warning: Implicit string type conversion with potential data loss from "WideString" to "AnsiString"
Title: Re: Does FreePascal have a WMI Query library?
Post by: Dimitrios Chr. Ioannidis on June 10, 2016, 09:29:33 pm
Hi,

Does FreePascal have a WMI Query , Windows Management instrumentation library?

 I played a little with this WMI Delphi Code Creator (http://octopus.software/index.php/open-source/wmi-delphi-code-creator) ( don't let the name misguide you, it works with fpc also, or at least it worked  ) in the past. You could look at it if it's suitable for you.

[EDIT] Ooops, I din't see that taazz already mention it. Sorry...

regards,
Title: Re: Does FreePascal have a WMI Query library?
Post by: molly on June 11, 2016, 05:48:15 am
utilwmi.pas(47,37) Error: Call by var for arg no. 3 has to match exactly: Got "Pointer" expected "LongWord"

with other warning as well:
Seems you upgraded your FPC version as well ?

Try version 0.2 of wmiutil unit. In theory that version should be able to support fpc 3.0.0 (as well as previous versions).
Title: Re: Does FreePascal have a WMI Query library?
Post by: christensen on June 14, 2016, 10:36:15 pm
Yes, i've upgrade everything.


I've tried v2 and now i got other error:
Quote
main.pas(239,50) Error: Incompatible type for arg no. 2: Got "TStringList", expected "{Open} Array Of AnsiString"

in this section of code:

Code: Pascal  [Select][+][-]
  1.  // read bios sn
  2.     Infos := TstringList.Create;
  3.         Infos.CommaText:='SerialNumber=';
  4.  
  5.      ResultatWMI := GetWMIInfo('Win32_BIOS',Infos);
  6.       Result:=TstringList (ResultatWMI[f]).ValueFromIndex[j];
  7.  
  8.       Infos.Free;      
Title: Re: Does FreePascal have a WMI Query library?
Post by: molly on June 14, 2016, 11:22:21 pm
I've tried v2 and now i got other error:
Quote
main.pas(239,50) Error: Incompatible type for arg no. 2: Got "TStringList", expected "{Open} Array Of AnsiString"
The argument type was changed from a stringlist into an open array of strings, hence the error.

Code: Pascal  [Select][+][-]
  1. program example;
  2.  
  3. {$MODE OBJFPC}{$H+}
  4.  
  5. uses
  6.   classes,
  7.   utilwmi2,
  8.   contnrs;
  9.  
  10. procedure BIOS;
  11. var
  12.   WMIResult         : TFPObjectList;
  13.   f,j               : integer;
  14.   retVal            : String;
  15. begin
  16.   WMIResult := GetWMIInfo('Win32_BIOS', ['SerialNumber', 'Manufacturer']);
  17.  
  18.   for f := 0 to Pred(WMIResult.Count) do
  19.   begin
  20.     j := 0;  // first entry = SerialNumber
  21.     retVal := TStringList(WMIResult[f]).ValueFromIndex[j];
  22.     WriteLn(retVal);
  23.  
  24.     j := 1;  // second entry = Manufacturer
  25.     retVal := TStringList(WMIResult[f]).ValueFromIndex[j];
  26.     WriteLn(retVal);
  27.   end;
  28.  
  29.   WMIResult.Free;
  30. end;
  31.  
  32. begin
  33.   BIOS;
  34. end.
  35.  
Title: Re: Does FreePascal have a WMI Query library?
Post by: jma_sp on December 19, 2016, 02:46:09 pm
Thanks Jurasic Pork and Molly, it works!!! What license uses it?

I have been trying with tprocess and wmic but it stops and nothing returns. With this all ok. :)

There is a lot of information that can be returned, by example:


wmic -?

Returns a list of parameters... if it get BIOS we change as Win32_BIOS, if CPU Win32_CPU,

If Desktop Win32_Desktop,............





For people searching for info in BIOS.....thereis also a project:

https://github.com/RRUZ/tsmbios 

It can be compiled easily with Lazarus.
Title: Re: Does FreePascal have a WMI Query library?
Post by: molly on December 19, 2016, 03:04:35 pm
Thanks Jurasic Pork and Molly, it works!!! What license uses it?
I have no idea. afaik It's Jurasic Pork's project so whatever J.P. says/tells goes as far as i am concerned.

I'm just glad that you liked it and/or the project was useful for you.

Thanks for the link to tsmbios as it is a very nice project. I already stumbled upon it a while ago but forgot about it already  :-[
Title: Re: Does FreePascal have a WMI Query library?
Post by: ASerge on December 19, 2016, 04:10:32 pm
Thanks Jurasic Pork and Molly, it works!!!
I'm new here, but I think the design
Code: Pascal  [Select][+][-]
  1. try
  2. ...
  3. except
  4.   on e: Exception do raise;
  5. end;
is not very good. And with this approach you need to free the memory occupied by the Result. I.e.
Code: Pascal  [Select][+][-]
  1. except
  2.   Result.Free;
  3.   raise;
  4. end;
Title: Re: Does FreePascal have a WMI Query library?
Post by: molly on December 19, 2016, 04:32:17 pm
@ASerge:
You are correct.

I would choose another solution though, e.g. the way exceptions are intended to be used.

The example codes seen can sometimes be wrong in that regards, and actually should look more like:
Code: Pascal  [Select][+][-]
  1. begin
  2.   try
  3.     WMIResult := GetWMIInfo('Win32_BIOS', ['SerialNumber', 'Manufacturer']);
  4.     for i := 0 to Pred(WMIResult.Count) do
  5.     begin
  6.       ..
  7.     end;
  8.   finally
  9.     WMIResult.Free;
  10.   end;
  11. end;
  12.  

Can you notice the difference ?

Also note that v3 was released here (http://forum.lazarus.freepascal.org/index.php/topic,34743.msg228859.html), which adds support for WMI array return values.
Title: Re: Does FreePascal have a WMI Query library?
Post by: Jurassic Pork on December 19, 2016, 05:24:31 pm
hello,
here is now the official version of utilwmi in attachment with a MIT Licence :
Quote
(**********************************************************************************
 Copyright (c) 2016 Jurassic Pork - Molly

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in the
Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
***********************************************************************************)
unit Utilwmi;
 
// 0.1  Jurassic Pork Juillet 2015
// 0.2  Molly  Janvier 2016 : improvement : fpc 3.0 compatibility + usage of  TFPObjectList
 
// Changes 2016-jan-02 (Mol)
// - updated/corrected comments
// - Introduction of variable nrValue.
// - Generic solution for variable nr, using nrValue (inc. pointer assignment)
// - re-introduction of calling ShowMessage() when exception occurs (code only
//   active when USE_DIALOG is defined) + reorganized defines
 
// 0.3  Molly  November 2016 : improvement : support for variant arrays
// Changes 2016-nov-11 (Mol)
// - Add support for variant arrays   

to test the support for variant arrays  try :
Code: Pascal  [Select][+][-]
  1.  WMIResult := GetWMIInfo('Win32_BIOS', ['BIOSVersion', 'Manufacturer']);  

BIOSVersion wmi result is a variant array.

Friendly, J.P

Title: Re: Does FreePascal have a WMI Query library?
Post by: jma_sp on December 20, 2016, 09:49:06 am
Thanks,

It´s very useful because WMI let´s obtain a lot of information. By example it can return the total amount of physical memory: . This one is a very frequent question in Internet :)

GetWMIInfo('Win32_COMPUTERSYSTEM', ['TotalPhysicalMemory']);

Saludos.
Title: Re: Does FreePascal have a WMI Query library?
Post by: ASerge on December 20, 2016, 04:17:51 pm
Can you notice the difference ?
Of course. Try must be used AFTER the resource allocation. But to write code with errors based on incorrect application is also wrong.
Title: Re: Does FreePascal have a WMI Query library?
Post by: molly on December 21, 2016, 04:37:29 pm
@ASerge:
You are correct in that code can become a bit awkward when attempting to handle such exception correctly.

But what would you propose then ?

I'm uncomfortable with the solution as shown by you earlier, because it is usually end-user responsibility to act on exceptions.

In addition to that. It might be that only one 'entry' went wrong while all other entries are (still) valid. It would be unwise to clear the whole objectlist for that ?

There probably is/was a good reason that Jurassic Pork left things open as it currently is.

Note that J.P. 's unit is only a small helper routine that offer you quick WMI access. A better choice would probably be to use an implementation based on something like a dataset.

I'm all for improving things, that is why i contributed. In case you have something to offer/contribute then please feel free to contact J.P. and make an offer. He's a very reasonable person (and after all, it is his idea/project. e.g. my vote doesn't really count).
Title: Re: Does FreePascal have a WMI Query library?
Post by: ASerge on December 22, 2016, 03:51:25 pm
@ASerge:
I'm uncomfortable with the solution as shown by you earlier, because it is usually end-user responsibility to act on exceptions.
In addition to that. It might be that only one 'entry' went wrong while all other entries are (still) valid. It would be unwise to clear the whole objectlist for that ?
Why not? Once the memory is allocated inside the function, when internal errors - it is must to clean.
In my opinion it is more convenient when cleaning the one, who allocate. But if we delegate to function allocate only, I prefer this approach:
Code: Pascal  [Select][+][-]
  1. function ProducedSomeData(const ByParams: TInputParamsClass;
  2.   out DataHolder: TDataHolderClass): Boolean;
  3. //...
  4. begin
  5.   try
  6.     DataHolder := TDataHolderClass.Create({...});
  7.     //...
  8.     Result := True;
  9.   except
  10.     DataHolder.Free; // Escape memory leak
  11.     raise; // End-user responsibility to act on exceptions
  12.     // { Or handle this on their own} DataHolder := nil; Result := False;
  13.   end;
  14. end;
  15.  
  16. procedure UseSomeData;
  17. //...
  18. begin
  19.   if ProducedSomeData(InputParams, DataHolder) then
  20.   try
  21.     //...
  22.   finally
  23.     DataHolder.Free;
  24.   end;
  25. end;                    
Title: Re: Does FreePascal have a WMI Query library?
Post by: vonskie on August 30, 2017, 05:07:57 pm
I have this code in vbscript

Sub networkcard
   
   Set colItems = objWMIService.ExecQuery _
   ("Select * From Win32_NetworkAdapterConfiguration Where IPEnabled = True")
   
   For Each objItem In colItems
      
      If InStr(objItem.Description,"WAN")=0 Then
         
         
         report=report  & "Description: " & objItem.Description &vbCrLf
         report=report  & "IP Address: " &vbCrLf
         
         
         For Each strAddress In objItem.IPAddress
            report=report  & strAddress & vbCrLf
         Next
         
      End If
      
   Next
   
End Sub

I have gotten this far but I do not know how to do the "strAddress In objItem.IPAddress" using the wmi call please help!

PropNamesNetworkAdapterConfiguration: array[0..0] of string = ('Description');

WMIResult := GetWMIInfo('Win32_NetworkAdapterConfiguration',
        PropNamesNetworkAdapterConfiguration, 'Where IPEnabled = True');
      for i := 0 to Pred(WMIResult.Count) do
      begin
        REPORT := report + '================================================' + #13#10;
        for PropNamesIndex := Low(PropNamesNetworkAdapterConfiguration) to High(PropNamesNetworkAdapterConfiguration) do
        begin
          REPORT := report + TStringList(WMIResult).Names[PropNamesIndex] +
            ' : ' + TStringList(WMIResult).ValueFromIndex[PropNamesIndex] + #13#10;
        end;
      end;

      // Clean up
      WMIResult.Free;     

Please help!
Title: Re: Does FreePascal have a WMI Query library?
Post by: molly on August 30, 2017, 05:42:48 pm
Please don't ignore the warnings that the compiler throws at you as they give you a clue.

Not sure if this is what you meant to do:
Code: Pascal  [Select][+][-]
  1. program example_nwadaptercfg;
  2.  
  3. {$MODE OBJFPC}{$H+}
  4.  
  5. uses
  6.   classes, contnrs, utilwmi;
  7.  
  8. procedure DoIt;
  9. var
  10.   WMIResult         : TFPObjectList;
  11.   i                 : Integer;
  12.   PropNamesIndex    : Integer;
  13.   PropNames         : Array[0..1] of String = ( 'Description', 'IPAddress' );
  14. begin
  15.   WMIResult := GetWMIInfo('Win32_NetworkAdapterConfiguration', PropNames, 'Where IPEnabled = True');
  16.  
  17.   for i := 0 to Pred(WMIResult.Count) do
  18.   begin
  19.     WriteLn('================================================');
  20.  
  21.     for PropNamesIndex := Low(PropNames) to High(PropNames) do
  22.     begin
  23.       WriteLn(TStringList(WMIResult[i]).Names[PropNamesIndex] + ' : ' +
  24.               TStringList(WMIResult[i]).ValueFromIndex[PropNamesIndex]);
  25.     end;
  26.   end;
  27.   // Clean up
  28.   WMIResult.Free;
  29. end;
  30.  
  31. begin
  32.   DoIt;
  33. end.
  34.  
Title: Re: Does FreePascal have a WMI Query library?
Post by: Thaddy on August 30, 2017, 07:17:00 pm
Since when can you hardcast to a TStringlist? If that works it is by accident.... Tstringlist is not an array..... it is a class.
Title: Re: Does FreePascal have a WMI Query library?
Post by: rvk on August 30, 2017, 07:35:05 pm
Since when can you hardcast to a TStringlist? If that works it is by accident.... Tstringlist is not an array..... it is a class.
Have you checked out what WMIResult := GetWMIInfo() really does before posting that comment ??

It creates a TFPObjectList of multiple TStringLists so the hardcast is perfectly legit.
(i.e. WMIResult[i] is a TStringList of itself)
Title: Re: Does FreePascal have a WMI Query library?
Post by: molly on August 30, 2017, 08:14:04 pm
Indeed as rvk wrote, the objectlist contains stringlists.

There is much room for further improvements...
Title: Re: Does FreePascal have a WMI Query library?
Post by: molly on August 30, 2017, 08:54:28 pm
Sorry ASerge, i seem to have missed your latest response  :-[

Why not? Once the memory is allocated inside the function, when internal errors - it is must to clean.
In my opinion it is more convenient when cleaning the one, who allocate. But if we delegate to function allocate only, I prefer this approach:
Sure, but even better would be to have a separate wmi class that does everything internally (an act correctly when something goes wrong, e.g. not bother the user with it).

As said, there is much room for improvements. If you have something to offer then offer it to J.P. Because of the backwards compatibility with fpc 2.6.4 i have not given it very much additional thoughts (generics, operator overloading etc.).

There is a wmi dataset class floating around for Delphi. That could perhaps work as a good alternative for my clumsy coding ?
Title: Re: Does FreePascal have a WMI Query library?
Post by: 9ep2rz on December 24, 2017, 01:56:25 pm
Hi Jurassic Port,

Using utilwmi unit I can get serial number of hard drives but I want to get from a specific drive, because I have 2 hard drive in my computer.

Here is the code but I need to pass drive letter (D, F, H) and want to get physical serial number:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2.   var
  3.     WMIResult         : TFPObjectList;
  4.     WMIResult2         : TFPObjectList;
  5.     f              : integer;
  6.     retVal            : String;
  7. begin
  8.  WMIResult := GetWMIInfo('Win32_DiskDrive', ['DeviceID', 'SerialNumber']);
  9.   for f := 0 to Pred(WMIResult.Count) do
  10.   begin
  11.     retVal := TStringList(WMIResult[f]).ValueFromIndex[0] + ' : ' + TStringList(WMIResult[f]).ValueFromIndex[1];
  12.     Memo1.Lines.add(Retval);
  13.   end;
  14.  
  15.   WMIResult.Free;
  16. end;
  17.  

Thanks,
Title: Re: Does FreePascal have a WMI Query library?
Post by: molly on December 25, 2017, 12:34:42 am
Here is the code but I need to pass drive letter (D, F, H) and want to get physical serial number:
Not possible to accomplish with using utilWMI.

Use your own instance of wmi and associate the proper objects to each other.  Hint: you need to parse things the other way around and in the end match your drive-letter. (DiskDrive -> Partition -> LogicalDisk -> DriveLetter -> DiskDrive.SerialNumber)
Title: Re: Does FreePascal have a WMI Query library?
Post by: Jurassic Pork on December 25, 2017, 07:38:36 am
hello,
utilwmi can only do Select WQL  Request.
Not possible to accomplish with using utilWMI.
Use your own instance of wmi and associate the proper objects to each other.  Hint: you need to parse things the other way around and in the end match your drive-letter. (DiskDrive -> Partition -> LogicalDisk -> DriveLetter -> DiskDrive.SerialNumber)
To do this , you must use Associators of WQL Request.
here is an example  :
Code: Pascal  [Select][+][-]
  1. // uses  Variants,ActiveX, ComObj        ;
  2. procedure TForm1.Button1Click(Sender: TObject);
  3. const
  4.   wbemFlagForwardOnly = $00000020;
  5. var
  6.   FSWbemLocator     : OLEVariant;
  7.   FWMIService       : OLEVariant;
  8.   wmiDiskDrives     : OLEVariant;
  9.   wmiDiskPartitions : OLEVariant;
  10.   wmiLogicalDisks   : OLEVariant;
  11.   wmiDiskDrive      : OLEVariant;
  12.   wmiDiskPartition  : OLEVariant;
  13.   wmiLogicalDisk    : OLEVariant;
  14.   oEnum             : IEnumvariant;
  15.   oEnum2            : IEnumvariant;
  16.   oEnum3            : IEnumvariant;
  17.   iValue            : LongWord;
  18.   DeviceID          : string;
  19.   Partitions        : string;
  20.   SerNum,SerNumByDriveLetter  : string;
  21. begin;
  22.   FSWbemLocator   := CreateOleObject('WbemScripting.SWbemLocator');
  23.   FSWbemLocator.Security_.privileges.addasstring('sedebugprivilege', true);
  24.   FWMIService   := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
  25.   FWMIService.Security_.ImpersonationLevel := 3;
  26.   //Get the physical disk drive
  27.   wmiDiskDrives := FWMIService.ExecQuery('SELECT Caption, DeviceID,SerialNumber FROM Win32_DiskDrive','WQL',wbemFlagForwardOnly);
  28.   oEnum         := IUnknown(wmiDiskDrives._NewEnum) as IEnumVariant;
  29.   while oEnum.Next(1, wmiDiskDrive, iValue) = 0 do
  30.   begin
  31.      SerNum := '';
  32.      Memo1.Lines.add(wmiDiskDrive.Caption);
  33.      if wmiDiskDrive.SerialNumber <> Null then
  34.      SerNum := UpperCase(String( wmiDiskDrive.SerialNumber));
  35.      Memo1.Lines.add('Serial Number : ' + SerNum  +
  36.                      '  =  ' + HexStrToStr(SerNum));
  37.  
  38.      Partitions := '';
  39.      //Use the disk drive device id to find associated partition
  40.      DeviceID:=StringReplace(String(wmiDiskDrive.DeviceID),'\','\\',[rfReplaceAll]);
  41.      wmiDiskPartitions := FWMIService.ExecQuery(
  42.      WideString('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="'+
  43.      DeviceID+'"} WHERE AssocClass = Win32_DiskDriveToDiskPartition'),
  44.      'WQL',wbemFlagForwardOnly);
  45.      oEnum2          := IUnknown(wmiDiskPartitions._NewEnum) as IEnumVariant;
  46.      while oEnum2.Next(1, wmiDiskPartition, iValue) = 0 do
  47.      begin
  48.         wmiLogicalDisks := FWMIService.ExecQuery(
  49.         WideString('ASSOCIATORS OF {Win32_DiskPartition.DeviceID="'+
  50.         String(wmiDiskPartition.DeviceID)+
  51.         '"} WHERE AssocClass = Win32_LogicalDiskToPartition'),
  52.         'WQL',wbemFlagForwardOnly);
  53.         oEnum3          := IUnknown(wmiLogicalDisks._NewEnum) as IEnumVariant;
  54.         while oEnum3.Next(1, wmiLogicalDisk, iValue) = 0 do
  55.         begin
  56.           if  (wmiLogicalDisk.DeviceID = 'C:') AND
  57.           (wmiDiskDrive.SerialNumber <> Null)  then
  58.           SerNumByDriveLetter :=   HexStrToStr(SerNum);
  59.  
  60.           Partitions := Partitions + String(wmiLogicalDisk.DeviceID)+ ' ,';
  61.           wmiLogicalDisk:=Unassigned;
  62.         end;
  63.        wmiDiskPartition:=Unassigned;
  64.      end;
  65.     wmiDiskDrive:=Unassigned;
  66.     Memo1.Lines.Append('Partitions : ' + Partitions);
  67.     Memo1.Lines.add('=======================================');
  68.   end;
  69.     Memo1.Append('Disk Serial Number for C: is ' + SerNumByDriveLetter );
  70. end;  
The function HexStrToStr is a code of ASerge :
Code: Pascal  [Select][+][-]
  1. uses Classes;
  2.  
  3. function HexStrToStr(const HexStr: string): string;
  4. var
  5.   ResultLen: Integer;
  6. begin
  7.   ResultLen := Length(HexStr) div 2;
  8.   SetLength(Result, ResultLen);
  9.   if ResultLen > 0 then
  10.     SetLength(Result, HexToBin(Pointer(HexStr), Pointer(Result), ResultLen));
  11. end;

Friendly J.P
Title: Re: Does FreePascal have a WMI Query library?
Post by: 9ep2rz on December 25, 2017, 11:01:24 am
Thanks Jurassi Pork,

It really helped me.
TinyPortal © 2005-2018