C# - 可以使用 IOCTL

发布于 2024-09-02 22:54:21 字数 1347 浏览 8 评论 0原文

我正在尝试为销售点系统编写代码,该系统允许“现金抽屉”附件。手册中提供了用于打开现金抽屉的代码(使用 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);
}

I'm trying to code for a Point Of Sale system which allows for a "Cash Drawer" attachment. Code is provided in the manual for opening the cash drawer (in C++ using IOCTL). Since I am coding in C# .NET, is it possible to perform something similar from within C# or will I have to write some unmanaged code?

Am I able to get a handle to "\\.\ADVANSYS" from within C#? Do I need to use DLLImport?

Would appreciate it if someone could point me in the right direction.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

好菇凉咱不稀罕他 2024-09-09 22:54:21

C++ 充满了错误,不确定我是否正确。最好的办法是使用更改的参数类型来声明 DeviceIoControl(),以便于调用。您还必须 P/Invoke CreateFile,因为 FileStream 无法打开设备。它应该看起来与此类似:

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);
}

The C++ is riddled with mistakes, not sure if I got it right. The best thing to do is to declare DeviceIoControl() with altered argument types so that it is easy to call. You also have to P/Invoke CreateFile because FileStream cannot open devices. It ought to look similar to this:

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);
}
等往事风中吹 2024-09-09 22:54:21

您可以使用 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);

此示例可能也会有所帮助。

You can use 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);

This example might also help.

荭秂 2024-09-09 22:54:21

pinvoke.net 上有大量为此准备的代码,还有大量示例。

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

There's loads of code ready for this on pinvoke.net with plenty of examples too.

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

不知在何时 2024-09-09 22:54:21

你写道:

似乎GPD_TYPE 56053
如文档中所述
我的说法不正确

您可以发布 GPD_TYPE 的正确值吗?

最好的问候!

you wrote:

It seemed that the GPD_TYPE 56053
as specified in the documentation that
I had was not correct

Can you post proper value of GPD_TYPE ?

Best regadrs!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文