C# Programming

Image

PRN: ポートへのアクセス

開発環境: Visual Studio 2003 

PRN: ポートへのアクセス

ここでは、PRN: ポートへ直接文字を書き出し、プリンタに出力するプログラムを作ってみます。

PRN: ポートを .Net フレームワークの FileStream などで直接オープンしようとすると、

Image

というエラーダイアログが表示され、直接 PRN: ポートをオープンすることができません。
このメッセージにあるように、CreateFile を呼び出して使用するしかないようです。
Win32 の CreateFile の unsafe コードを使わざるを得ません。 ったく!

作り方

0. PrnPort という名前で、コンソールアプリケーションを新規作成します。

1. Win32 SDK の CreateFile を使用する必要があります。
しかし、CreateFile は、Kernel32.lib にある Unmanaged Code なので、そのままでは C# から使えません。
そこで、DllImport というディレクティブを使い、C# から呼び出せるようにします。
そのためには、using System.Runtime.InteropServices; の1行が必要です。

2. 次に CreateFile を定義します。コードは、下のソースコード、参照してください。
この static extern unsafe int CreateFile(...) というように unsafe キーワードで宣言することにより、
unsafe なコードを安全に使用することができるということです。 ほんとか??って感じですね。


3. 次に、CreateFile の返り値は、HANDLE なので、そのハンドルから FileStream を作ります。
ここまでくれば、マネージドコードで扱うことができるようになります。

4. さて、コードが書けたところで、コンパイルしてみます。
すると、"unsafe コードは /unsafe でコンパイルした場合のみ有効です。"
というコンパイルエラーになるので、ビルド時の設定を行う必要があります。
ソリューションエクスプローラから、プロジェクトのプロパティ を選ぶと次のようなプロパティ ページが表示されます。
ここで、"セーフモード以外のコードブロックの許可" を "True" にします。(下図)
これで、実行すればプリンタにアクセスに行くはずです。


Image


注意
  • "Hello World" という文字列を書き出しているだけなので、プリンタによっては制御コードまで書かないと出力できない可能性があります。それぞれの環境に合わせて作ってください。
  • エンコーディングについて考慮していません。場合によって適切なエンコーディングを選ぶ必要があります。
  • 例外処理、エラー処理を行っていません。
  • COM1: ポートへも同様にアクセスできるはずです。
参考情報

詳細は、 MS のヘルプを見ると良いでしょう。

ソースコード

using System;
using System.Runtime.InteropServices;

namespace PrnPort
{
        /// <summary>
        /// Class1 の概要の説明です。
        /// </summary>
        class Class1
        {
                const uint GENERIC_WRITE = 0x40000000;
                const uint OPEN_EXISTING = 3;

                /// <summary>
                /// CreateFile は、Win32 SDK (unsafe) を使用します。
                /// このため、プロジェクトのビルドプロパティで 
                /// セーフモード以外のコードブロックの許可を true に
                /// する必要があります。
                /// 
                /// CreateFile の要件
                ///   Windows NT/2000/XP: Included in Windows NT 3.1 and later.
                ///   Windows 95/98/Me: Included in Windows 95 and later.
                ///   Header: Declared in Winbase.h; include Windows.h.
                ///   Library: Use Kernel32.lib.
                /// </summary>
                [DllImport("kernel32", SetLastError=true)]
                static extern unsafe int CreateFile(
                        string filename,
                        uint desiredAccess,
                        uint shareMode,
                        uint attributes,   // really SecurityAttributes pointer
                        uint creationDisposition,
                        uint flagsAndAttributes,
                        uint templateFile);

                /// <summary>
                /// アプリケーションのメイン エントリ ポイントです。
                /// </summary>
                [STAThread]
                static void Main(string[] args)
                {
                        int handle = CreateFile("PRN:",
                                GENERIC_WRITE,
                                0, 
                                0,
                                OPEN_EXISTING,
                                0,
                                0);

                        System.IO.FileStream fs = new System.IO.FileStream((IntPtr)handle, System.IO.FileAccess.ReadWrite);
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(fs);
                        sw.WriteLine("Hello World");
                        sw.Close();
                        fs.Close();
                }
        }
}