• 締切済み

C#でWin32 MFC DLLが呼び出せない

C#で以下のエラーが発生し、非常に困ってます。 色々とサイトを見たのですが、DLLが本当にないのでは?という意見が多かったです。 しかし、私の方はDLLファイルはbin->debugフォルダ , obj->debugフォルダ、System32に置いてます。 問題が分かる方、是非教えてください! using System.Runtime.InteropServices; namespace WindowsFormsApplication { public partial class Form1 : Form { [DllImport("Win32DLL_TEST.dll")] private extern static int func(int x, int y); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { int n = func3(5, 7);//ここでエラー! } } } エラー内容 'System.DllNotFoundException' のハンドルされていない例外が WindowsFormsApplication.exe で発生しました。 追加情報: DLL 'Win32DLL_TEST.dll' を読み込めません: 指定されたモジュールが見つかりません。 (HRESULT からの例外: 0x8007007E) 備考 DLLは自作のWin32 DLL です。 extern "C"{ __declspec(dllexport) int __cdecl func(int x, int y) } と宣言し、VC++のMFC dialog上では呼び出しを成功しています。

みんなの回答

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.4

作成中のCSのプロジェクトに MFC/非MFCのDLLとPDBを追加します ファイル > 追加 > 既存の項目 で 追加したファイルのプロパティの 出力ディレクトリーへコピーを常にコピー(または新しい場合はコピー) に設定します これで CSのbin\debug にDLLファイルがコピーされます MFC/非MFCで手順は変わりないと思いますよ …

  • chie65535
  • ベストアンサー率43% (8514/19356)
回答No.3

因みに、DLLを作った時に、Win32DLL_TEST.libも一緒に作成してある筈。 静的リンクでDLLを使う場合、上記のlibファイルを使用するようにプリプロセッサ命令で以下のように指示すると #pragma comment(lib, "Win32DLL_TEST.lib") リンカが自動的にDLLも一緒にリンクするようにプロジェクトが書き換えられるので、自分で「これもリンクして」と指示する必要は無い筈です。 要は #pragma comment(lib, "Win32DLL_TEST.lib") の1行をどっかに書き足せば、それですべてオッケー、と言う事です(静的リンクで済ますなら、です) 静的リンクなので「DLLを書き換えた場合はexeをリビルドする必要がある」と言うのを忘れないように。

  • chie65535
  • ベストアンサー率43% (8514/19356)
回答No.2

>[DllImport("Win32DLL_TEST.dll")] > private extern static int func(int x, int y); これだけじゃ、DLL内の関数は呼べない。 ・暗黙的(静的)リンクをする場合 DLLの関数を__declspecl(dllimport)を付けて宣言する。 リンカに「このDLLも一緒にリンクして」と指示する必要がある(リンクし忘れると実行時に'System.DllNotFoundException'例外が起きる) この場合、作成されるexeファイルにDLLの実体が取り込まれるので、後からDLLのみ変更する事はできない(後からWin32DLL_TEST.dllを変更しても、変更が反映されない。DLLを変更したら、exeをビルドし直さなければならない) 宣言したDLL関数は、そのまま呼び出せる。 ・明示的(動的)リンクをする場合 DLLの関数を宣言しない。 LoadLibraryのAPI関数で、dllファイルを自分でロードしなければならない。 GetProcAddressのAPI関数で、関数のアドレスを自分で取得してから呼び出さなければならない。 DLLは、実行時に「プログラムから明示的にロードされる」ので、一緒にリンクする必要はない。 この場合、作成されるexeファイルにはDLLの実体は取り込まれないので、後でDLLを変更すると、変更したDLLが呼び出される(後からWin32DLL_TEST.dllを変更すると、変更が反映される。exeをビルドし直す必要はない) --- 質問者さんがしなければならない事は、 ・DLLを「静的リンク」にするか「動的リンク」にするか選ぶ ・「静的リンク」を選んだ場合は、プロジェクトに「Win32DLL_TEST.dll」を追加し、ビルド時に一緒にリンクされるようにする。 ・「動的リンク」を選んだ場合は、関数宣言を削除し、LoadLibraryとGetProcAddressを駆使して、自分でDLLをロードして、自分で関数アドレスを取得して、自前で関数を呼び出すようにする。 と言う作業です。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

System.DllNotFoundExceptionが発生しているのであれば 自作のDLLが C#のbin\debugフォルダーに無いのが原因でしょう … 1つのソリューションに C#とVCのプロジェクトがあるのであれば C#は標準で そのソリューションフォルダー(またはプロジェクトフォルダー)のbin\debugがexeの出力先 VCは ソリューションフォルダーのdebugが出力先 となっているので確認してみましょう また DLL側の関数が __cdeclであるならば DllImportの CallingConventionをCdeclに設定したほうがいいでしょう

