「通常使うプリンタを取得、設定する」と同じように、WMIのWin32_Printerを使ってプリンタの情報を取得できます。ポートはPortNameプロパティ、状態はPrinterStatusプロパティで取得できます。
また、P/InvokeでGetPrinter関数を呼び出すことにより、プリンタの情報を取得することもできます。ここではこの方法を紹介します。
下にプリンタの情報をPRINTER_INFO_2構造体で取得するためのメソッド(GetPrinterInfoメソッド)のサンプルを示します。
なおこのコードを書くために「Newsgroups:microsoft.public.dotnet.framework.interop / Subject:Solution: Printer Port and Driver Information (PRINTER_INFO_2)」と「The Code Project - Changing printer settings using C#」を参考にしました。
'Imports System.Runtime.InteropServices 'Imports System.ComponentModel <DllImport("winspool.drv", CharSet:=CharSet.Auto, SetLastError:=True)> _ Private Shared Function OpenPrinter( _ ByVal pPrinterName As String, ByRef hPrinter As IntPtr, _ ByVal pDefault As IntPtr) As Boolean End Function <DllImport("winspool.drv", SetLastError:=True)> _ Private Shared Function ClosePrinter( _ ByVal hPrinter As IntPtr) As Boolean End Function <DllImport("winspool.drv", SetLastError:=True)> _ Private Shared Function GetPrinter( _ ByVal hPrinter As IntPtr, ByVal dwLevel As Integer, _ ByVal pPrinter As IntPtr, ByVal cbBuf As Integer, _ ByRef pcbNeeded As Integer) As Boolean End Function <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ Public Structure PRINTER_INFO_2 Public pServerName As String Public pPrinterName As String Public pShareName As String Public pPortName As String Public pDriverName As String Public pComment As String Public pLocation As String Public pDevMode As IntPtr Public pSepFile As String Public pPrintProcessor As String Public pDatatype As String Public pParameters As String Public pSecurityDescriptor As IntPtr Public Attributes As System.UInt32 Public Priority As System.UInt32 Public DefaultPriority As System.UInt32 Public StartTime As System.UInt32 Public UntilTime As System.UInt32 Public Status As System.UInt32 Public cJobs As System.UInt32 Public AveragePPM As System.UInt32 End Structure ''' <summary> ''' プリンタの情報をPRINTER_INFO_2で取得する ''' </summary> ''' <param name="printerName">プリンタ名</param> ''' <returns>プリンタの情報</returns> Public Shared Function GetPrinterInfo( _ ByVal printerName As String) As PRINTER_INFO_2 'プリンタのハンドルを取得する Dim hPrinter As IntPtr If Not OpenPrinter(printerName, hPrinter, IntPtr.Zero) Then Throw New Win32Exception(Marshal.GetLastWin32Error()) End If Dim pPrinterInfo As IntPtr = IntPtr.Zero Try '必要なバイト数を取得する Dim needed As Integer GetPrinter(hPrinter, 2, IntPtr.Zero, 0, needed) If needed <= 0 Then Throw New Exception("失敗しました。") End If 'メモリを割り当てる pPrinterInfo = Marshal.AllocHGlobal(needed) 'プリンタ情報を取得する Dim temp As Integer If Not GetPrinter(hPrinter, 2, pPrinterInfo, needed, temp) Then Throw New Win32Exception(Marshal.GetLastWin32Error()) End If 'PRINTER_INFO_2型にマーシャリングする Dim printerInfo As PRINTER_INFO_2 = _ CType(Marshal.PtrToStructure( _ pPrinterInfo, GetType(PRINTER_INFO_2)), PRINTER_INFO_2) '結果を返す Return printerInfo Finally '後始末をする ClosePrinter(hPrinter) Marshal.FreeHGlobal(pPrinterInfo) End Try End Function
//using System.Runtime.InteropServices; //using System.ComponentModel; [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); [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] 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; } /// <summary> /// プリンタの情報をPRINTER_INFO_2で取得する /// </summary> /// <param name="printerName">プリンタ名</param> /// <returns>プリンタの情報</returns> public static PRINTER_INFO_2 GetPrinterInfo(string printerName) { //プリンタのハンドルを取得する IntPtr hPrinter; if (!OpenPrinter(printerName, out hPrinter, IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } 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 Win32Exception(Marshal.GetLastWin32Error()); } //PRINTER_INFO_2型にマーシャリングする PRINTER_INFO_2 printerInfo = (PRINTER_INFO_2) Marshal.PtrToStructure(pPrinterInfo, typeof(PRINTER_INFO_2)); //結果を返す return printerInfo; } finally { //後始末をする ClosePrinter(hPrinter); Marshal.FreeHGlobal(pPrinterInfo); } }
GetPrinterInfoメソッドを使ってプリンタのポートと状態を取得する例を以下に示します。"PRINTER NAME"を適当なプリンタの名前に変えてください。
'プリンタ名 Dim printerName As String = "PRINTER NAME" 'プリンタ情報を取得する Dim pinfo As PRINTER_INFO_2 = GetPrinterInfo(printerName) 'ポートを表示する Console.WriteLine(("Port:" + pinfo.pPortName)) '状態を表示する Console.WriteLine(("Status:" + pinfo.Status.ToString()))
//プリンタ名 string printerName = "PRINTER NAME"; //プリンタ情報を取得する PRINTER_INFO_2 pinfo = GetPrinterInfo(printerName); //ポートを表示する Console.WriteLine("Port:" + pinfo.pPortName); //状態を表示する Console.WriteLine("Status:" + pinfo.Status.ToString());
(この記事は、「.NETプログラミング研究 第47号」で紹介したものを基にしています。)