在 C# 里用 [DllImport("SgCamWrapper.dll")] 去调用非托管 DLL 时,很多同学最常踩的坑就是——DLL 到底该放哪?其实 .NET 的查找顺序有一套明确的规则,搞懂了这一步,以后遇到 DllNotFoundException 就不会一脸懵了。
✅ .NET 查找 DLL 的路径顺序
优先级从高到低是这样的:
- 应用程序启动目录(当前工作目录)——简单说就是
YourApp.exe所在的文件夹。绝大多数情况下,直接把SgCamWrapper.dll放在 exe 旁边就能搞定。 - 系统目录,比如
C:\Windows\System32或C:\Windows\SysWOW64(取决于进程是 64 位还是 32 位)。 - 环境变量 PATH 中列出的目录——这个范围就很广了,包括系统 PATH 和用户 PATH。
- GAC(全局程序集缓存)——注意这里只对托管 DLL 有效,非托管的 native DLL 不会走 GAC 查找。
✅ 如何确保它能找到 DLL?
三个办法,按推荐程度排序:
方法 1:把 SgCamWrapper.dll 放到可执行文件旁边
最简单粗暴,也最不容易出问题。如果你在用 Visual Studio,直接把 DLL 拷贝到 bin\Debug 或 bin\Release 目录下:
YourProject/ │ ├── bin/ │ └── Debug/ │ ├── YourApp.exe │ ├── CameraWrapper.dll │ └── SgCamWrapper.dll <-- 放这里!
方法 2:项目中设置“始终复制”到输出目录
把 DLL 添加到项目里,右键 → 属性 → 复制到输出目录 设为“始终复制”或“如果较新则复制”。这样每次编译都会自动把它带到输出文件夹,省心不少。
方法 3:在代码中动态指定路径
如果 DLL 的存放位置比较特殊(比如放在某个子目录或者配置文件里指定),你可以先用 LoadLibrary 手动加载,再调用封装好的 CameraWrapper:
[DllImport("kernel32", SetLastError = true)]
private static extern IntPtr LoadLibrary(string lpFileName);
LoadLibrary("C:\\Path\\To\\SgCamWrapper.dll");
⚠️ 注意事项
- 如果
SgCamWrapper.dll本身还依赖其他 C++ 运行时库或第三方 DLL,那些依赖也得保证能被 .NET 找到。否则即便主 DLL 在正确路径,加载时还是会报错。 - 遇到
DllNotFoundException或BadImageFormatException,十有八九是路径不对或者平台不匹配(32 位 vs 64 位)。检查一下 exe 的编译目标平台和 DLL 的位数是否一致。
ℹ️ 如何调试 DLL 加载失败?
加个简单的异常捕获,就能快速定位问题:
try
{
CameraWrapper.SgCreateCamera();
}
catch (DllNotFoundException e)
{
Console.WriteLine("DLL not found: " + e.Message);
}
如果还查不出原因,可以用工具(比如 dumpbin /headers 或 Visual Studio 自带的 CorFlags.exe)来确认 DLL 是 32 位还是 64 位。这一步搞清楚了,后面就好办了。