C#からネイティブDLLを呼び出す場合のVSからのデバッグのジレンマを解決する

C#を使う最大のメリットって、やっぱり、Visual Studioですよね!」って自信を持って言いたいですね。

という心境ではあるんですが、私の仕事はどっちかというとC++よりなので、どうしても、DllImportはお友達という側面があります。そうすると、プログラム実行時に、

AnyCPUなアセンブリ.exe
ネイティブC++.dll

みたいな感じになって、要は、AnyCPUなアセンブリがネイティブC++ちゃんを呼び出す構図になるんですが、この構成、64-bitの環境で開発をしていたりすると相当なジレンマを抱えることになります。

普通に実行する場合には、x64環境なので、「ネイティブC++.dll」さんは、64-bit版を配置しておくべきなんですが、VS上からデバッグしようとすると、win32(32-bit版)を置いておかないと行けなかったり、あるいは、「ネイティブC++.dll」さんのデバッグ版は激遅なので、デバッグ中でも普通はリリース版を置いておきたかったりと、様々な面倒なシチュエーションに出くわすことになります。

で、これを解決する方法を考えたよという話です。
簡単に言うと、

AnyCPUなアセンブリ.exe
win32/
  ネイティブC++.dll
x64/
  ネイティブC++.dll

というディレクトリ構成にしてしまえという。「AnyCPUなアセンブリ.exe」は、賢いので、自分が実行されている環境に応じて、どっちをロードするか見てくれるという。

で、どうするかというと、次みたいなコードをアプリに取り込んでしまえという。
これは、MainWindow.xaml.csとかの例ですが、もっと早い段階がよければ、そこでやっても良いですね:

static MainWindow()
{
  SetDllDirectory("");
#if DEBUG
  if (setDllLocation(true))
    return;
#endif
  setDllLocation(false);
}

/// <summary>
/// Controlling DLL directory which native DLLs are loaded from.
/// </summary>
/// <param name="debug">Whether this is debug mode or not.</param>
/// <returns><c>true</c> if DLL directory is correctly set; otherwise <c>false</c>.</returns>
static bool setDllLocation(bool debug)
{
  var appDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
  if (debug) appDir = Path.Combine(appDir, "debug");
  var dllDir = Path.Combine(appDir, IntPtr.Size == 8 ? "x64" : "win32");
  if (Directory.Exists(dllDir))
  {
    Debug.WriteLine(string.Format("Set DLL Location ({0}): {1}", debug ? "Debug" : "Release", dllDir));
    SetDllDirectory(dllDir);
    return true;
  }
  return false;
}

[DllImport("Kernel32.dll")]
static extern bool SetDllDirectory(string lpPathName);

やってることの内容としては、 SetDllDirectory APIを呼び出して、DLLをロードするディレクトリを事前に変更しておこうと。
C++だと、delayloadがらみを調整して同じような事が出来ますが、C#でのDllImportは完全に実行時にバインディングを解決することになるので、かなりこういう芸当がやりやすいです。

で、上のコードにはオマケがあって、デバッグ版では、さらに、

AnyCPUなアセンブリ.exe
debug/
  win32/
    ネイティブC++.dll
  x64/
    ネイティブC++.dll

みたいなレイアウトにしておけば、デバッグ版のDLLを見つけてロードしてくれると。
いずれにしても、デバッグ時にDLLをコピーしたり移動したりの右往左往がかなり軽減されるという意味では開発が楽になると思います。

原文地址:https://www.cnblogs.com/xpvincent/p/9903416.html

时间: 2024-09-30 03:31:25

C#からネイティブDLLを呼び出す場合のVSからのデバッグのジレンマを解決する的相关文章

[SharePoint 2010]Sandboxed Solution (沙箱解決方案)

現有的SharePoint 2007系統中,我們如果要安裝客製化的程式碼到系統中,我們必須製作一個解決方案包裝檔(Solution Package),然後在系統的中央管理後台中,真對整個伺服器農場Farm發佈出去. 使用解決方案包裝檔(Solution Package)的好處是在一個多台伺服器的環境中可以一次性將客製化程式碼發佈出去. 然而, 現有的解決方案包裝檔可以存取每一台伺服器上的資源,而且我們為了方便通常會給予很高的執行權限或者是將它部屬到Global Assembly Cache中.

