C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: C#から正しいプリンタの情報を取得するには?


(過去ログ 30 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■14502 / inTopicNo.1)  C#から正しいプリンタの情報を取得するには?
  
□投稿者/ hanayama (4回)-(2008/02/20(Wed) 11:26:59)

分類:[C#] 

お世話になっております。hanayamaです。

C#でWin32APIを使用し、プリンタの情報を取得したいのですが、
現状のコードで正しいステータスが取れているかどうか不明です。

以下がコードです。長文ご容赦下さい。

***************************************************************************************

public class Sample
{
[DllImport("winspool.drv", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool OpenPrinter(string pPrinterName,
out IntPtr hPrinter, IntPtr pDefault);

[DllImport("winspool.drv", SetLastError = true)]
private static extern bool ClosePrinter(IntPtr hPrinter);

[DllImport("winspool.drv", SetLastError = true)]
private static extern bool GetPrinter(IntPtr hPrinter,
int dwLevel, IntPtr pPrinter, int cbBuf, out int pcbNeeded);

// JOB_INFO_2構造体定義
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PRINTER_INFO_2
{
public string pServerName;
public string pPrinterName;
public string pShareName;
public string pPortName;
public string pDriverName;
public string pComment;
public string pLocation;
public IntPtr pDevMode;
public string pSepFile;
public string pPrintProcessor;
public string pDatatype;
public string pParameters;
public IntPtr pSecurityDescriptor;
public uint Attributes;
public uint Priority;
public uint DefaultPriority;
public uint StartTime;
public uint UntilTime;
public uint Status;
public uint cJobs;
public uint AveragePPM;
}

public PrinterInfo GetPrinterInfo(string printerName)
{
IntPtr hPrinter;

// 返却用
PrinterInfo printerInfo = null;

//プリンタのハンドルを取得する
if (!OpenPrinter(printerName, out hPrinter, IntPtr.Zero))
{
throw new Exception("プリンタハンドル取得失敗");
}

IntPtr pPrinterInfo = IntPtr.Zero;

try
{
//必要なバイト数を取得する
int needed;
GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out needed);
if (needed <= 0)
throw new Exception("失敗しました。");

//メモリを割り当てる
pPrinterInfo = Marshal.AllocHGlobal(needed);

//プリンタ情報を取得する
int temp;

if (!GetPrinter(hPrinter, 2, pPrinterInfo, needed, out temp))
{
throw new Exception("プリンタオープン失敗");
}

//PRINTER_INFO_2型にマーシャリングする
PRINTER_INFO_2 printerInfo =
(PRINTER_INFO_2)Marshal.PtrToStructure(pPrinterInfo,
typeof(PRINTER_INFO_2));

printerInfo = new PrinterInfo();

printerInfo.PrinterName = printerName;
printerInfo.DeviceName = printerInfo.pPrinterName;
printerInfo.PortName = printerInfo.pPortName;
printerInfo.JobCount = (int)printerInfo.cJobs;
printerInfo.Status = (int)printerInfo.Status;
}
finally
{
//後始末をする
ClosePrinter(hPrinter);
Marshal.FreeHGlobal(pPrinterInfo);
}

return printerInfo;
}
}

***************************************************************************************

   上記コードをコンパイルしたアプリケーションを実行すると、プリンタ名からプリンタのハンドルを取得した後、
  JOB_INFO_2構造体の情報を取得し、その中からさらにステータスを取得しているのですが、
  コントロールパネルの「プリンタとFAX」からプリンタドライバをオフラインに変更しても
  アプリケーションで取得できるステータス(Status)が0(正常)のままとなります。
  印刷中も同様にステータスが0のままです。
  唯一、プリンタドライバのステータスを「中断」に変更した場合だけ
  ステータスが1(中断)となり、正しいステータスを取得できています。

   私の認識だとJOB_INFO_2構造体の情報はプリンタドライバの情報を
  取得するものだと思っているのですが、誤りでしょうか?

   以上、ご教授お願いいたします。

  


 
引用返信 編集キー/
■14510 / inTopicNo.2)  Re[1]: C#から正しいプリンタの情報を取得するには?
□投稿者/ とっちゃん (243回)-(2008/02/20(Wed) 13:46:02)
とっちゃん さんの Web サイト
No14502 (hanayama さん) に返信

GetPrinter で取得するのは、PRINTER_INFO_X で、JOB_INFO_X ではありません。
もちろん、内容も異なりますので、取得できる情報も異なります。

オーバーランなどが発生しないのは、バッファサイズを要求分確保しているからにすぎません。

コード的には、PRINTER_INFO_2 の定義を正しくしてやれば行けそうな気がします。

JOB_INFO_X(こちらは、一つの出力ブロックごとの情報)を取得するには
GetJob API(.NET Framework に同様のがあるかは不明)で取得となります。

引用返信 編集キー/
■14513 / inTopicNo.3)  Re[2]: C#から正しいプリンタの情報を取得するには?
□投稿者/ 七曜 (78回)-(2008/02/20(Wed) 15:15:34)
No14510 (とっちゃん さん) に返信
> GetJob API(.NET Framework に同様のがあるかは不明)で取得となります。

