根据应用程序版本

时间:2016-05-28 12:20:07

标签: c# .net

我编写.net扩展名,可以加载到某些非托管应用程序的不同版本中。

下面我导入了some_func_v01some_func_v02some_func_v03函数:

[DllImport("some_library_v1.0.dll", CallingConvention = CallingConvention.Cdecl, 
    CharSet = CharSet.Unicode, EntryPoint = "func_name")]
extern static private void some_func_v01(string msg);

[DllImport("some_library_v2.0.dll", CallingConvention = CallingConvention.Cdecl, 
    CharSet = CharSet.Unicode, EntryPoint = "func_name")]
extern static private void some_func_v02(string msg);

[DllImport("some_library_v3.0.dll", CallingConvention = CallingConvention.Cdecl, 
    CharSet = CharSet.Unicode, EntryPoint = "func_name")]
extern static private void some_func_v03(string msg);

...

public void some_func(string msg) 
{
  switch (Application.Version.Major)
  {
    case 1: some_func_v01(msg); break;
    case 2: some_func_v02(msg); break;
    case 3: some_func_v03(msg); break;
  }
}

some_library库是目标应用程序的一部分,与应用程序具有相同的版本。

问题是,当出现新版本的应用程序时,我将编辑扩展程序的代码。我想根据应用程序版本动态生成代码。例如,对于应用程序版本1:

[DllImport("some_library_v1.0.dll", CallingConvention = CallingConvention.Cdecl, 
    CharSet = CharSet.Unicode, EntryPoint = "func_name")]
extern static private void some_func(string msg);

我可以通过PowerShell托管使用,但可能更简单的方式存在...我不想创建PowerShell托管只是为了执行此任务。

存在这种简单的方法吗?

2 个答案:

答案 0 :(得分:1)

我认为最好的解决方案是动态加载DLL。

使用WINAPI LoadLibraryGetProcAddress获取该函数的地址。然后使用Marshal.GetDelegateForFunctionPointer获取.net委托。

示例:

//skipping WINAPI native definitions
//you need to define delegate type:
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
delegate void MyFuncType(string msg);


//how to get delegate object:

var library = LoadLibrary(libraryNameChosenAtRuntime);
var funcPtr = GetProcAddress(library, funcName);
var func = Marshal.GetDelegateForFunctionPointer<MyFuncType>(funcPtr);

// now you can use func as delegate
// you can store this delegate object somewhere and reuse.
func("msg");

答案 1 :(得分:0)

由于您知道外部应用程序的版本,因此您也知道其目录,因此也知道外部应用程序目录中某处的外部dll的位置。您要忽略的是dll的后缀名称(示例中给出的版本v_1部分)。我相信在每个外部应用程序版本中只有一个版本的dll。

如果我的假设是正确的那么你就可以实现这一切:

  1. 选择始终位于文件名中的dll前缀,无论版本如何(&#34; some_library&#34;在您的示例中)
  2. 枚举外部应用程序目录或子目录中的dll位置中的所有文件(如果使用较旧的.NET,则为Directory.EnumerateFiles或.GetFiles)
  3. 找到与前缀匹配的文件名(&#34; some_library _ * .dll&#34;如示例中所示)
  4. 动态加载dll并调用函数(Oleh在回答中给出了一个很好的例子)。