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をコピーしたり移動したりの右往左往がかなり軽減されるという意味では開発が楽になると思います。
C#からネイティブDLLを呼び出す場合のVSからのデバッグのジレンマを解決する的更多相关文章
- [SharePoint 2010]Sandboxed Solution (沙箱解決方案)
現有的SharePoint 2007系統中,我們如果要安裝客製化的程式碼到系統中,我們必須製作一個解決方案包裝檔(Solution Package),然後在系統的中央管理後台中,真對整個伺服器農場Fa ...
- 假如现在有一堆长度大于3小于9的电话号码,用座机呼叫,如果出现这样的号码【123和12345】那么12345将永远不会被拨出,因为拨到123的时候电话已经呼出了,试写一个函数输出所有不能被呼出的电话号码(java实现)
解题: 假如现在有一堆长度大于3小于9的电话号码,用座机呼叫,如果出现这样的号码[123和12345]那么12345将永远不会被拨出,因为拨到123的时候电话已经呼出了,试写一个函数输出所有不能被呼出 ...
- 技术解析:锁屏绕过,三星Galaxy系列手机也能“被”呼出电话
近期,由两位安全研究人员,Roberto Paleari及Aristide Fattori,发布了关于三星Galaxy手机设备安全漏洞的技术细节.据称,Galaxy手机可在锁屏状态下被未授权的第三方人 ...
- asterisk中使用dahdi通道呼出的注意事项
asterisk中使用dahdi通道呼出的注意事项 在使用dahdi通道呼出的时候,可以在Dial中对呼出所使用的通道进行指定选择.以下面的例子来说明: 场景说明:数字板卡单E1,使用pri信令,1- ...
- iOS中如何呼出另一个应用
我们经常会遇到在一个应用里面呼出另一个应用的需求,比如在文档里面点击地址,调用safari来打开网页:比如在文件浏览器里面点击某种文件,自动激活一个应用来打开文件. iOS里面对于这样的需求使用URL ...
- 在动态链接库dll中弹出对话框
在动态链接库dll中弹出对话框步骤: 1.添加Dialog资源,然后在资源视图的对话框界面右击添加类,输入类名MyDlg,使得其继承与CDialogEx.(继承CDialog应该也可以)2.在新生成的 ...
- gentoo emacs 中文输入法 呼出
最近在另外一台电脑上面安装 gentoo和 emacs,但是碰到奇怪的问题,在旧电脑上面,可以使用 ctrl + space 呼出输入法,而新电脑只能触发 复制功能. 经过在网上查找和两台电脑之间的对 ...
- 安卓手机H5底部fix定位,呼出键盘底部会上浮解决办法
<script type="text/javascript">var windowInnerHeight = window.innerHeight; //获取当前浏览器 ...
- vos设置可呼出手机或固话
问题: 默认公司只让呼出手机号码,但有的客户要求能打固话,怎么办? 落地网关——补充设置——落地前缀——落地被叫改写规则 在改写规则里添加固话号段即可 具体案例: 5201——1表示让520号段只能拨 ...
随机推荐
- django+mysql简单总结
1.工程下建立APP(以WIN10+PYTHON3.6为例) C:\Users\WYS>django-admin startproject myweb #建立项目 C:\Users\WYS&g ...
- 在CentOS 上搭建nginx来部署静态页面网站
在centOs 上搭建nginx来部署静态页面网站 一.部署服务器环境 nginx:轻量级.高性能的HTTP及反向代理服务器,占用内存少,并发能力强,相比老牌的apache作为web服务器,性能更加卓 ...
- EF CodeFirst系列(8)--- FluentApi配置单个实体
我们已经知道了在OnModelCreating()方法中可以通过FluentApi对所有的实体类进行配置,然而当实体类很多时,我们把所有的配置都放在OnModelCreating()方法中很难维护.E ...
- 从Socket入门到BIO,PIO,NIO,multiplexing,AIO(未完待续)
Socket入门 最简单的Server端读取Client端内容的demo public class Server { public static void main(String [] args) t ...
- Linux 命令详解(十三)如何启动、关闭和设置ubuntu防火墙
sudo ufw enable|disable 由于LInux原始的防火墙工具iptables过于繁琐,所以ubuntu默认提供了一个基于iptable之上的防火墙工具ufw. ubuntu 9.1 ...
- SpringBoot系列: 使用 Swagger 生成 API 文档
SpringBoot非常适合开发 Restful API程序, 我们都知道为API文档非常重要, 但要维护好难度也很大, 原因有: 1. API文档如何能被方便地找到? 以文件的形式编写API文档都有 ...
- burp Suite 模块Authz 使用方法
这个模块是朋友告诉我的,然后进行了研究使用方法. 以下为个人理解,如有错误感谢各位纠正. 0x00 安装Authz Extender > BApp Store > Authz > i ...
- Coursera, Big Data 2, Modeling and Management Systems (week 4/5/6)
week4 streaming data format 下面讲 data lakes schema-on-read: 从数据源读取raw data 直接放到 data lake 里,然后再读到mode ...
- ZOC7在Mac下发送命令到多个窗口设置
1 详见截图,找了半天 2 然后,下边框就会出现命令发送多个窗口的输入框了
- Python3.6及以上pip安装pymssql错误的解决办法[Windows&Linux freetds安装]
只有由于Python3.6装不上 pymssql,所以一直用Python3.5的版本. 报错界面 现在有了新的解决方法: 原帖如下: https://docs.microsoft.com/en-us/ ...