mindeyed
質問者

補足

アドバイス有難うございます。 フォルダ先にDLLがないか何回も確かめましたが、あります。 分かった事は、Win32(MFC無)のDLLを作成し、確認したところ C#側では正常に動作しました。 Win32(MFC無)、Win32(MFC付)で違いがあるという事です。 この点について原因、改善点が分かる方、是非お教えて頂きたいです。

関連するQ&A

  • VS2010C#からのDLL使用について

    VS2010 C#からVC6で作成したDLLへint配列を引数として渡したい。 VC++6で作成されたDLLがあります。 ここで定義されている int test(char*fname,int* x,int* y); ファイルのフルパスを渡すと 返り値が関数の成否のコードを返す。 処理内で x,y にファイルから読み込んだ値が それぞれ上限100個としてセットして返す といったような関数を C#から呼び出したいのですが 1 [DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)] public unsafe static extern int test(IntPtr fname, ref int* x,ref int* y); 2 [DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)] public unsafe static extern int test(IntPtr fname, ref IntPtr x,ref IntPtr y); と2種類の呼び出し方法をこころみました。 ファイルのフルパスは IntPtr fnamePtr = Marshal.StringToHGlobalAnsi(string型ファイルフルパス); としております。 1の場合は int[] resX = new int[100]; int[] resY = new int[100]; fixed(int* x= resX) fixed(int* x= resY) として呼び出そうとすると : エラー CS1657: '固定変数' であるため、'x' を ref または out 引数として渡せません となり失敗してしまいます。 2 で試みた場合 int size = sizeof(int)*100; IntPtr x = Marshal.AllocHGlobal(size); IntPtr y = Marshal.AllocHGlobal(size); と引き渡したところ ビルドは通りますが 実行時に System.AccessViolationException' のハンドルされていない例外が 発生しました。 追加情報: 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 となってしまいます。 どのようにすれば思惑通りの結果を得られますでしょうか。

  • C#から、C++作成dll内の関数を呼び出す方法

    C#から、C++で作成したdll内の関数を呼び出す方法は、以下の方法で実現できました。(メッセージボックスで "10" が表示されました) [C++側のヘッダファイル] #ifdef CPPDLL_EXPORTS #define CPPDLL_API __declspec(dllexport) #else #define CPPDLL_API __declspec(dllimport) #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ CPPDLL_API int fnCppDll(); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ [C++側のソースファイル] CPPDLL_API int fnCppDll() { return 10; } [C#側] using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApp1 { public partial class Form1 : Form { [DllImport("CppDll.dll")] public static extern int fnCppDll(); public Form1() { InitializeComponent(); } private void buttonGo_Click(object sender, EventArgs e) { int n = fnCppDll(); MessageBox.Show(n.ToString()); } } } 今回お聞きしたいのは、int型ではなく、C++側で型を定義されたクラスのオブジェクト(の参照)を返す関数を、C#側から呼び出し、それをどうやってC#で受け取るかを教えていただきたいのです。 具体的には以下のように実装してみました。 [C++側のヘッダファイル] #ifdef CPPDLL_EXPORTS #define CPPDLL_API __declspec(dllexport) #else #define CPPDLL_API __declspec(dllimport) #endif class CPPDLL_API CCppDll { public: int data; CCppDll(void); }; #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ CPPDLL_API CCppDll& fnCppDll(); // C#が参照渡しということで、参照を返すようにした。 #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ [C++側のソースファイル] CPPDLL_API CCppDll& fnCppDll() { CCppDll* a = new CCppDll(); return *a; } CCppDll::CCppDll() : data(11) // メンバーは 11 で初期化 { } [C#側] using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApp1 { // ビルドエラーが起きるないように、とりあえず、C++と同じ(ような)クラスを定義 public class CCppDll { public int data; } public partial class Form1 : Form { [DllImport("CppDll.dll")] public static extern CCppDll fnCppDll(); public Form1() { InitializeComponent(); } private void buttonGo_Click(object sender, EventArgs e) { int n; CCppDll cls = fnCppDll(); // ※ n = cls.data; MessageBox.Show(n.ToString()); } private void buttonCancel_Click(object sender, EventArgs e) { Close(); } } } 実装しながらも、「これじゃあ、ダメだろうな。いかにもダメだな」と思った通り、上の※の部分で以下の例外が発生しました。 ------- 例外(ここから) ------- マネージド デバッグ アシスタント 'FatalExecutionEngineError' : 'ランタイムの重大なエラーが発生しました。エラーのアドレスは 0xcc9ff5a2、スレッド 0x36c8 です。エラー コードは 0xc0000005 です。これは CLR のバグであるか、またはユーザー コードのアンセーフまたは確認不可能な部分にバグがある可能性があります。このバグの一般的な原因には、スタックが壊れる可能性のある COM-interop または PInvoke のユーザー マーシャリング エラーが含まれています。' ------- 例外(ここまで) ------- 明らかに基本的なことが分かっていないことから起因するエラーと思われますが、具体的にどう実装すれば、正常に動きますか。(メッセージボックスで "11" を表示) よろしくお願いします。

  • C++で作ったDLLをC#で使うには?

    C#でC++で書いたDLLを使いたいと思っていますが、可能でしょうか? 本で調べてみると出来ると思って挑戦しています。 public class Form1 : System.Windows.Forms.Form { [DllImport("test.dll")] public static extern long abc(); ..... と宣言し、使う時には long a = abc(); としています。 しかし、いざデバッグして実行してみると、エントリポイントが見つかりません。と表示されてしまいます。 (そもそもDLLが使えるのならばですが)できればC#でC++のDLLが使いたいため、詳しい方ご教授願います。

  • C#で、DLL内の関数へのthisの渡し方

    例えば以下のように、thisを引数として渡して thisに格納されたWitdhを表示するコードを書いてみたのですが DLL側で以下のようなエラーが出てうまくいきません。 何か引数の渡し方などに問題があるのでしょうか?ご指導お願いします(>o<) ※エラー 'ClassLibrary1.Form1.Dispose(bool)': オーバーライドする適切なメソッドが見つかりませんでした。 ■フォームアプリケーションのコード private void Form1_Load(object sender, EventArgs e) {   System.Windows.Forms.Form This_obj = new System.Windows.Forms.Form();   This_obj = this;   GetFormWidth(This_obj); } ■↓DLL内のコード public class DLL {   public static void GetFormWidth(System.Windows.Forms.Form Form_obj) {     //引数のwidthを表示する。     System.Diagnostics.Debug.WriteLine(Form_boj.Width.Tostring());   } }

  • C#からDLLを呼びたいのですが・・・

    C#のASP.NET WebアプリケーションのDLLをC#のWindowsFormのexeで呼び出そうとしています。 すると 'System.EntryPointNotFoundException' のハンドルされていない例外が FTPApi.exe で発生しました。 追加情報 : DLL SampleApi.dll の GetURL というエントリ ポイントが見つかりません。 というエラーメッセージが表示されてしまいます。 クラス上部で [System.Runtime.InteropServices.DllImport("SampleApi.dll", EntryPoint="GetURL")] public static extern string GetURL(); と宣言した後、呼び出したい場所で、 strUrlPath = GetURL(); と呼んでいます。 よろしくお願いします。

  • C#からDLLの呼び出し方

    visual studio 2008 express edition C#3.5 を使用しています。 http://www.hata.cc/docs/wlinee/1.html を参考にC++からではMySub関数を呼び出すことができたのですが、 C#から呼び出そうと次のように記述したのですが、 [System.Runtime.InteropServices.DllImport("a.dll")] extern int WINAPI MySub(int a, int b); 書き終わったときに、MySubの下に赤線がでて「;が必要です」 というエラーが出てしまいます・・・ たぶん「WINAPI」が認識されてないと思うのですが、 どのように記述すればよいのでしょうか? ~C++での記述~ [dllcall.cpp] #include "stdafx.h" #include <windows.h> #include <conio.h>  // getch( ) を使用するのに必要 extern int WINAPI MySub(int a, int b); int _tmain(int argc, _TCHAR* argv[]) { int c; c=MySub(9, 3); printf("ans=%d\n",c); getch();// キーが押されるまで待つ return 0; } [a.cpp] __declspec(dllexport)int WINAPI MySub(int a, int b) { return a-b; }

  • C#でのUNZIP32.DLLの利用方法が・・・

    「C#」で圧縮ファイルの中身を確認するためUNZIP32.DLLを利用しようと思うのですが、上手くいきません。 ためしに、UNZIP32.DLLのバージョン情報を獲得しようとしたのですが、以下のエラーが発生します。 'System.NuLLReferenceException'のハンドルされていない例外がWindowsApplication.exeで発生しました。 追加情報:オブジェクト参照がオブジェクトインスタンスに設定されていません。 ------------------------------------------- ソース ------------------------------------------- using System.Runtime.InteropServices; (略) [DllImport(@"D:\WINNT\system32\UNZIP32.DLL", EntryPoint="UnZipGetVersion")] public static extern string MyUnZipGetVersion(); (略) private void button1_Click(object sender, System.EventArgs e) { //MyMessageBox1(0,"by ANSI","Hello!",0); this.textBox1.Text = MyUnZipGetVersion(); } ご協力お願いします。(V^-°)

  • C++/CLIで、アンマネージC++のDLLを使用する方法

    こんにちは。 C++/CLIのプログラムで、アンマネージC++のDLLを使用したいと考えています。 ネット上をいろいろ調べたのですが、具体的な手段がわかりません。 見よう見まねで以下のようにサンプルを作成したのですが、コンパイルすら通る状況になりません。 かなり基本的な問題がありそうで申し訳ないのですが、下記の問題点を教えていただけないでしょうか。 また、参考になりそうなサイトなどありましたら教えていただけると大変助かります。 ■アンマネージC++のDLL VC++6.0で、以下のように、単にデバッグ文字列を書き出すだけのDLL関数を作成しました。 (このDLLが使用できることは他のVC++6.0プロジェクトで確認済みです) /*-----Func.h-----*/ #ifndef __FUNC_H__ #define __FUNC_H__ AFX_EXT_CLASS void WINAPI ShowMessage(); #endif //__FUNC_H__ /*-----Func.cpp-----*/ #include "StdAfx.h" #include "Func.h" #include <stdio.h> void WINAPI ShowMessage() { CString str = "This is The Message from DLL Func!\n"; OutputDebugString(str); } ■C++/CLI でのDLL使用 Visual Studio2008にて、C++のCLRプロジェクトを作成して、以下のようにDLLを使用する準備を行いました。 1.ソリューションエクスプローラのヘッダフォルダに、Func.hを追加 2.プロジェクトのフォルダに、上記で作成したFuncのDLLとLIBファイルを置く。 3.プロジェクトの「プロパティ > C/C++ > プリプロセッサ > プリプロセッサの定義」に、"_AFXDLL"を追加 4.mainクラスのソースに以下を記述 /*----------*/ using namespace System; #include "Func.h" #using "ManagedDllApp.dll" int main() { ShowMessage(); return 0; } /*----------*/ この状態でコンパイルすると、 「エラー 3 error C2144: 構文エラー : 'void' は ';' によって先行されなければなりません。 d:\xxx\Func.h 4 Console 」等、Func.h周りで複数のエラーが出ます。 また、Func.hをインポートしないでコンパイルすると、 「エラー 3 fatal error C1113: #using が 'd:\xxx\manageddllapp.dll' で失敗しました。 」と、Dllでエラーが出ます。 よろしくお願いいたします。

  • DLLの作成でで

    DLLの作成でで extern "C" int test(void) { int a; a=2; return a; } test の前のintは返す値の型なのでしょうか? もし文字を返す場合はcharでいいのでしょうか? また複数の値を返す場合は別に追加しなければいけないのでしょうか?よろしくお願いいたします。 初心者なので説明が下手ですがよろしくお願いいたします。

  • C# タスクバーを隠したフォーム固定の方法

    前略 ・C#の初心者です。 ・先日このMSN相談箱でtsukasa-12rさんからタスクバーを非表示する下記のプログラムをおしえていだきました。 このプログラムでウィンドウフォームを固定しようとして this.FormBorderStyle = FormBorderStyle.FixedSingle; のコードを1行だけ追加しましたがウィンドウフォームを固定できませんでした。  タスクバーを隠して かつウィンドウフォームを固定したいのですが tsukasa-12rさん以外の方でもかまいませんのでどなたか教えてください。  以上、よろしくお願いします //----------------------------------- using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, IntPtr lpWindowName); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); private const int SW_HIDE = 0; private const int SW_NORMAL = 1; [StructLayout(LayoutKind.Sequential)] struct APPBARDATA { public int cbSize; public IntPtr hwnd; public uint uCallbackMessage; public uint uEdge; public Rectangle rc; public int lParam; }; private const int ABM_SETSTATE = 10; private const int ABS_AUTOHIDE = 1; private const int ABS_ALWAYSONTOP = 2; [DllImport("shell32.dll")] static extern int SHAppBarMessage(int msg, ref APPBARDATA pbd ); public Form1() { InitializeComponent(); // 「タスクバーを自動的に隠す」 APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.lParam = ABS_AUTOHIDE; SHAppBarMessage(ABM_SETSTATE, ref abd); // タスクバーを非表示 ShowWindow(FindWindow("Shell_TrayWnd", IntPtr.Zero), SW_HIDE); // コントロールボックスを非表示 this.ControlBox = false; // 最大表示 this.WindowState = FormWindowState.Maximized; this.FormBorderStyle = FormBorderStyle.FixedSingle;// ← ウィンドウサイズを固定しようとして追加 → 固定できず } private void button1_Click(object sender, EventArgs e) { // タスクバーを常に表示 APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.lParam = ABS_ALWAYSONTOP; SHAppBarMessage(ABM_SETSTATE, ref abd); // タスクバーを表示 ShowWindow(FindWindow("Shell_TrayWnd", IntPtr.Zero), SW_NORMAL); // フォームを閉じる this.Close(); } } }

専門家に質問してみよう