none
C#でのプリンタリスト取得(一部除外)の方法 RRS feed

  • 質問

  • C#で「Select * from Win32_Printer」のコマンドを使用し、プリンタ一覧を取得しようと思います。

    但し、「Microsoft Office Document Image Writer」や「Microsoft XPS Document Writer」等、IPアドレスが設定されていない

    PC初期状態から存在するものは除外したいのです。

    どのようにすればよろしいでしょうか。

    2013年6月26日 11:33

回答

  • ネットワークプリンタなら、WHERE Network = True とかクエリに追加すればいいと思いますが、当然ながらUSBで繋いだプリンタとかも除外されます。
    • 回答としてマーク A_M_Scofield 2013年6月27日 8:08
    2013年6月26日 13:25
  • うろ覚えで書きますが、ネットワークプリンターをローカルプリンターとして登録することもできたように思います。その場合も除外されてしまうかもしれません。
    # 記憶違いならすみません。
    • 回答としてマーク A_M_Scofield 2013年6月27日 8:08
    2013年6月26日 14:47

すべての返信

  • ネットワークプリンタなら、WHERE Network = True とかクエリに追加すればいいと思いますが、当然ながらUSBで繋いだプリンタとかも除外されます。
    • 回答としてマーク A_M_Scofield 2013年6月27日 8:08
    2013年6月26日 13:25
  • うろ覚えで書きますが、ネットワークプリンターをローカルプリンターとして登録することもできたように思います。その場合も除外されてしまうかもしれません。
    # 記憶違いならすみません。
    • 回答としてマーク A_M_Scofield 2013年6月27日 8:08
    2013年6月26日 14:47
  •  WMI ではなく、API 呼び出しになりますが。

     プリンターで判断するのではなく、プリンターがつながっているポート(モニター)で判断します。ただ、「ポートの種類」というものがないので、辞書登録するしかないと思いますが。その方法です。

     EnumPrinters 関数で、レベル2を指定してプリンター情報を取得します。PRINTER_INFO_2 structure から、ポート名が取得できます。
     EnumPorts 関数で、レベル2を指定して、ポート情報を取得します。PORT_INFO_2 structure から、モニター名が取得できます。
     PRINTER_INFO_2.pPortName の内容が PORT_INFO_2.pMonitorName の内容と等しい PORT_INFO_2 の pMonitorName を調べ、"ローカル モニター"などが「IPアドレスが設定されていない」ものになります。まぁ、「ローカル モニター」は、ロケールに依存していそうだから、何か工夫がいるだろうけど。MONITOR_INFO_2 では、DLL が取れるので、そこまで見ればいいかも。

     同じことは、WMI でもできると思います。

     その他、プリンター メーカーによっては、独自のモニターを登録します。それらも含めて、どのようなプリンターが、どのように見えるか、確認してください。プリンターの追加で、他の PC が公開しているプリンターを追加したのでなければ、ローカルなプリンターになります。また、リモート デスクトップなどで、クライアントが持っているプリンターをサーバー側で使う場合、サーバーのローカル プリンターになります。

     ちょっと時間が空いたので、C ですが、作ってみました。C# だと、PRINTER_INFO_2, PORT_INFO_2 の構造体を定義して、Marshal の中のメソッドでコチョコチョして、EnumPrinters, EnumPorts を P/Invoke すればいいはずです。C++ の Win32 コンソール アプリケーション プロジェクトなら、そのまま貼り付けて実行できます。C# には、だめですよ。

    #include "stdafx.h"
    #include <Windows.h>
    #include <WinSpool.h>
    #include <locale.h>
    
    PRINTER_INFO_2* DoEnumPrinters(LPDWORD pdwPrinters)
    {
    	DWORD dwSize = 0;
    	DWORD dwNeeded;
    	LPBYTE pBuffer = NULL;
    	EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
    		NULL,
    		2,
    		pBuffer,
    		dwSize,
    		&dwNeeded,
    		pdwPrinters);
    	pBuffer = (LPBYTE) malloc(dwNeeded);
    	dwSize = dwNeeded;
    	EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
    		NULL,
    		2,
    		pBuffer,
    		dwSize,
    		&dwNeeded,
    		pdwPrinters);
    
    	return (PRINTER_INFO_2*) pBuffer;
    }
    
    PORT_INFO_2* DoEnumPorts(LPDWORD pdwPorts)
    {
    	DWORD dwSize = 0;
    	DWORD dwNeeded = 0;
    	LPBYTE pBuffer = NULL;
    	EnumPorts(NULL, 2, pBuffer, dwSize, &dwNeeded, pdwPorts);
    	pBuffer = (LPBYTE) malloc(dwNeeded);
    	dwSize = dwNeeded;
    	EnumPorts(NULL, 2, pBuffer, dwSize, &dwNeeded, pdwPorts);
    	return (PORT_INFO_2*) pBuffer;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	setlocale(LC_ALL, "japanese");
    
    	DWORD dwPorts;
    	PORT_INFO_2 *pPort2 = DoEnumPorts(&dwPorts);
    	DWORD dwPrinters;
    	PRINTER_INFO_2 *pInfo2 = DoEnumPrinters(&dwPrinters);
    	for (int idx = 0; idx < dwPrinters; ++idx)
    	{
    		_tprintf(TEXT("Name    : %s\n"), pInfo2[idx].pPrinterName);
    		_tprintf(TEXT("Port    : %s\n"), pInfo2[idx].pPortName);
    		for (int i = 0; i < dwPorts; ++i)
    		{
    			if (_tcscmp(pInfo2[idx].pPortName, pPort2[i].pPortName) == 0)
    			{
    				_tprintf(TEXT("Monitor : %s\n"), pPort2[idx].pMonitorName);
    				break;
    			}
    		}
    		_tprintf(TEXT("\n"));
    	}
    
    	free(pPort2);
    	free(pInfo2);
    	return 0;
    }
    

    Jitta@わんくま同盟

    2013年6月27日 14:13