14

何らかの理由で、私の C# .NET 2.0 アプリケーションが呼び出しを行うたびに、GetProcAddress常にゼロが返されます。

public class MyClass
{
    internal static class UnsafeNativeMethods
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern bool SetDllDirectory(string lpPathName);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
    }

    private void MyFunc()
    {
        IntPtr _dllHandle;
        IntPtr _fptr;
        string _fullPath = ".\\mydll.dll";
        string _procName = "MyDllFunc";

        _dllHandle = UnsafeNativeMethods.LoadLibrary(_fullPath);
        _fptr = UnsafeNativeMethods.GetProcAddress(_dllHandle, _procName); // <-- Always returns zero.
    }
}

関数名のスペルが正しいと確信しており、常にゼロ以外の値が割り当てられている_fullPathため、おそらく正しいと思われます。_dllHandleあなたが提供できるかもしれないどんな洞察も高く評価されます。ありがとう。

4

4 に答える 4

19

GetProcAddress は ANSI フレーバーでのみ提供されるため、文字列パラメーターをマーシャリングするときに常に ANSI を使用するようにランタイムに指示することで、ランタイムを支援します。また、C# のデフォルトでは ExactSpelling が false に設定されているため、ランタイムが存在しない GetProcAddressA を探すのを防ぎます。

http://www.pinvoke.net/default.aspx/kernel32.getprocaddress

于 2010-09-20T18:38:14.173 に答える
2

エラーチェックを追加する必要があります。少なくとも、_dllHandle != IntPtr.Zero かどうかを確認してください。また、現在の作業ディレクトリによっては危険なので、Assembly.GetEntryAssembly().Location を使用してフルパス名を取得します。

関数名が間違っている可能性があります。エクスポートは、_MyDllFunc や _MyDllFunc@4 のように装飾される傾向があります。C++ コンパイラでコンパイルされた場合はさらに乱暴になります。実際の名前を表示するには、DLL で Dumpbin.exe /exports を使用します。

エラー処理に戻ると、[DllImport] 属性で SetLastWin32Error を使用します。関数が false または IntPtr.Zero を返す場合、Win32Exception をスローします。


編集:本当の問題がわかります。GetProcAddress() に CharSet.Auto を使用するのは間違っています。非常に不運なことに、ANSI バージョンしかない唯一のWindows API 関数です。CharSet.Ansi を使用する必要があります。適切な [DllImport] 宣言を取得するのに適した場所は、pinvoke.net です。

于 2010-09-20T18:34:11.863 に答える
1

DLL から関数をエクスポートする方法を示していませんが、問題は、エクスポートされた名前があなたの意図とは異なることだと思います。実行dumpbin /exports mydll.dllして dll のエクスポートを表示し、名前を確認できます。

エクスポートのコード スニペットを見せていただければ、より直接的なアドバイスを提供できます。エクスポートされた関数を でデコレートしextern "C"て、テストとして名前マングリングをなくすことができます。

于 2010-09-20T18:33:43.217 に答える
0

DLL の .DEF ファイルのエクスポートは、ここでの入力と一致しますか? dumpbinここで他の返信ごとに、エクスポートされたものを見つけるために使用できます。

の根本的な Win32 エラーは何GetProcAddress()ですかGetLastError()?

P/Invoke の追加の荷物なしで、最初に正しい入力を解決するために、ネイティブ コードでこれを試すことができます。

于 2010-09-20T18:36:02.920 に答える