C # - Possibilità di utilizzare IOCTL
Domanda
Sto cercando di codice per un punto di vendita sistema che consente un fissaggio "cassetto contanti". Codice viene fornito nel manuale per aprire il cassetto (in C ++ utilizzando IOCTL). Dal momento che sto codifica in C # .NET, è possibile eseguire qualcosa di simile all'interno di C # o dovrò scrivere del codice non gestito?
Sono io in grado di ottenere una maniglia per "\\. \ Advansys" dal di dentro C #? Ho bisogno di usare DllImport?
sarei grato se qualcuno mi potrebbe punto nella giusta direzione.
// 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);
}
Soluzione
Il C ++ è pieno di errori, non so se ho capito bene. La cosa migliore da fare è quello di dichiarare DeviceIoControl () con tipi di argomenti alterati in modo che sia facile da chiamata. Hai anche a P / Invoke CreateFile perchè FileStream can dispositivi non aperti. Dovrebbe essere simile a questo:
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);
}
Altri suggerimenti
È possibile utilizzare 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);
Questo esempio potrebbe anche aiutare.
C'è un sacco di codice pronto per questo su pinvoke.net con abbondanza di esempi troppo.
http://www.pinvoke.net/default.aspx/kernel32.DeviceIoControl
ha scritto:
Sembrava che il GPD_TYPE 56053 come specificato nella documentazione Che avevo non era corretto
Puoi pubblicare il corretto valore di GPD_TYPE
Le migliori regadrs!