プリンタのオンライン/オフラインの判定をするのに
下記のようにしましたが、戻ってくるステータスの値は
0のままです。DELPHI 5, Win XPです。
よろしくお願いいたします。
ListBoxにプリンタが列挙されている状態で
procedure TForm1.ListBox1Click(Sender: TObject);
VAR
hPrinter : THandle ;
pPrntrInf2 : PPrinterInfo2 ;
cbNeeded : Cardinal ;
BEGIN
WinSpool.OpenPrinter( PChar( ListBox1.Items[ ListBox1.ItemIndex ] ), hPrinter, NIL ) ;
IF hPrinter = INVALID_HANDLE_VALUE THEN
EXIT ;
WinSpool.GetPrinter( hPrinter, 2, NIL, 0, @cbNeeded ) ;
pPrntrInf2 := AllocMem( cbNeeded ) ;
TRY
WinSpool.GetPrinter( hPrinter, 2, pPrntrInf2, cbNeeded, @cbNeeded ) ;
IF ( pPrntrInf2^.Status AND PRINTER_STATUS_OFFLINE ) = PRINTER_STATUS_OFFLINE THEN
ShowMessage( 'オフライン' ) ;
FINALLY
FreeMem( pPrntrInf2 ) ;
WinSpool.ClosePrinter( hPrinter ) ;
END ;
END;
下記のサイトなどを参考にしてMicrosoftのScript Control
タイプライブラリを取り込んで、DelphiからVBを実行すること
によりプリンタのオン・オフラインを判定することができました。
迂遠な方法で釈然としませんが、とりあえず必要な情報はえられ
ました。VBに相当するDelphiのコードはどうなるのか引き続き調べて
見たいと思います。
質問をごらんになって考えてくださった方に御礼申し上げます。
http://www.vbforums.com/showthread.php?532954-RESOLVED-Printer-status-detecting-on-or-off
http://oshiete.goo.ne.jp/qa/120709.html
USES
MSScriptControl_TLB ;
PROCEDURE TForm1.ListBox1Click( Sender: TObject ) ;
VAR
VB_Script : STRING ;
ScriptControl : TScriptControl ;
begin
VB_Script := 'GetObject("winmgmts:\\.\root\CIMV2").Get("Win32_Printer=''' + ListBox1.Items[ ListBox1.ItemIndex ] + '''").WorkOffline' ;
ScriptControl := TScriptControl.Create( Application ) ;
ScriptControl1.Language := 'VBScript' ;
IF ScriptControl1.Eval( VB_Script ) THEN
ShowMessage( 'オフライン' ) ;
ScriptControl.Free ;
end;
一部訂正
上記コードの最終から5,6行目にある
ScriptControl1はScriptControl
と訂正します。
判定はなかなか条件が厳しいようですね。たとえばこちらの話。
プリンターの電源が入っているかの確認 - Visual Basic 掲示板
http://madia.world.coocan.jp/cgi-bin/VBBBS/wwwlng.cgi?print+200306/03060053.txt
要約すると…GetPrinterによるStatusはドライバの仕様でほぼ0のみ、メーカーのユーティリティーを
常駐すれば取れることもある、双方向通信(双方向サポート)が有効でないとダメ、とか。
これを裏付けるような情報がMSにもありました。
プリンタと印刷ジョブの状態の取得方法 - Microsoft サポート
http://support.microsoft.com/kb/160129/ja
>プリンタの状態をより簡単に判断する方法は、PRINTER_INFO 構造体の Status メンバを確認することです。
>この構造体は、GetPrinter 関数によって取得できます。
(中略)
>ただし、通常、Windows のデフォルトのポート モニタは、プリンタの Status メンバの
>PRINTER_STATUS_ERROR ビット以上の情報を設定しません。
WMIを使っても、私の環境ではどのプリンタ(実機と仮想のPDF等)も常にOnline&Idleなんですよねー。
もちろんVBScript、Delphiともに。メーカーのユーティリティは電源オフを感知して示してるんですが。
環境:Delphi6 Personal、WindowsXP、Brother MFC-J615N Printer
■VBScript
If GetObject("winmgmts:\\.\root\CIMV2").Get("Win32_Printer=""Brother MFC-J615N Printer""").WorkOffline Then
WScript.Echo "Offline"
Else
WScript.Echo "Online"
End If
■Delphi
implementation
{$R *.dfm}
uses
ComObj;
const
mWorkOffline: array[Boolean] of String =(
'Online', 'Offline'
);
mPrinterStatus: array[0..7] of String =(
'*Undefined Value*',
'Other', 'Unknown', 'Idle', 'Printing', 'Warming Up',
'Stopped printing', 'Offline'
);
procedure TForm1.Button1Click(Sender: TObject);
var
oLocator: OleVariant;
oService: OleVariant;
oClassSet: OleVariant;
oClass: OleVariant;
begin
oLocator:=CreateOleObject('WbemScripting.SWbemLocator');
oService:=oLocator.ConnectServer;
oClassSet:=oService.ExecQuery('Select * From Win32_Printer');
Memo1.Lines.Add('--------------------------------------');
// 本当は '\\マシン名\root\cimv2:Win32_Printer.DeviceID="プリンタ名"' らしい
oClass:=oClassSet.Item('Win32_Printer.DeviceID="'+Edit1.Text+'"');
Memo1.Lines.Add('プリンタ名:'+VarToStr(oClass.Name));
Memo1.Lines.Add('WorkOffline:'+mWorkOffline[Boolean(oClass.WorkOffline)]);
Memo1.Lines.Add('PrinterStatus:'+mPrinterStatus[Integer(oClass.PrinterStatus)]);
oClass:= Unassigned;
oClassSet:=Unassigned;
oService:= Unassigned;
oLocator:= Unassigned;
end;
Delphi長杉…。
procedure TForm1.Button2Click(Sender: TObject);
var
oClass: OleVariant;
begin
oClass:=OleVariant(CreateOleObject('WbemScripting.SWbemLocator')).ConnectServer.
ExecQuery('Select * From Win32_Printer').Item('Win32_Printer.DeviceID="'+Edit1.Text+'"');
Memo1.Lines.Add('--------------------------------------');
Memo1.Lines.Add('プリンタ名:'+VarToStr(oClass.Name));
Memo1.Lines.Add('WorkOffline:'+mWorkOffline[Boolean(oClass.WorkOffline)]);
Memo1.Lines.Add('PrinterStatus:'+mPrinterStatus[Integer(oClass.PrinterStatus)]);
oClass:=Unassigned;
end;
↑悔しいので、無理やり短くしてみました。失礼しました。
Harryさん、ありがとうございました。
まったく「Delphi長杉…」ですね。
歯がゆいですがしょうがありません。
ちなみに今回のアプリケーションで使って
いるプリンタはSonyのUP-D897で、連続
ロール紙への印刷になります。
オフライン判定法がわからないうちは、
一度小さい白字で1行出力してみて、2,3秒後
にSpoolerにJobが残っているようだったら
オフラインとみなしてJobをPurgeしていました。
ツイート | ![]() |