2

「Cash Drawer」アタッチメントを可能にする POS システムのコードを作成しようとしています。コードは、キャッシュ ドロワーを開くためのマニュアルに記載されています (IOCTL を使用した C++ で)。私は C# .NET でコーディングしているので、C# 内から同様のことを実行することは可能ですか? またはアンマネージ コードを記述する必要がありますか?

C# 内から "\\.\ADVANSYS" へのハンドルを取得できますか? DLLImport を使用する必要がありますか?

誰かが私を正しい方向に向けることができれば幸いです。

// IOCTL Codes
#define GPD_TYPE 56053
#define ADV_OPEN_CTL_CODE CTL_CODE(GPD_TYPE, 0x920, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define ADV_STATUS_CTL_CODE CTL_CODE(GPD_TYPE, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
void OpenDrawer(UCHAR uWhichDrawer) // uWhichDrawer = 1 => CD#1, uWhichDrawer = 2 => CD#2
{
    HANDLE hFile;
    BOOL bRet
    UCHAR uDrawer = uWhichDrawer;

    // Open the driver
    hFile = CreateFile(TEXT("\\\\.\\ADVSYS"),
    GENERIC_WRITE | GENERIC_READ,
    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

    if (m_hFile == INVALID_HANDLE_VALUE)
    {
        AfxMessageBox("Unable to open Cash Drawer Device Driver!");
        return;
    }

    // Turn on the Cash Drawer Output (Fire the required solenoid)
    bRet = DeviceIoControl(hFile, ADV_CD_OPEN_CTL_CODE,
    &uDrawer, sizeof(uDrawer),
    NULL, 0,
    &ulBytesReturned, NULL);

    if (bRet == FALSE || ulBytesReturned != 1)
    {
        AfxMessageBox("Failed to write to cash drawer driver");
        CloseHandle(hFile);
        return;
    }
    CloseHandle(hFile);
}
4

4 に答える 4

5

C++ には間違いがたくさんあります。正しく理解できたかどうかはわかりません。最善の方法は、簡単に呼び出せるように、引数の型を変更して DeviceIoControl() を宣言することです。FileStream はデバイスを開くことができないため、CreateFile を P/Invoke する必要もあります。次のようになります。

using System;
using System.IO;
using System.ComponentModel;
using System.Runtime.InteropServices;

class Program {
    static void Main(string[] args) {
        IntPtr hdl = CreateFile("\\\\.\\ADVSYS", FileAccess.ReadWrite,
            FileShare.None, IntPtr.Zero, FileMode.Open,
            FileOptions.None, IntPtr.Zero);
        if (hdl == (IntPtr)(-1)) throw new Win32Exception();
        try {
            byte drawer = 1;
            bool ok = DeviceIoControl(hdl, CTLCODE, ref drawer, 1, IntPtr.Zero,
                0, IntPtr.Zero, IntPtr.Zero);
            if (!ok) throw new Win32Exception();
        }
        finally {
            CloseHandle(hdl);
        }
    }
    // P/Invoke:
    private const uint CTLCODE = 0xdaf52480;
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CreateFile(string filename, FileAccess access,
          FileShare sharing, IntPtr SecurityAttributes, FileMode mode,
          FileOptions options, IntPtr template
    );
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool DeviceIoControl(IntPtr device, uint ctlcode,
        ref byte inbuffer, int inbuffersize,
        IntPtr outbuffer, int outbufferSize,
        IntPtr bytesreturned, IntPtr overlapped
    );
    [DllImport("kernel32.dll")]
    private static extern void CloseHandle(IntPtr hdl);
}
于 2010-05-20T08:47:13.767 に答える
2

Pinvokeを使用できます。

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
internal static extern bool DeviceIoControl([In] SafeFileHandle hDevice, [In] int dwIoControlCode, [In] IntPtr lpInBuffer, [In] int nInBufferSize, [Out] IntPtr lpOutBuffer, [In] int nOutBufferSize, out int lpBytesReturned, [In] IntPtr lpOverlapped);

この例も役立つかもしれません。

于 2010-05-20T07:05:19.540 に答える
1

あなたが書いた:

私が持っていたドキュメントで指定されているGPD_TYPE 56053は正しくないようでし

GPD_TYPEの適切な値を投稿できますか?

よろしくお願いします!

于 2010-07-01T12:02:21.780 に答える
1

pinvoke.net には、これに対応する準備が整ったコードがたくさんあり、多くの例もあります。

http://www.pinvoke.net/default.aspx/kernel32.DeviceIoControl

于 2010-05-20T08:55:43.297 に答える