.NET Framework 3.0以降であれば、System.Printing 名前空間のクラスを利用して
こんな感じで情報を取れたりしますね。

            PrintServer server = new PrintServer();
            foreach (PrintQueue queue in server.GetPrintQueues())
            {
                Console.WriteLine(String.Format("{0}", queue.Name));
                Console.WriteLine(String.Format("\t{0}", queue.QueueDriver.Name));
                Console.WriteLine(String.Format("\t{0}", queue.QueuePort.Name));
                Console.WriteLine(String.Format("\t{0}", queue.NumberOfJobs));
                Console.WriteLine(String.Format("\t{0}", (queue.IsOffline) ? "オフライン" : "オンライン"));
            }

細かくは試してませんので、記述方法や使用方法はMSDNなどで確認してみてください。

引用返信 編集キー/
■14515 / inTopicNo.4)  Re[3]: C#から正しいプリンタの情報を取得するには?
□投稿者/ とっちゃん (244回)-(2008/02/20(Wed) 15:25:22)
とっちゃん さんの Web サイト
No14513 (七曜 さん) に返信
> .NET Framework 3.0以降であれば、System.Printing 名前空間のクラスを利用して
> こんな感じで情報を取れたりしますね。
>
うは!?こんなに簡単に...

GetJob するとなると、プリンタ引っ張ってきて(OpenPrinter)、EnumJobして...アロケートしてGetJobして...ようやくですw
で、考えてみたら、3.0 っていくつかプリンタサポート入ってましたよね。

そっち使えば、GetPrinter の処理もちょっと楽になるような...w

引用返信 編集キー/
■14524 / inTopicNo.5)  Re[3]: C#から正しいプリンタの情報を取得するには?
□投稿者/ Jitta (454回)-(2008/02/20(Wed) 22:50:54)
Jitta さんの Web サイト
No14513 (七曜 さん) に返信
> ■No14510 (とっちゃん さん) に返信
>>GetJob API(.NET Framework に同様のがあるかは不明)で取得となります。
>
> .NET Framework 3.0以降であれば、System.Printing 名前空間のクラスを利用して
> こんな感じで情報を取れたりしますね。
>
> PrintServer server = new PrintServer();
> foreach (PrintQueue queue in server.GetPrintQueues())
> {
> Console.WriteLine(String.Format("{0}", queue.Name));
> Console.WriteLine(String.Format("\t{0}", queue.QueueDriver.Name));
> Console.WriteLine(String.Format("\t{0}", queue.QueuePort.Name));
> Console.WriteLine(String.Format("\t{0}", queue.NumberOfJobs));
> Console.WriteLine(String.Format("\t{0}", (queue.IsOffline) ? "オフライン" : "オンライン"));
> }
>
> 細かくは試してませんので、記述方法や使用方法はMSDNなどで確認してみてください。
>

