MissingMethodException - Can't find PInvoke DLL "TestDLL.dll" - Unable to invoke a function in imported DLL in C# mobile app.
-
Wednesday, June 24, 2009 5:32 PM
Hi,
I have a simple form application in C# that calls a function in an imported dll. I get a missingMethodException on calling that function. I have read all the related threads in the forum but nothing seems to be working for me.
Exception I get:
System.MissingMethodException was unhandled Message="Can't find PInvoke DLL 'TestDLL.dll'." StackTrace: at SmartDeviceProject1.Form1.button1_Click() at System.Windows.Forms.Control.OnClick() at System.Windows.Forms.Button.OnClick() at System.Windows.Forms.ButtonBase.WnProc() at System.Windows.Forms.Control._InternalWnProc() at Microsoft.AGL.Forms.EVL.EnterMainLoop() at System.Windows.Forms.Application.Run() at SmartDeviceProject1.Program.Main() InnerException:
Here is my C# solution (Target device - Windows Mobile 6 Professional Device .NET CF 2.0) . It consists of two projects.
SmartDeviceProject1:
Here are the testdll project files:namespace SmartDeviceProject1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { //displayString.Text = "test"; displayString.Text = Convert.ToString(NativeMethods.fnTestdll()); } } internal abstract class NativeMethods { [DllImportAttribute("TestDLL.dll", EntryPoint = "fnTestdll", CallingConvention = CallingConvention.Winapi, SetLastError = false, CharSet = CharSet.Unicode)] public static extern int fnTestdll(); } }
// Testdll.cpp : Defines the entry point for the DLL application. // #include "stdafx.h" #include "Testdll.h" BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } // This is an example of an exported variable TESTDLL_API int nTestdll=0; // This is an example of an exported function. TESTDLL_API int fnTestdll(void) { return 42; } // This is the constructor of a class that has been exported. // see Testdll.h for the class definition CTestdll::CTestdll() { return; }testdll.h
// The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the TESTDLL_EXPORTS // symbol defined on the command line. this symbol should not be defined on any project // that uses this DLL. This way any other project whose source files include this file see // TESTDLL_API functions as being imported from a DLL, whereas this DLL sees symbols // defined with this macro as being exported. #ifdef TESTDLL_EXPORTS #define TESTDLL_API __declspec(dllexport) #else #define TESTDLL_API __declspec(dllimport) #endif // This class is exported from the Testdll.dll class TESTDLL_API CTestdll { public: CTestdll(void); // TODO: add your methods here. }; extern TESTDLL_API int nTestdll; TESTDLL_API int fnTestdll(void);I have spend enough time on this, any help is greatly appreciated.
Thanks.- Edited by Jason.Smith Friday, June 26, 2009 5:29 PM fixing double-encoding in title
All Replies
-
Wednesday, June 24, 2009 5:49 PMModerator
That can be because:
- You don't have this DLL in the correct location (which is either your main application location or \windows).
- DLL needs dependencies which are missing (e.g. MFC).
- DLL is compiled for wrong CPU.
- DLL does not export required entry points.- Exported name is mangled.
You can use depends or dumpbin tools to check most of these issues. Use file explorer on device to check first one.
This posting is provided "AS IS" with no warranties, and confers no rights.- Proposed As Answer by Mal Loth Wednesday, June 24, 2009 6:28 PM
- Marked As Answer by warrentangModerator Wednesday, July 01, 2009 12:55 AM
-
Wednesday, June 24, 2009 6:23 PM
- I put the testdll.dll in main application location (on device) and also in \windows on device.
- DLL had a dependency on coredll.dll which depends.exe could not locate on my desktop. However, I see that coredll.dll in located in \windows on device.
- I am compiling for "platform: Windows mobile 6 Professional SDK ARMV4I" in Visual studio which is the same as my device's.
- Here is partial dumpbin output (seems like it does export the symbols).
Section contains the following exports for Testdll.dll 00000000 characteristics 4A42615E time date stamp Wed Jun 24 10:24:46 2009 0.00 version 1 ordinal base 4 number of functions 4 number of names ordinal hint RVA name 1 0 00001060 ??0CTestdll@@QAA@XZ = ??0CTestdll@@QAA@XZ (public: __cdecl CTestdll::CTestdll(void)) 2 1 00001000 ??4CTestdll@@QAAAAV0@ABV0@@Z = ??4CTestdll@@QAAAAV0@ABV0@@Z (public: class CTestdll & __cdecl CTestdll::operator=(class CTestdll const &)) 3 2 00001048 ?fnTestdll@@YAHXZ = ?fnTestdll@@YAHXZ (int __cdecl fnTestdll(void)) 4 3 00003028 ?nTestdll@@3HA = ?nTestdll@@3HA (int nTestdll) Section contains the following imports: COREDLL.dll 10003000 Import Address Table 10002044 Import Name Table 0 time date stamp 0 Index of first forwarder reference Ordinal 36
-
Wednesday, June 24, 2009 6:28 PM
You must use DATA in def file or else the names of Your methods and classes will be mangled as mr Ilya Tumanov said .
Look under this discussion which I've done paralel with Yours.
If You'll find my answer satisfactory or helpful - mark it as answered! Thank You. PS. Votes also doesn't hurt :).- Proposed As Answer by Mal Loth Wednesday, June 24, 2009 6:28 PM
-
Wednesday, June 24, 2009 6:52 PM
I tried that but it's of no avail. I put the TestDLL.dll file in the same location as programfiles\SmartDeviceProject3\ which contains SmartDeviceProject3.exe - my application.
testDLL.def
LIBRARY "TestDLL" EXPORTS GetNumber DATA
-----------------------------------------------------------------
TestDLL.cpp
#include "stdafx.h" BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; } int GetNumber() { return 42; }---------------------------------------------
C# code:
namespace SmartDeviceProject3 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { displayString.Text = Convert.ToString(NativeMethods.GetNumber()); } } internal abstract class NativeMethods { [DllImportAttribute("TestDLL.dll", EntryPoint = "GetNumber")] public static extern int GetNumber(); } } -
Wednesday, June 24, 2009 8:31 PM
I see You don't like reading :). It should be like this:
C# code:
namespace SmartDeviceProject3
{
public partial class Form1 : Form
{
[DllImport("testdll.dll", EntryPoint = "GetNumber")
private static extern int GetNumber();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
displayString.Text = Convert.ToString(GetNumber());
}
}
}
The rest is ok.
If You'll find my answer satisfactory or helpful - mark it as answered! Thank You. PS. Votes also doesn't hurt :). -
Wednesday, June 24, 2009 9:16 PM
It didn't help. Here is my latest attempt as you have suggested:
namespace SmartDeviceProject3 { public partial class Form1 : Form { [DllImport("testdll.dll", EntryPoint = "GetNumber")] private static extern int GetNumber(); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { displayString.Text = Convert.ToString(GetNumber()); } } }I tried to DllImport the coredll.dll and it is getting loaded and I am able to invoke a function in that DLL. which possibly means system DLLs don't have an issue with DllImport. Since mine is a test dll could there be anything related to security\signing? Should I disable security policy or something? -
Thursday, June 25, 2009 11:11 AMHmm, maybe. Did You checked "Allow Unsafe Code" in application properties on C# side?
If You'll find my answer satisfactory or helpful - mark it as answered! Thank You. PS. Votes also doesn't hurt :). -
Thursday, June 25, 2009 4:22 PMYes, tried that too. I just copy the testdll.dll to my device into the appropriate folders (i.e. where my <application>.exe resides and into the \windows folder). Is that enough or should I be doing anything extra? This is the first time I am writing a mobile app, so please bear with me if I ask fundamental questions.
-
Thursday, June 25, 2009 8:07 PM
Just one copy of testdll.dll next to Your application should do the trick.
Must be in the same folder as the .exe which is calling it.
I wonder where do You have problems, because I did it many times and I know it works in both emulator and device.
Maybe something is too obvious for me and I forgot to tell You about it... Hmm.
If You'll find my answer satisfactory or helpful - mark it as answered! Thank You. PS. Votes also doesn't hurt :).- Marked As Answer by warrentangModerator Wednesday, July 01, 2009 12:55 AM
-
Sunday, July 19, 2009 6:53 PM
Hello, this is my first post to a software dev. forum. Is it possible that a very long directory path to the native *.dll that I try to import, can cause problems?
NOTE: I am running it through a simple windows mobile form via WM 6 Pro Emulator, the current DLL path is %mylongprojectpath%/bin/debug/*.dll (on my windows Vista PC) and I get the same MissingMethodException for PInvoke as mentioned previously.
Also: I used the following definition for writing my custom *.cpp file(which I saved as "Unicode" and compiled from VStudio command line with "/LD" option):
extern "C" __declspec(dllexport) string outmsg () {body of function returning a string message}
The Csharp definition I am trying to use it with is as below:
namespace
MobTest1 {
public partial class Form1 : Form {
[
DllImport("myseconddll22.dll")]
private static extern string CallNative();
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e){
MessageBox.Show(CallNative());
}
}
}
Very simple, yet I would really appreciate it if you could say what you think I should do since I am a complete beginner with PInvoke.
Thank you. -
Sunday, March 21, 2010 4:50 PM
Please see possible solution for you in this thread:
- Proposed As Answer by SandySears Sunday, March 21, 2010 4:50 PM

