سؤال

أحاول رمز نظام نقاط البيع الذي يتيح مرفق "درج نقدي". يتم توفير الكود في الدليل لفتح درج النقود (في C ++ باستخدام IOCTL). بما أنني أقوم بالترميز في C# .NET ، هل من الممكن إجراء شيء مشابه من داخل C# أو هل سيتعين علي كتابة بعض التعليمات البرمجية غير المدارة؟

هل يمكنني الحصول على مقبض لـ ". Advansys" من داخل C#؟ هل أحتاج إلى استخدام 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);
}
هل كانت مفيدة؟

المحلول

C ++ مليء بالأخطاء ، لست متأكدًا مما إذا كنت قد حصلت عليه بشكل صحيح. أفضل ما يجب فعله هو إعلان DeviceIoControl () مع أنواع الوسيطة المتغيرة بحيث يكون من السهل الاتصال بها. يجب عليك أيضًا استدعاء 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);
}

نصائح أخرى

يمكنك استخدام بينفوك;

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

هذا المثال قد تساعد أيضا.

هناك الكثير من التعليمات البرمجية جاهزة لهذا على pinvoke.net مع الكثير من الأمثلة أيضًا.

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

انت كتبت:

يبدو أن gpd_type 56053كما هو محدد في الوثائق التي لم تكن صحيحة

هل يمكنك نشر القيمة المناسبة لـ gpd_type ?

أفضل Regadrs!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top