Search code examples
c#c++wpfpinvokedllimport

C++ Dll in WPF C# application


After looking for solutions already proposed to a similar question to mine, and since this is the first time I'm using a non-.NET DLL in a .NET application, I really need your help.

I have an WPF application, using MVVM Pattern, and in my ViewModel class I need to use a DLL done in C++ to recover a token. I have an example in C++ that uses this DLL, so I have the method's names, but I can't do the same in C#. I know that I must use DllImport to use this methods, but how implement it and use the pointer in C#??

#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <string>

int main()
{
    HINSTANCE hinst = NULL;

    typedef bool ( *GetTokenProto )( char ** );
    typedef void ( *FreeTokenProto )( char * );

    GetTokenProto GetToken;
    FreeTokenProto FreeToken;

    std::string str = "DllName.dll";
    std::string token;

    if ( (hinst = LoadLibraryA(str.c_str()) ) )
    {
        GetToken = (GetTokenProto) GetProcAddress(hinst, "GetToken");
        FreeToken = (FreeTokenProto) GetProcAddress(hinst, "FreeToken");

        if (GetToken && FreeToken)
        {
            char *buf;
            if (GetToken(&buf))
            {
                token = buf;
                FreeToken(buf);

                std::cout << "Token:" << token << std::endl;
            }
            else
            {
                std::cerr << "DLL loaded but no token" << std::endl;
                exit(1);
            }
        }
        else
        {
            std::cerr << "DLL loaded but missing proc address(es)" << std::endl;
            exit(1);
        }

        FreeLibrary(hinst);
    }
    else
    {
        std::cerr << "Failed to load DLL" << std::endl;
        exit(1);
    }
    return 0;
}

Update

[DllImport("DllName.dll", EntryPoint = "GetToken", CallingConvention = CallingConvention.Cdecl)] 
public static extern bool get_token(ref string token); 

[DllImport("DllName.dll", EntryPoint = "FreeToken", CallingConvention = CallingConvention.Cdecl)] 
public static extern void free_token(ref string token);

public static string a_token; 
public string get_token_method() 
{ 
    try 
    { 
        string buffer = null; 
        if (get_token(ref buffer)) 
        { 
            a_token = buffer; 
            free_token(ref buffer); 
            Debug.WriteLine("token : " + a_refresh_token); 
        } 
        else 
        { 
            Debug.WriteLine("DLL Loaded but no token"); 
        } 
    } 
    catch (Exception ex) 
    { 
       Debug.WriteLine("\n" + ex.Message); 
    } 
    return a_refresh_token; 
}

The error

I have an Exception "System.DllNotFoundException" : Unable to load DLL 'DllName.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E).

Dll file is in the same folder of the .exe (..\bin\Debug)


Solution

  • If your DLL is in the same Directory, there are still a few things that might be the problem.

    Firstly

    The DLL may have dependencies

    The native DLL you use may have other dependencies which have to be installed (try Dependency Walker). If the native DLL requires for example registry settings, config files etc. these should also be present. It should be distributed to user machines the same way you installed it on the dev machine.

    Most likely you are missing the C++ redistributable package (which one I'm not sure) however Dependency Walker should tell you.

    Secondly

    It could be targeting a different bitness i.e x86 x64, so I'd try changing your project to see if that helps

    • Right click your project, and select properties.

    • In properties, select the build tab. Under platform target, select x86.

    • Hit Ctrl+Shift+S to save all files, right click the solution and select "Clean" to get rid of old binaries. Any builds after that should be 32 bit