技术解析:锁屏绕过,三星Galaxy系列手机也能“被”呼出电话

近期,由两位安全研究人员,Roberto Paleari及Aristide Fattori,发布了关于三星Galaxy手机设备安全漏洞的技术细节.据称,Galaxy手机可在锁屏状态下被未授权的第三方人员用以进行电话外呼和短信发送. 锁屏绕过概述 根据Roberto Paleari及Aristide Fattori发布的技术细节可知,攻击者可借助对手机设备的临时访问或窃取受害用户手机的方式,通过USB接入手机设备并将之连接到Linux工作平台上,最后发送指令来实现电话呼叫及短信发送. 而该方式并没

一键呼出小米羊城通刷卡

小米5可以用羊城通直接刷公交和地铁,非常方便,唯一美中不足的地方是: 需要在锁屏/黑屏的情况下,长按音量下键或者双击Home键,才能呼出羊城通刷卡界面. 那如果我在需要刷羊城通时,已经进入了桌面,那我就必须先按关机键锁屏,再长按音量下键,才能呼出羊城通界面,有强迫症的人表示伤不起.解决这种问题,其实写个程序就可以了. 1.   先呼出羊城通界面,然后用adb命令查看顶级Activity的相关信息. adb 命令:adb shell ddumpsys activity activities 信息如

iOS中如何呼出另一个应用

我们经常会遇到在一个应用里面呼出另一个应用的需求,比如在文档里面点击地址,调用safari来打开网页:比如在文件浏览器里面点击某种文件,自动激活一个应用来打开文件. iOS里面对于这样的需求使用URL来实现,把其他的应用看成一种资源,本质上就是调用系统资源. 我们有两个应用App1和App2,在App2里面呼出App1,那么首先要配置App1,让系统认识App1的URL,这个就是配置info.plist文件的某些项,在Xcode里面就是配置一些选项,在Xcode4.6.2里面的样子如下图: 这样

SAMETIMESでチャートする時ウィンドウを出るの解決策

→ SAMETIMESでチャートする時ウィンドウを出るの解決策

日常问题解决记录一:远程桌面进程如果关闭了怎么呼出?

手贱如我,杀进程杀出一片蓝,如下图所示. 这种情况怎么呼出远程桌面呢? 1)使用键盘按键 Ctrl+Alt+End 呼出远程桌面的任务管理器 2)文件-新建任务,打开 C\Windows\explorer.exe 即可

vos设置可呼出手机或固话

问题: 默认公司只让呼出手机号码,但有的客户要求能打固话,怎么办? 落地网关--补充设置--落地前缀--落地被叫改写规则 在改写规则里添加固话号段即可 具体案例: 5201--1表示让520号段只能拨打1开头的号段,即只能拨打手机号 91502--02表示可以拨打02开头的号段,02开头的号段为固定电话号段

Lync 项目经验-40-Skype for Business-呼入正常-呼出不正常

项目环境: 在家部署一个Skype for Business Server 2015环境,实现: 1. 电脑,移动客户端,内部外部登录,没问题. 2. 电脑,移动客户端,内部外部音频和视频,没问题. 项目问题: 结果菲律宾客户要看测试效果. 结果: 1. 电脑,移动客户端,内部外部登录,没问题. 2. 电脑,移动客户端,内部外部音频和视频,呼入没问题,呼出总不行. 解决方案: 因为以前做过无数次培训,项目,非常自信不会有问题,但总这样那样问题,最终排错,常见问题如下: 1. 证书 如果,使用公网

gentoo emacs 中文输入法 呼出

最近在另外一台电脑上面安装 gentoo和 emacs,但是碰到奇怪的问题,在旧电脑上面,可以使用 ctrl + space 呼出输入法,而新电脑只能触发 复制功能. 经过在网上查找和两台电脑之间的对比,找到了解决方法. 首先使用 locale -a 来查看电脑是否支持 zh_CN.utf8 或者 zh_CN.UTF-8, 然后在 .bachrc 中设置 LC_CTYPE = zh_CN.utf8 或者 UTF-8. 我用的是 i3wm,所以在 .xinitrc 中设置 export GTK_I