none
多個讀卡機同時在系統時,如何取得讀卡機列表? RRS feed

  • 問題

  • 在winscard.dll當中
    LONG SCardListReaders( 
      __in     SCARDCONTEXT hContext, 
      __in     LPCTSTR mszGroups, 
      __out    LPTSTR mszReaders, 
      __inout  LPDWORD pcchReaders 
    ); 
     
     

    這個function可以用來取得可用的讀卡機列表

    我用C# DllImport:
    public class SCard{ 
      ... 
      ... 
     
      [DllImport("winscard.dll")] 
      public static extern int SCardListReaders( 
        uint hContext,  
        string mszGroups,  
        ref IntPtr mszReaders,  
        ref int pcchReaders 
      ); 
      
      ... 
      ... 
    IntPtr mazReaders = new IntPtr(); 
    int pcchReaders=-1; //-1:SCARD_AUTOALLOCATE 
    SCard.SCardListReaders(hContext, null,ref mszReaders, ref pcchReaders); 
     
    string readerName=Marshal.PtrToStringAnsi(mszReaders); 
     
     


    這樣是可以取得第一台讀卡機的名稱,
    而pcchReaders好像是會將讀卡機裝置名稱的長度取出,
    但是要如何將第二台或第二台以上的裝置取出呢?

    希望知道的能給小弟指點一下
    2009年2月16日 上午 07:35

解答

  •  

    1 [DllImport(DllName, EntryPoint="SCardListReadersA", CharSet=CharSet.Ansi)]  
    2     public static extern int SCardListReaders(  
    3       int hContext,   
    4       byte[] mszGroups,  
    5       byte[] mszReaders,  
    6       ref UInt32 pcchReaders  
    7       );  
    8  
    9 //====================================================================================  
    10  
    11 long ret = 0;  
    12 int hContext;  
    13 Int32 pcchReaders = 0;  
    14 int nullindex = -1;  
    15 char nullchar = (char) 0;  
    16 ArrayList readersList = new ArrayList();  
    17  
    18 //establish context  
    19 ret = SCardEstablishContext(SCARD_SCOPE_USER,IntPtr.Zero,IntPtr.Zero,out hContext);  
    20  
    21 //get readers buffer len  
    22 ret = SCardListReaders(hContext,IntPtr.Zero,null,ref pcchReaders);  
    23 byte[] mszReaders = new byte[pcchReaders];  
    24  
    25 // fill readers' buffer  
    26 ret = SCardListReaders(hContext,IntPtr.Zero ,mszReaders, ref pcchReaders);  
    27  
    28 //fill readersList  
    29 //remember that readers is a multistring with a double trailing \0  
    30 // This is much easier and faster to do the allocation like this than the looping way  
    31 //ASCIIEncoding asc = new ASCIIEncoding();  
    32 //String[] Readers = asc.GetString( mszReaders ).Split( '\0' );  
    33 ASCIIEncoding ascii = new ASCIIEncoding();  
    34 string currbuff = ascii.GetString(mszReaders);  
    35 int len = pcchReaders;  
    36  
    37 while (currbuff[0]!=nullchar)  
    38 {  
    39   nullindex = currbuff.IndexOf(nullchar);   //get null end character  
    40   string reader = currbuff.Substring(0, nullindex);  
    41   readersList.Add(reader);  
    42   len = len-(reader.Length+1);  
    43   currbuff = currbuff.Substring(nullindex+1,len);              
    44 }  
    45  
    46 ret = SCardReleaseContext(hContext);  
    47  
    48  
    49  
    • 已提議為解答 cmf 2009年2月17日 上午 02:48
    • 已標示為解答 Lolota Lee 2009年2月23日 上午 02:22
    2009年2月17日 上午 02:41

所有回覆

  •  

    1 [DllImport(DllName, EntryPoint="SCardListReadersA", CharSet=CharSet.Ansi)]  
    2     public static extern int SCardListReaders(  
    3       int hContext,   
    4       byte[] mszGroups,  
    5       byte[] mszReaders,  
    6       ref UInt32 pcchReaders  
    7       );  
    8  
    9 //====================================================================================  
    10  
    11 long ret = 0;  
    12 int hContext;  
    13 Int32 pcchReaders = 0;  
    14 int nullindex = -1;  
    15 char nullchar = (char) 0;  
    16 ArrayList readersList = new ArrayList();  
    17  
    18 //establish context  
    19 ret = SCardEstablishContext(SCARD_SCOPE_USER,IntPtr.Zero,IntPtr.Zero,out hContext);  
    20  
    21 //get readers buffer len  
    22 ret = SCardListReaders(hContext,IntPtr.Zero,null,ref pcchReaders);  
    23 byte[] mszReaders = new byte[pcchReaders];  
    24  
    25 // fill readers' buffer  
    26 ret = SCardListReaders(hContext,IntPtr.Zero ,mszReaders, ref pcchReaders);  
    27  
    28 //fill readersList  
    29 //remember that readers is a multistring with a double trailing \0  
    30 // This is much easier and faster to do the allocation like this than the looping way  
    31 //ASCIIEncoding asc = new ASCIIEncoding();  
    32 //String[] Readers = asc.GetString( mszReaders ).Split( '\0' );  
    33 ASCIIEncoding ascii = new ASCIIEncoding();  
    34 string currbuff = ascii.GetString(mszReaders);  
    35 int len = pcchReaders;  
    36  
    37 while (currbuff[0]!=nullchar)  
    38 {  
    39   nullindex = currbuff.IndexOf(nullchar);   //get null end character  
    40   string reader = currbuff.Substring(0, nullindex);  
    41   readersList.Add(reader);  
    42   len = len-(reader.Length+1);  
    43   currbuff = currbuff.Substring(nullindex+1,len);              
    44 }  
    45  
    46 ret = SCardReleaseContext(hContext);  
    47  
    48  
    49  
    • 已提議為解答 cmf 2009年2月17日 上午 02:48
    • 已標示為解答 Lolota Lee 2009年2月23日 上午 02:22
    2009年2月17日 上午 02:41
  • 延伸問題
    EZ 100PU
    調用SCardStatus  發現  dwState 不準確.  只能用rv   Check.

            [DllImport("WinScard.dll")]  
            private static extern int SCardStatus(uint hCard, byte[] mszReaders, ref int pcchReaderLen, ref int pdwState, ref int pdwProtocol, byte[] pbAtr, ref int pcbAtrLen);  
     
     
     
     
     
           
     
             bool CardInReader( )  
            {  
                //檢查狀態  
                //取得狀態  
                int pcchReaderLen = 0;  
                int dwState = 0;  
     
                int dwProtocol = 0;  
                byte[] pbAtr = new byte[32];  
                int dwAtrLen = 32;  
     
     
                int rv = SCardStatus(_hCard, nullref pcchReaderLen, ref dwState, ref dwProtocol, pbAtr, ref dwAtrLen);  
     
     
                return ((rv==0)   );  
            }  
     
    2009年2月23日 上午 09:52