プリンターの情報を取得する

# はじめに

プリンターの一覧やステータスを取得したいと思い、調べたことについての備忘録。

# プリンターの一覧とステータスの取得

PRINTER_INFO_2 構造体を取得すれば良さそう。

https://learn.microsoft.com/ja-jp/windows/win32/printdocs/printer-info-2



```cs
[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);
```

```cs:プリンター一覧の取得
using System.Drawing.Printing;

PrinterSettings.InstalledPrinters
```

<details><summary>PRINTER_INFO_2 構造体</summary>

```cs

        // CharSet.Autoだと文字化けするので Ansiに変更
        [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;
        }
```

</details>

<details><summary>PRINTER_INFO_2を取得する</summary>

```CS
        /// <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);
            }
        }
```

</details>

<details><summary>コピペ用エラー表示</summary>

```cs:コピペ用

//プリンタ名
string printerName = tbPrinterName.Text;
//プリンタ情報を取得する
PRINTER_INFO_2 pinfo = GetPrinterInfo(printerName);

//状態を表示する
tbMessage.Text += $"Status:{pinfo.Status} ";

switch (pinfo.Status)
{
    case 0:        
        tbMessage.Text += "Printer ready 印刷可能" + Environment.NewLine;
        break;            
                          
    case 1:              
        tbMessage.Text += "Printer paused 印刷一時停止" + Environment.NewLine;
        break;            
                          
    case 2:               
        tbMessage.Text += "Printer error プリンターエラー" + Environment.NewLine;
        break;            
                          
    case 4:               
        tbMessage.Text += "Printer pending deletion プリンターの削除が保留中" + Environment.NewLine;
        break;            
                          
    case 8:               
        tbMessage.Text += "Paper jam 紙詰まり" + Environment.NewLine;
        break;

    case 16:
        tbMessage.Text += "Out of paper 用紙切れ" + Environment.NewLine;
        break;

    case 32:
        tbMessage.Text += "Manual feed 手差し" + Environment.NewLine;
        break;

    case 64:
        tbMessage.Text += "Paper problem 用紙に問題がある" + Environment.NewLine;
        break;

    case 128:             
        tbMessage.Text += "Printer offline オフライン状態" + Environment.NewLine;
        break;

    case 256:
        tbMessage.Text += "IO active アクティブな入出力状態" + Environment.NewLine;
        break;

    case 512:
        tbMessage.Text += "Printer busy ビジー状態" + Environment.NewLine;
        break;

    case 1024:
        tbMessage.Text += "Printing 印刷中" + Environment.NewLine;
        break;

    case 2048:
        tbMessage.Text += "Printer output bin full 排紙トレーが一杯" + Environment.NewLine;
        break;

    case 4096:
        tbMessage.Text += "Not available 利用不可" + Environment.NewLine;
        break;

    case 8192:
        tbMessage.Text += "Waiting 待機中" + Environment.NewLine;
        break;

    case 16384:
        tbMessage.Text += "Processing 処理中" + Environment.NewLine;
        break;

    case 32768:
        tbMessage.Text += "Initializing 初期化中" + Environment.NewLine;
        break;

    case 65536:
        tbMessage.Text += "Warming up ウォーミングアップ" + Environment.NewLine;
        break;

    case 131072:
        tbMessage.Text += "Toner low 残りトナーが少ない" + Environment.NewLine;
        break;

    case 262144:
        tbMessage.Text += "No Toner トナー切れ" + Environment.NewLine;
        break;

    case 524288:
        tbMessage.Text += "Page punt 現在のページを印刷できません" + Environment.NewLine;
        break;

    case 1048576:
        tbMessage.Text += "User intervention ユーザーがエラー処理をする必要がある" + Environment.NewLine;
        break;

    case 2097152:
        tbMessage.Text += "Out of memory メモリ不足" + Environment.NewLine;
        break;

    case 4194304:
        tbMessage.Text += "Door open ドアが開いている" + Environment.NewLine;
        break;

    case 8388608:
        tbMessage.Text += "Server unknown 状態不明" + Environment.NewLine;
        break;

    case 6777216:
        tbMessage.Text += "Powe save 省エネモード" + Environment.NewLine;
        break;

    default:
        tbMessage.Text += "不明" + Environment.NewLine;
        break;
}

```

</details>

# 参考ページ

http://mrxray.on.coocan.jp/Delphi/plSamples/010_Printer_Info_Structure.htm#11

https://dobon.net/vb/dotnet/graphics/printerport.html

https://ishigame-machine-technology.net/IMT/archives/887