WMI with delphi - delphi

I've been working on a project which would read the temperature of the CPU.
Unfortunately I'm getting a conversion error. The whole thing compiles without a problem. But when I actually try to execute the code it gives me this error:
"Could not convert variant of type (Dispatch) into type (String)"
I'm not actually trying to get the Temp, On this bit I'm just looking if the way this is coded works. Temp part is going to be added later on...
The particular code:
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, ExtCtrls, jpeg, WbemScripting_TLB, StdCtrls;
type
TForm3 = class(TForm)
MainMenu1: TMainMenu;
F1: TMenuItem;
Quit1: TMenuItem;
Help1: TMenuItem;
Programms1: TMenuItem;
CalCulator1: TMenuItem;
Browser1: TMenuItem;
emperature1: TMenuItem;
WallPad1: TMenuItem;
MediaPlayer1: TMenuItem;
Image1: TImage;
Image2: TImage;
Load1: TMenuItem;
Background1: TMenuItem;
Label1: TLabel;
Button1: TButton;
procedure CalCulator1Click(Sender: TObject);
procedure Image1DblClick(Sender: TObject);
procedure Browser1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure MediaPlayer1Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
WMIServices: ISWbemServices;
Root : ISWbemObjectSet;
Item : Variant;
I : Integer;
implementation
uses Unit4, Unit2, Unit5;
{$R *.dfm}
procedure TForm3.Browser1Click(Sender: TObject);
begin
Form2.Show;
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
WMIServices := CoSWbemLocator.Create.ConnectServer('.', 'root\cimv2','', '', '', '', 0, nil);
Root := WMIServices.ExecQuery('Select DeviceID FROM Win32_TemperatureProbe','WQL', 0, nil);
Label1.caption := VarToStr(Root)
end;
procedure TForm3.CalCulator1Click(Sender: TObject);
begin
form4.show;
end;
procedure TForm3.FormCreate(Sender: TObject);
begin
image1.bringtofront
end;
procedure TForm3.Image1DblClick(Sender: TObject);
begin
Form4.show;
end;
procedure TForm3.MediaPlayer1Click(Sender: TObject);
begin
form5.show;
end;
end.
I'm assuming the solution is going to be quite simple, yet I can't see it...
The error is created on this bit
Label1.caption := VarToStr(Root)

Before continuing on this path maybe you should read the documentation Win32_TemperatureProbe class.
In the header you can read:
"Most of the information That the Win32_TemperatureProbe WMI class Provides you eat from SMBIOS. Real-time readings for the CurrentReading property can not be Retrieved from SMBIOS tables. For this reason, current implementations of WMI do not populate the CurrentReading property. The CurrentReading property's Presence is reserved for future use."
if you want to use WMI correctly, you can find much information on the website of Rodrigo Ruz or on my website including samples and specific components to WMI (GLibWMI on Sourceforge).
There is an interesting project (opensource) in http://openhardwaremonitor.org to access hardware properties (including the ones you need). Check it out.
A greeting.

Related

For loop continue going after reaching goal. Delphi

This issue appears only with numbers, bigger, then 12 including.
Those two pictures captured in one time. How it is even possible?
For loop must go from 0 to 12-1=11, doesn't it?
Nevertheless, when I use while loop instead, it works fine.
Is it my fault or Delphi's?
P.S. Code down bellow.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids;
type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
Button1: TButton;
Edit1: TEdit;
Button2: TButton;
Label1: TLabel;
Button3: TButton;
Label2: TLabel;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure StringGrid1KeyPress(Sender: TObject; var Key: Char);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
n:Integer;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); //Button, that sets array length
var
i, index:Integer;
begin
val(Edit1.Text, n, index);
if(index<>0) then
begin
ShowMessage('Wrong number');
Edit1.Clear();
exit;
end;
StringGrid1.ColCount:=n;
for i:=0 to n-1 do
StringGrid1.Cells[i,0]:=IntToStr(i+1);
StringGrid1.SetFocus();
end;
procedure TForm1.Button2Click(Sender: TObject); //Main button
var
i, index:Integer;
a:array[0..10] of Real;
denom, sum:Real;
begin
i:=0;
sum:=0;
denom:=-1;
//that for loop from screenshot is here
for i:=0 to n-1 do
//while i<=(n-1) do
begin
Val(StringGrid1.cells[i,1], a[i], index);
if(index<>0) then
begin
ShowMessage('Wrong number with ' + IntToStr(i+1) + ' Id');
StringGrid1.Col:=i;
StringGrid1.Row:=1;
StringGrid1.SetFocus();
exit;
end;
a[i]:=a[i]/denom;
sum:=sum+a[i];
StringGrid1.Cells[i,2]:=FloatToStrF(a[i],ffFixed,5,3);
denom:=-denom*(i+2);
//Inc(i);
end;
Label2.Caption:=FloatToStrF(sum,ffFixed,5,3);
end;
//code down bellow just allow to go to another cell by pressing Enter
procedure TForm1.StringGrid1KeyPress(Sender: TObject; var Key: Char);
begin
if (Key=#13) and (StringGrid1.Col=(n-1)) then
Button2.SetFocus()
else if (Key=#13) and (StringGrid1.Col<>(n-1)) then
StringGrid1.Col:=StringGrid1.Col+1;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
Close();
end;
end.
As to answer your question of 'how is this even possible'...
In your screen, n is 12. As pointed out by Kermation, the highest index of a is 10, so when i is 11, unless you have range checking activated, when you write to a[11] (i=11) you will overwrite something else. This is in the local variable area so it might be i, for instance, or even internal variables you can't see like the limit used for the for loop, which is calculated at the start of the loop. Once you allow this to happen, pretty much anything is possible.
Of course the exact manifestation of the problem will very from one version of the compiler to another. In one version you might get away with it. in another you won't.
Array a size was smaller, then amount of cells.

Saving record to file Error 'file access denied'

When I run my code an select the save button which i created. The record doesnt save but i get an error 'file access denied'.
my code :
The code i split into 2 units MainUnit and AddTenantUnit.
I think the problem lies within the procedure at the end of the code. If you scroll down I made it clear which procedure (TAddTenantForm.SaveButtonClick).
unit MainUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TMainForm = class(TForm)
AddTenantButton: TButton;
procedure FormCreate(Sender: TObject);
procedure AddTenantButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
TTenantRecord = record
FirstName : string[20];
LastName : string[20];
end;
var
MainForm: TMainForm;
Tenant : TTenantRecord;
TenantFile : file of TTenantRecord;
implementation
uses AddTenantUnit;
{$R *.dfm}
procedure TMainForm.AddTenantButtonClick(Sender: TObject);
begin
AddTenantForm.ShowModal;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
assignfile (TenantFile, 'Tenant.dat');
if not fileexists ('Tenant.dat')
then
begin
rewrite (TenantFile);
closefile (TenantFile)
end
{endif};
end;
end.
unit AddTenantUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, MainUnit, StdCtrls;
type
TAddTenantForm = class(TForm)
MainFormButton: TButton;
FirstNameLabel: TLabel;
FirstNameEdit: TEdit;
LastNameLabel: TLabel;
LastNameEdit: TEdit;
SaveButton: TButton;
ClearButton: TButton;
procedure SaveButtonClick(Sender: TObject);
procedure LastNameEditChange(Sender: TObject);
procedure ClearButtonClick(Sender: TObject);
procedure FirstNameEditChange(Sender: TObject);
procedure MainFormButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
AddTenantForm: TAddTenantForm;
implementation
{$R *.dfm}
procedure TAddTenantForm.MainFormButtonClick(Sender: TObject);
begin
AddTenantForm.Close;
end;
procedure TAddTenantForm.FirstNameEditChange(Sender: TObject);
begin
Tenant.FirstName := FirstNameEdit.Text;
end;
procedure TAddTenantForm.ClearButtonClick(Sender: TObject);
begin
FirstNameEdit.Clear;
LastNameEdit.Clear;
end;
procedure TAddTenantForm.LastNameEditChange(Sender: TObject);
begin
Tenant.LastName := LastNameEdit.Text;
end;
// This is where the problem lies when I run this piece of
// code. This represents the Save button being clicked.
procedure TAddTenantForm.SaveButtonClick(Sender: TObject);
begin
assignfile (TenantFile, 'Tenant.dat');
write(TenantFile, Tenant);
closefile (TenantFile);
end;
end.
You are trying to write data into not opened file.
procedure TAddTenantForm.SaveButtonClick(Sender: TObject);
begin
assignfile (TenantFile, 'Tenant.dat');
// Rewrite(TenantFile) or Reset(TenantFile) missed here
write(TenantFile, Tenant);
closefile (TenantFile);
end;

How To Use RxChar ComPort in another form

I have problem with delphi code... I have code:
MAIN FORM
unit MainForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, CPort, Menus, ComObj, StdCtrls;
type
TMainForm = class(TForm)
MainMenu1: TMainMenu;
Berkas1: TMenuItem;
Alat1: TMenuItem;
erminal1: TMenuItem;
ComPort1: TComPort;
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
procedure erminal1Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure ComPort1RxChar(Sender: TObject; Count: Integer);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
uses
ChildForm;
{$R *.dfm}
procedure TMainForm.erminal1Click(Sender: TObject);
var
ChildForm: TChildForm;
begin
ChildForm := TChildForm.Create(Application);
ChildForm.Show;
end;
procedure TMainForm.Button1Click(Sender: TObject);
begin
ComPort1.ShowSetupDialog;
end;
procedure TMainForm.ComPort1RxChar(Sender: TObject; Count: Integer);
var
ComPort: TComPort;
data: string;
begin
inherited;
ComPort := TComPort.Create(Self);
ComPort1.ReadStr(data, 5);
ChildForm.Memo1.Text := ChildForm.Memo1.Text+''+data+'';
end;
end.
CHILD FORM:
unit ChildForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComObj;
type
TChildForm = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
ChildForm: TChildForm;
implementation
uses
MainForm;
{$R *.dfm}
procedure TChildForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
procedure TChildForm.Button1Click(Sender: TObject);
begin
MainForm.ComPort1.Open;
end;
end.
I want to show data input from my device to memo in child form. I put the comport component in main form. But when I run the program, it says:
Project Data.exe raised exception class EAccessViolation with message 'Access violation at address 00466051 in module 'Data.exe'. Read of address 000002F8'. Process stopped. Use Step or Run to continue.
How can i solve the problem?
There are many problems with your code as mentioned in the comments.
To make a better implementation of your parent/child form interaction with the comport component,
do as follows:
Create a TDataModule (ex: DataModule1), put the comport component there.
Now you can access the comport component from the main form and the child form.
Add a private method to your child form:
procedure TChildForm.ComPort1RxChar(Sender: TObject; Count: Integer);
var
data: string;
begin
DataModule1.ComPort1.ReadStr(data, 5);
Self.Memo1.Text := Self.Memo1.Text+''+data+'';
end;
When you open the comport in the child form, set the comport OnRxChar event to your TChildForm.ComPort1RxChar method.
In the TChildForm.OnClose event, set the comport OnRxChar event to nil and close the comport.

Delphi sort Stringlist with two fields on first

I'm implementing a local cache to speed up DNS lookups (IP->hostname).
The cache is loaded from a CSV file("1.1.1.1host.example.com") into a TStringList with two fields:
TStringList[0] := IPAddress;
TStringList[1] := HostName;
Since I will be querying TStringList via the IP, I obliously want the first field to be sorted:
TStringList.sorted := True;
Will that take care of it so that I can find faster with
IPResolved:=TStringList[TStringList.IndexOf('1.1.1.1'),1];
?
Thanks!
Disclaimer:
This won't answer you how to sort a string list or how to load your data into a string list. It will offer you to use a hash table, which is more efficient than using a string list for your purpose (40k name, value pairs with the search by name).
Alternative:
Since you have Delphi XE2, you can use generics TDictionary class. It will contain IP address as the key and host name as the value. In the following code is shown, how to fill a dictionary and how to search for the value (host name) by a given key (IP address):
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Generics.Collections;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
IPList: TDictionary<string, string>;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
// create the TDictionary instance
IPList := TDictionary<string, string>.Create;
// here you will read your CSV file and add the items in a loop
// I've used here some of the major IP addresses for Sweden
IPList.Add('77.244.224.0', 'Insat Net AB');
IPList.Add('79.138.128.0', 'Hi3G Access AB');
IPList.Add('62.181.192.0', 'DGC Access AB');
IPList.Add('81.216.128.0', 'TDC Swerige AB');
IPList.Add('80.252.176.0', 'Phonera Networks AB');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
// release a dictionary instance
IPList.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
HostName: string;
begin
// and how to search by the IP address and get the host name if found
if IPList.TryGetValue('81.216.128.0', HostName) then
ShowMessage(HostName)
else
ShowMessage('IP address not found!');
end;
end.
Extension:
The above solution you can then simply extend to use a structure to store more than only a host name, e.g. also a host location:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Generics.Collections;
type
TIPData = record
HostName: string;
HostLocation: string;
end;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
IPList: TDictionary<string, TIPData>;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
IPData: TIPData;
begin
IPList := TDictionary<string, TIPData>.Create;
IPData.HostName := 'Broadnet Europe France';
IPData.HostLocation := 'France';
IPList.Add('78.155.128.0', IPData);
IPData.HostName := 'DNA Palvelut Oy';
IPData.HostLocation := 'Finland';
IPList.Add('62.113.160.0', IPData);
IPData.HostName := 'CD-Telematika a.s.';
IPData.HostLocation := 'Czech republic';
IPList.Add('89.203.128.0', IPData);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
IPList.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
IPData: TIPData;
begin
if IPList.TryGetValue('89.203.128.0', IPData) then
ShowMessage('Provider ' + IPData.HostName + ' from ' + IPData.HostLocation)
else
ShowMessage('IP address not found!');
end;
end.

Delphi Grid Visible Item

HI all,
I am working with Delphi 7. I am facing a problem with Grid.
My Grid having 100 rows, I am appending some more after that. For example, I am selected item is on 1oth. The grid shows 20 items on screen at a time. I scrolled the grid to downward. I reached last one. Here grid's Itemindex= 10; Please note the selected item is not showing on the visible window. When I adds the item, the grid refresh and moving to show 10th item.
I don't want to do this.
My requirement is When Adding new rows, Screen should remain same, as shown last time.
Expecting quick reply.
Thanks and Regards,
VIJESH V.NAIR
System Analyst.
Delhi, India.
Before adding an item bookmark the current row of your table that correspond to dbgrid.
Afer adding an item goto your bookmark
a sample for working with TBookmark:
(you can replace clientdataset1 with your tableName like table1)
unit MainForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, DBClient, ExtCtrls, ActnList, Grids, DBGrids,
DBCtrls;
type
TfrmMain = class(TForm)
DataSource1: TDataSource;
pnlClient: TPanel;
pnlBottom: TPanel;
btnFirst: TButton;
btnLast: TButton;
btnNext: TButton;
btnPrior: TButton;
DBGrid1: TDBGrid;
ClientDataSet1: TClientDataSet;
btnSetRecNo: TButton;
DBNavigator1: TDBNavigator;
btnGetBookmark: TButton;
btnGotoBookmark: TButton;
procedure FormCreate(Sender: TObject);
procedure btnNextClick(Sender: TObject);
procedure btnLastClick(Sender: TObject);
procedure btnSetRecNoClick(Sender: TObject);
procedure btnFirstClick(Sender: TObject);
procedure btnPriorClick(Sender: TObject);
procedure btnGetBookmarkClick(Sender: TObject);
procedure btnGotoBookmarkClick(Sender: TObject);
private
{ Private declarations }
FBookmark: TBookmark;
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.FormCreate(Sender: TObject);
begin
ClientDataSet1.LoadFromFile('C:\Employee.cds');
end;
procedure TfrmMain.btnFirstClick(Sender: TObject);
begin
ClientDataSet1.First;
end;
procedure TfrmMain.btnPriorClick(Sender: TObject);
begin
ClientDataSet1.Prior;
end;
procedure TfrmMain.btnNextClick(Sender: TObject);
begin
ClientDataSet1.Next;
end;
procedure TfrmMain.btnLastClick(Sender: TObject);
begin
ClientDataSet1.Last;
end;
procedure TfrmMain.btnSetRecNoClick(Sender: TObject);
var
Value: string;
begin
Value := '1';
if InputQuery('RecNo', 'Enter Record Number', Value) then
ClientDataSet1.RecNo := StrToInt(Value);
end;
procedure TfrmMain.btnGetBookmarkClick(Sender: TObject);
begin
if Assigned(FBookmark) then
ClientDataSet1.FreeBookmark(FBookmark);
FBookmark := ClientDataSet1.GetBookmark;
end;
procedure TfrmMain.btnGotoBookmarkClick(Sender: TObject);
begin
if Assigned(FBookmark) then
ClientDataSet1.GotoBookmark(FBookmark)
else
ShowMessage('No bookmark set!');
end;
end.

Resources