Adding a DLL to my project

Posted on 2006-05-16
Last Modified: 2008-01-09

I have a DLL I'm trying to incorporate into my project, without luck.  The application used to make the DLL was MFC, I believe.  From Solution Explorer, I select to Add a Reference, switch to the COM page, and browse to select the DLL.  But when I press OK I get a failure messagebox, that it's not a valid assmebly of COM component.  I thought all DLLs were COM components.

I have the C++ header file by the same name as the DLL.

Any suggestions?

Question by:ba272
    LVL 48

    Expert Comment

    MFC dll can export classes and functions. If it exports functions, you can call them using PInvoke. If it exports classes, it cannot be called directly from C#, and it is necessary to write wrapper Dll. In both cases, MFC Dll cannot be added as reference to C# project.
    Post Dll interface h-file to see what happens.

    Author Comment

    #ifndef AIDAPI_INC
    #define AIDAPI_INC

    // Async ID transfer defines
    #define ASYNCTMRID (WM_USER + 1)
    #define EOTCHR 0xAA
    #define ESCCHR 0xBB
    #define IDCLRMSGLEN 8
    #define ASYNCIDTOSEC 5

    /* Returned from Base...
      '0' The command was successful.
      '1' The <ATT> character was issued before completion of the command (abort)
      '2' Bad Base Command (out of range or out of context as in Transfer Mode '1' and using Get ID Table cmd)
      '3' Failed CheckSum on transmission from the PC to the Base [not possible in LT product]
      '4' Failed Checksum on return from Badge to Base [not possible in LT product]
      '5' Timeout on transfer from PC to Base [not possible in LT product]
      '6' Timeout on transfer from Badge to Base (retries exhausted) [not possible in LT product]
      '7' Bit Error detected on transfer from Badge to Base [not possible in LT product]
      '8' Base EEProm write error
      '9' Network Busy  [not possible in LT product]

    /* Base Commands  -  AirID and/or LT
      'a' Get Base Version      AID/LT
      'b' Set Cycle Count       AID
      'c' Get Cycle Count       AID
      'd' Set Attenuation       AID/LT
      'e' Get Attenuation       AID/LT
      'h' Set ID Timeout        LT
      'i' Get ID Timeout        LT
      'j' Get ID Table          LT
      'k' Set Transfer Mode     LT
      'l' Get Transfer Mode     LT
    /* Badge Commands  -  AirID Only
      0 Get Mobile Version
      1 Set Password
      2 Get Password
      3 Address Probe
      4 Set Passcode
      5 Get Passcode
      6 Initialize Parameters
      7 Set Address
      8 Get Address

    class AidAPI
    // methods
      // construction / destruction
      virtual ~AidAPI();

      // implementation methods for Base Communications
      WORD GetBaseVersion( char *ver ); //'a' Get Base Version
      WORD SetBaseRetryCnt( WORD cnt ); //'b' Set Cycle Count
      WORD GetBaseRetryCnt( WORD *cnt ); //'c' Get Cycle Count
      WORD SetBaseRxAtten( WORD atten ); //'d' Set Attenuation
      WORD GetBaseRxAtten( WORD *atten ); //'e' Get Attenuation
      WORD SetIDTimeout( WORD to ); //'h' Set ID Timeout
      WORD GetIDTimeout( WORD *to ); //'i' Get ID Timeout
      WORD GetActiveIDs( WORD seed, DWORD *pdwtbl, WORD *cnt, WORD *auth ); //'j' Get ID Table
      WORD SetIDXfrMode( WORD mode, WORD seed ); //'k' Set Transfer Mode
      WORD GetIDXfrMode( WORD *mode ); //'l' Get Transfer Mode

      void InitAsyncProt( void );  // initialize Async xfr mode variables after each msg
      WORD PutAsyncXfrChr( WORD c ); // feed the Async xfr mode protocol received chrs
      WORD GetAsyncXfrData( DWORD *id, WORD *flags, WORD *key ); // call when PutAsyncXfrChr return TRUE

      // implementation methods for Badge Communications

      WORD GetBadgeVersion( DWORD Addr, char *ver ); //0      Get Mobile Version
      WORD SetBadgePassword( DWORD Addr, WORD bank, DWORD Pcd, char *pPwd ); //1 Set Password
      WORD GetBadgePassword( DWORD Addr, WORD bank, DWORD Pcd, char *pPwd, char *garbage ); //2 Get Password
      WORD ProbeBadge( DWORD Addr ); //3 Address Probe
      WORD SetBadgePasscode( DWORD Addr, WORD bank, DWORD newPcd ); //4 Set Passcode
      WORD GetBadgePasscode( DWORD Addr, WORD bank, char *pPwd, DWORD *pPcd ); //5 Get Passcode
      WORD InitBadge( DWORD Addr, WORD bank ); //6 Initialize Parameters
      WORD SetBadgeAddress( DWORD Addr ); //7 Set Address
      WORD GetBadgeAddress( DWORD Addr, DWORD *pRetAddr ); //8 Get Address (Probe w/ Addr return)

      virtual WORD CycleBaseCmd( BYTE *txbuf, WORD txcnt, BYTE *rxbuf, WORD rxcnt );
      virtual WORD CycleBadgeCmd( BYTE *txbuf, WORD txcnt, BYTE *rxbuf, WORD rxcnt );
      WORD WakeBase( void );
      WORD TxCmd( BYTE *buf, int cnt );
      WORD RxRsp( BYTE *buf, int cnt );
      int Authenticate(
                       WORD TxChlng,
                       WORD RxRsp,
                       BYTE *pTmrTbl,
                       int ntimers
      BYTE CalcChkSum( BYTE *pbuf, WORD cnt );
      BYTE rrc( BYTE *pbuf, BYTE carry, BYTE bytecnt );
      void Crypt(
                 BYTE *Address,
                 BYTE *ComKey,
                 BYTE *BankKey,
                 BYTE *inbuf,
                 BYTE cnt

      // pure virtual, user must fill these in
      // serial communications - Synchronous Mode Only!
      virtual WORD TxChr( WORD c ) = 0;
      virtual WORD RxChr( void ) = 0;

    // data
      BYTE TxBuf[64];
      BYTE RxBuf[64];
      BYTE CmdData[32];
      // Async transfer mode data
      BYTE AsyncMsg[32];  // Async mode msg buf
      WORD bAsyncMsg;
      int AsyncMsgChrCnt;  // Async mode - running count of chars
      BYTE AsyncMsgChkSum;  // Async mode - checksum accumulator
      int bAsyncRxProtInEsc;  // Async mode - flags ESC char received



    LVL 48

    Expert Comment

    This class cannot be imported directly to C# project. You must write wrapper, one of two types:
    1) C++ Dll which internally uses AidAPI class and exposes C-style API interface, which can be called by C# client using PINvoke.
    2) C++/CLI Class Library which internally uses AidAPI class end exposes to C# client pure .NET interface.

    To my opinion, second way is better.

    Author Comment


    I like option #2 as well.

    Do I use the C++ Class Library choice?  That's the second template in VS 2003 for C++ .NET projects.

    Is there an easy way expose the entire interface?  Or do I need to add the calls one at a time?

    LVL 48

    Expert Comment

    You need to create C++/CLI class library and add wrapper class to it. Inside of this class keep AidAPI member. For all AidAPI functions (or every function which is used by client) add function to wrapper class, translating native types to .NET types when necessary.
    Other way is to write more functionality to C++/CLI class. In this case you don't need to wrap every AidAPI function. For example, some wrapper function makes number of calls to AidAPI providing single call to C# client.
    LVL 48

    Expert Comment

    Actually, I found that this is not so simple - C++/CLI project cannot read MFC Dll. I will make some tests and return to this thread.
    LVL 11

    Assisted Solution

    actually you need to add an new dll between the mfc and the c++/cli
    one made in vsc++ 7.0, make a wrapper there, then use this wrapper in the c++/cli dll where you can expose the classes to .net

    LVL 11

    Expert Comment

    to be more clear. the dll i was talking about should be a mfc dll but made with 7.0
    LVL 48

    Expert Comment

    OK, this is working. C++/CLI client can work with MFC Dll. You can continue in this direction.

    Author Comment


    Author Comment

    When I created a Class Library (.NET) project, then attempted to add the DLL, I got an error when adding a reference to the DLL.  Any ideas what the problem is?

    Author Comment

    I get the exact error when I created a sample MFC Application and tried to add a reference to the same DLL.

    "Add Reference: Error adding reference to the project"
    LVL 48

    Expert Comment

    You need to add .lib file to the list of external dependencies for linker. Project - Properties - Linker - Additional Dependencies. Type here name of .lib file. Then add #include line and use this class.
    LVL 1

    Assisted Solution

    You need to use PINVOKE

    Author Comment


    I don't have a .lib file.  But I do have various dll's from which to choose.  How about the one with this header?  It appear to be more focused on what I want.  I do not have a .lib file for any of them though.

    Do I need an older version of Visual C++ in order to create the C++/CLI client you'd talked about, as Agarici suggests?



    #ifndef RFIDREAD_INC
    #define RFIDREAD_INC

    #define IDSTRRETBUF_SZ 32

    typedef enum eErrCode {
    } teErrCode;

    // CDECL type call
    typedef long (*GETPCPROXID)( DWORD, PSTR );
    // PASCAL type call

    //long GetPCProxID( DWORD dwOptions, char *szRetBuf );
      DWORD dwOptions
        1st (Low) Byte
          Low 4 bits is the Comm Port - 1 thru 15 (Zero will force a search from Comm1-4
          Upper 4 bits should be zero (undefined) - someday could specify USB options
        2nd Byte
          Low 4 bits is the Max Comm Port connect time in seconds - 0 thru 15
              On NT, the Comm I/O takes a while to come up.
              It's seldom ready when the GINA entry points are accessed.
              Set this to 15 then back off if you like.
          Upper 4 bits should be zero (undefined)
        3rd Byte
          Low bit:0 - '0'= no debug dialogs, '1'= use debug dialogs
          Others are undefined as yet.
        4th (High) Byte
          Undefined as yet.

      char *szRetBuf:
        Pointer to a buffer of minimum size IDSTRRETBUF_SZ
        which includes the space for the terminating NULL
        (the strlen is at most IDSTRRETBUF_SZ - 1).
        The string ID returned has little to do with the ID
        printed on most cards.  You may want to use a 'HASH'
        of this string to narrow a database search.  The ID
        from the internal reader may be up to 64 bits long
        and it is too difficult to deal with a 64 bit unsigned
        integer so we treat it as two 32 bit DWORDS.  The ID
        includes the 'Facility Code' data along with the ID
        within the particular FacCode.  The code below demonstrates
        how the String ID is constructed from two DWORDs.

      Returns: One of the 'eErrCode's listed above,
               eErrCode_None (0) is good.

      Remarks: The string buffer is NULL terminated before
               any processing starts (unless the pointer is NULL).
               So, given a non-NULL pointer, the buffer will be
               initialized to a zero-length string regardless
               of the overall outcome.
        The interface call is a 'cdecl' not a PASCAL type!!!
        i.e. don't use APIENTRY declaration or anything else that
        resolves to a PASCAL type call.

    // max string = "42949672954294967295" = 0xFFFFFFFF : 0xFFFFFFFF
    //            = 20 characters of ID + 1 NULL char = 21 char buf needed
    BOOL IDExToStrID( DWORD dwId, DWORD dwIdEx, char *szIdStrBuf )
      if( NULL == szIdStrBuf ) return FALSE;
      if( dwIdEx )
        sprintf( szIdStrBuf, "%lu%010lu", dwIdEx, dwId );
        sprintf( szIdStrBuf, "%lu", dwId );
      return TRUE;


    #endif //#ifndef RFIDREAD_INC
    LVL 48

    Accepted Solution

    To work with Dll which exports class, you need .lib file. If Dll exports functions, you can use PInvoke. IDExToStrID function can be called using PINvoke, but why do you need it?
    I hope you have an idea what functions do you need to used from this SDK. h-file must contain all of them. Currently, you posted AidAPI class, but you don't have .lib file, so this class cannot be used in .NET and in any previous versions. You posted also h-file which doesn't contain any useful stuff. This is not enough,  must be something else.

    Author Comment

    ok.  I'll keep looking.

    Featured Post

    Highfive + Dolby Voice = No More Audio Complaints!

    Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

    Join & Write a Comment

    Bit flags and bit flag manipulation is perhaps one of the most underrated strategies in programming, likely because most programmers developing in high-level languages rely too much on the high-level features, and forget about the low-level ones. Th…
    Introduction                                                 Was the var keyword really only brought out to shorten your syntax? Or have the VB language guys got their way in C#? What type of variable is it? All will be revealed.   Also called…
    To add imagery to an HTML email signature, you have two options available to you. You can either add a logo/image by embedding it directly into the signature or hosting it externally and linking to it. The vast majority of email clients display l…
    Internet Business Fax to Email Made Easy - With eFax Corporate (, you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

    728 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    17 Experts available now in Live!

    Get 1:1 Help Now