2010-05-20 28 views
2

J'essaie de coder pour un système de point de vente qui permet une pièce jointe «Tiroir-caisse». Le code est fourni dans le manuel pour l'ouverture du tiroir-caisse (en C++ avec IOCTL). Puisque je code en C# .NET, est-il possible d'effectuer quelque chose de similaire à partir de C# ou devrais-je écrire du code non managé? Est-ce que je peux obtenir une poignée de "\\. \ ADVANSYS" de C#? Dois-je utiliser DLLImport?C# - Possibilité d'utiliser IOCTL

J'apprécierais que quelqu'un puisse me diriger dans la bonne 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); 
} 

Répondre

5

Le C++ est criblé d'erreurs, je ne sais pas si je l'ai bien compris. La meilleure chose à faire est de déclarer DeviceIoControl() avec des types d'arguments modifiés afin de faciliter l'appel. Vous devez également P/Invoke CreateFile car FileStream ne peut pas ouvrir les périphériques. Il devrait ressembler à ceci:

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

Merci Hans Passant. Je suis capable d'ouvrir le pilote de périphérique avec succès maintenant, mais l'appel DeviceIoControl produit "Win32Exception: Un périphérique attaché au système ne fonctionne pas." Je crois que cela pourrait être l'une des variables passées (ou type) ou la longueur du tampon. Je vais continuer à voir si je peux le faire fonctionner. – theblip

+0

Tout a fonctionné maintenant. Merci de votre aide. Il semblait que le GPD_TYPE 56053 tel que spécifié dans la documentation que j'avais était incorrect. – theblip

2

Vous pouvez utiliser 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 peut également aider.

1

vous avez écrit:

Il semblait que le GPD_TYPE 56053 comme spécifié dans la documentation que j'avais était pas correct

Pouvez-vous poster juste valeur de GPD_TYPE?

Les meilleurs regadrs!