むはっ!!!!
これは、提案に含めねばorz
引用返信 編集キー/
■14684 / inTopicNo.6)  Re[4]: C#から正しいプリンタの情報を取得するには?
□投稿者/ hanayama (5回)-(2008/02/25(Mon) 11:54:29)
No14524 (Jitta さん) に返信
> ■No14513 (七曜 さん) に返信
>>■No14510 (とっちゃん さん) に返信

> GetPrinter で取得するのは、PRINTER_INFO_X で、JOB_INFO_X ではありません。
> もちろん、内容も異なりますので、取得できる情報も異なります。

すみません、返信が遅れてしまいました。
回答ありがとうございます。

質問内容に不備がありました・・・・。

コメントや質問内容で「JOB_INFO_2構造体」
と言っているのは全て「PRINTER_INFO_2構造体」のことです。
(上記コード上ではPRINTER_INFO_2構造体でコーディングしています)
惑わせてしまい、申し訳ございません。

改めて、質問させていただきます。
PRINTER_INFO_2構造体の定義に誤りはない認識でおりますが、
質問させていただいたようにプリンタのステータスがとれません、、、(中断のみ取れる)

お手数ですが、回答お願い致します。





引用返信 編集キー/
■14688 / inTopicNo.7)  Re[5]: C#から正しいプリンタの情報を取得するには?
□投稿者/ とっちゃん (245回)-(2008/02/25(Mon) 13:19:17)
とっちゃん さんの Web サイト
No14684 (hanayama さん) に返信

> PRINTER_INFO_2構造体の定義に誤りはない認識でおりますが、
> 質問させていただいたようにプリンタのステータスがとれません、、、(中断のみ取れる)
>
確認ですが、Native C++ のレベルでは正しく値が取得できていますか?
テストプログラムのレベルでもかまいませんが、可能であれば、C# などから呼び出す形で
C++/CLI もしくは、Managed C++ で引っ張って見て、正しい値が取れるかどうかを
確認してみるのが良いかと。

Native C++ のレベルであれば意図した値がとれるということであれば、
C#へのポーティングがうまくいっていない(それがどこかはわかりませんが)ということになりますし
C++ のレベルでも取得できないということであれば、ドライバレベルで設定されない
ということになります。

PRINTER_INFO_X の情報のうち、プリンタ名だとかの部分はほとんどの状況で正しいものが
得られますが、それ以外の情報は、必ずしも正しい値が得られるとは限りません。

これは、ローカルにつながっている場合でも同様です。
もし、ネットワーク越しということになると、さらに取れる可能性は減ります。

いずれにしてもプログラムが間違っているのか、ドライバが返してくれる情報が
それ以上ないのかの切り分けができないと先に進めない気がします。

引用返信 編集キー/
■14693 / inTopicNo.8)  Re[5]: C#から正しいプリンタの情報を取得するには?
□投稿者/ 七曜 (84回)-(2008/02/25(Mon) 15:22:24)
No14684 (hanayama さん) に返信
> PRINTER_INFO_2構造体の定義に誤りはない認識でおりますが、
> 質問させていただいたようにプリンタのステータスがとれません、、、(中断のみ取れる)

[How to get the status of a printer and a print job]
http://support.microsoft.com/kb/160129/EN-US/

要は、印刷ジョブを投入して、そのジョブの状態で判断するのが正しい手法らしいです。
スプーラが絡むので、
印刷は受け付けられる(正常)→印刷ジョブを受け付ける→デバイスに送信→エラーが返る
という仕組みのようです。
あとは、プリンタドライバ、OS種類によっては、他にやり様はあるかもしれません。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -