WMIで情報取得、showmessageするとエラーとなる

解決


いぼん  2011-11-23 19:31:09  No: 41256

WMIで情報取得、showmessageで結果を表示後「OK」を押すとエラーとなります。コメントにするとエラーは出ません。

フォーム不要なのでインターネットのフォームありのサンプルを参考にフォームなしで作ったのですがフォームなしにすることに問題があるのでしょうか。

delphi初心者で対処方法が分からず困っています。
よろしくお願いします。

----
・環境:WindowsXP,Delphi6

・エラーメッセージ
EAccessViolationがモジュールProject2.exeの 00005F98で発生しました。
モジュール'Project2.exe'のアドレス00405F98でアドレス57FB2C08に対する読み込み違反が起きました。

program Project2;

uses
  Windows, Messages ,Dialogs, ActiveX, WbemScripting_TLB;

var
  Locator: ISWbemLocator;
  Service: ISWbemServices;
  ObjSet: ISWbemObjectSet;
  Enum: IEnumVariant;
  Obj: OleVariant;
  Value: Cardinal;
  msg: string;

{$R *.res}

begin
  Locator := CoSWbemLocator.Create;
  Service := Locator.ConnectServer('.', 'root\cimv2', '', '', '', '', 0, nil);

  ObjSet:= Service.ExecQuery('SELECT * FROM Win32_ComputerSystemProduct',
    'WQL', wbemFlagReturnImmediately, nil);
  Enum:= (ObjSet._NewEnum) as IEnumVariant;
  while (Enum.Next(1, Obj, Value) = S_OK) do
  begin
    Obj:= IUnknown(Obj) as SWBemObject;
    msg :=  Obj.Vendor +  Obj.Name + Obj.IdentifyingNumber;

  end;

showmessage(msg);  //<--このメッセージ表示後「OK」を押すとエラーとなります。

end.


monaa  2011-11-23 21:57:26  No: 41257

D6が無いのでなんとも言えませんが
program Project1;

uses
  Windows, Messages ,Dialogs;

{$R *.res}

begin
  ShowMessage('1');
  ShowMessage('2');
  ShowMessage('3');
  MessageBox(0,'a','b',MB_OK);
end.

これが動けばShowMessageはシロだと思います。
Win32APIで動けばそれはそれでいいかもしれません。
http://msdn.microsoft.com/ja-jp/library/cc410914.aspx


D  2011-11-23 22:43:07  No: 41258

XP D6Proで。
このソースコードだと'CoInitialize は呼び出されていません。'というエラーになります。

で、beginの後にApplication.Initialize;を入れたらエラーは出なくなりました。


いぼん  2011-11-24 01:17:08  No: 41259

D様、monaa様

アドバイスありがとうございます。
Application.Initialize」からヘルプを確認してQFormユニットを追加することでエラーが出なくなりました。残念ながら私には理由は分かりません。
「Application.Initialize;」はなくてもOKでした。

初心者で手探り状態なので今後もよきアドバイスよろしくお願いします。

変更後のソース−−−−−

program  Project2;

uses
  Windows, Messages ,Dialogs, ActiveX, WbemScripting_TLB,QForms;

var
  Locator: ISWbemLocator;
  Service: ISWbemServices;
  ObjSet: ISWbemObjectSet;
  Enum: IEnumVariant;
  Obj: OleVariant;
  Value: Cardinal;
  msg: string;
//  Application: TApplication;    ←なくてもOKなのでコメント

// {$R *.res}  ←使用していないのでコメント

begin
//  Application.Initialize;  ←なくてもOKなのでコメント
  Locator := CoSWbemLocator.Create;
  Service := Locator.ConnectServer('.', 'root\cimv2', '', '', '', '', 0, nil);

  ObjSet:= Service.ExecQuery('SELECT * FROM Win32_ComputerSystemProduct',
    'WQL', wbemFlagReturnImmediately, nil);
  Enum:= (ObjSet._NewEnum) as IEnumVariant;
  while (Enum.Next(1, Obj, Value) = S_OK) do
  begin
    Obj:= IUnknown(Obj) as SWBemObject;
    msg :=  Obj.Vendor + #13#10 +  Obj.Name + #13#10 + Obj.IdentifyingNumber;

  end;

  showmessage(msg);

end.


いぼん  2011-11-24 01:52:27  No: 41260

訂正です。
QFormsを組み込むとPG実行時に「qtinitf.dll」が必要になります。
Formsに変更して「Application.Initialize; 」追加でdll不要で動作しました。

program Project2;

uses
  Windows, Messages ,Dialogs, ActiveX, WbemScripting_TLB,Forms;

var
  Locator: ISWbemLocator;
  Service: ISWbemServices;
  ObjSet: ISWbemObjectSet;
  Enum: IEnumVariant;
  Obj: OleVariant;
  Value: Cardinal;
  msg: string;
  Application: TApplication;    //<---追加

// {$R *.res}

begin
  Application.Initialize;  //<---追加
  Locator := CoSWbemLocator.Create;
  Service := Locator.ConnectServer('.', 'root\cimv2', '', '', '', '', 0, nil);

  ObjSet:= Service.ExecQuery('SELECT * FROM Win32_ComputerSystemProduct',
    'WQL', wbemFlagReturnImmediately, nil);
  Enum:= (ObjSet._NewEnum) as IEnumVariant;
  while (Enum.Next(1, Obj, Value) = S_OK) do
  begin
    Obj:= IUnknown(Obj) as SWBemObject;
    msg :=  Obj.Vendor + #13#10 +  Obj.Name + #13#10 + Obj.IdentifyingNumber;

  end;

showmessage(msg);

end.


ぽむぽむ  2011-11-24 21:06:58  No: 41261

showmessageは、内部でTFormを使用してるので、厳密にフォーム無しにはならない。
monaa さんのレスにある、MessageBox はWindowsAPIなので、これを使い
Dialogsを削除したらいいのでは?
・・・テストしていませんけど。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加