1

メソッドにアクセスする必要のあるDLLがあります。

このようなほとんどの場合、[DllImport]を使用してアンマネージアセンブリからメソッドにアクセスしますが、この状況での問題は、インスタンス化時にDLLへのパスが必要になるため、文字列が一定になることです。

この特定のDLLは私のアプリケーションとともにインストールされるものであり、プログラムのインストール後にどこにあるかを保証することはできません(%SystemRoot%のような静的な場所に配置したくない)。

では、C#には、実行時に可変パスを使用してDLLからメソッドを宣言して使用できる方法がありますか?

任意のアイデアや提案をいただければ幸いです!

4

3 に答える 3

2

パスはまったく使用しないでください。Windowsは、DLLから関数を動的または静的にロードしようとするときに、デフォルトの方法でDLLを検索します。

正確な検索ロジックは、MSDNのLoadLibraryのドキュメントに記載されています。基本的に、DLLがアプリで使用されるだけの場合は、インストール中にアプリケーションと同じフォルダーに配置します。心配する必要はありません。一般的に使用されるDLLの場合は、LoadLibrary()で検索されたフォルダー構造のどこかに置くと、見つかります。

于 2009-04-10T19:22:56.233 に答える
2

これはちょっとしたハックですが、実行時にdllへのパスを見つけることができると言っているので、関数を使用する前に、現在の作業ディレクトリにそれをコピーしてみませんか?そうすれば、dllはexeの隣に存在し、LoadLibraryによって検出されます。DllImportに追加のパスは必要ありません。

動的パスからメソッドを使用する他の唯一の方法は、これを行うことです
。1)LoadLibraryGetProcAddress
に必要なP / Invokeシグネチャを実行し ます。2)目的のパスからライブラリをロードします(LoadLibrary)
3)目的の関数を見つけます(GetProcAddress )
4)ポインタをデリゲートMarshal.GetDelegateForFunctionPointer
にキャストします 。5)それを呼び出します。

もちろん、ポインタをデリゲートにキャストする必要があるため、この方法で「インポート」する関数ごとにデリゲートを宣言する必要があります。

于 2009-04-10T20:00:30.450 に答える
0

私も同じような状況でした。マシンにインストールされているSDKのDLLを使用しています。そのSDKレジストリキーからDLLのディレクトリの場所を取得します。実行中のユーザーのPATH変数にDLLの場所を設定しました(一時的な変更のみ)。基本的に、呼び出すDLLの動的パスを設定できるため、レジストリからのものである必要はありません。PATH変数は、WindowsがDLLを探す最後の場所であることに注意してください。ただし、一方で、WindowsがDLLを検索する他の場所は変更されません。

例:

DLLで呼び出したいAPI:

[DllImport("My.DLL")]
private static extern IntPtr ApiCall(int param);

レジストリキーを取得します( Microsoft.Win32;を使用する必要があります):

private static string GetRegistryKeyPath() {
        string environmentPath = null;

        using (var rk = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\SOMENNAME"))
        {
            if (rk != null)
            {
                environmentPath = rk.GetValue("Path(or whatever your key is)").ToString();
            }
            if (string.IsNullOrEmpty(environmentPath))
            {
                Log.Warn(
                    string.Format("Path not found in Windows registry, using key: {0}. Will default to {1}",
                         @"SOFTWARE\SOMETHING", @"C:\DefaultPath"));
                environmentPath = @"C:\DefaultPath";
            }
        }
        return environmentPath;
     }

PATH変数にDLLのパスを追加します(Concat()はLinqにあります):

void UpdatePath(IEnumerable<string> paths){
    var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? "" };
    path = path.Concat(paths);
    string modified = string.Join(Path.PathSeparator.ToString(), path);
    Environment.SetEnvironmentVariable("PATH", modified);
}

API呼び出しの使用を開始します。

var sdkPathToAdd = GetRegistryKeyPath();
IList<string> paths = new List<string>
        {
            Path.Combine(sdkPathToAdd),
            Path.Combine("c:\anotherPath")
        };
UpdatePath(paths);

//Start using
ApiCall(int numberOfEyes);
于 2015-08-14T13:43:05.770 に答える