You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VS2022社区版C#控制台应用加载第三方DLL报BadImageFormatException错误求助

问题根因

你错误使用了.NET托管程序集加载API加载非托管C++ DLL。Assembly.LoadFrom、Assembly.LoadFile等方法仅支持加载包含IL中间代码的.NET托管程序集,你所用的PCLService.dll是C++编译的原生非托管DLL,无IL结构,因此触发Bad IL format报错,.NET校验不通过后会立即卸载该DLL,对应你日志中出现的DllMain detach记录。

解决方案

有两种常用的非托管DLL调用方式,可按需选择:

1. 静态P/Invoke调用(推荐,适配已知导出函数签名的场景)

通过DllImport特性声明导出函数签名,CLR会自动完成DLL加载、函数调用逻辑,用法示例:

using System.Runtime.InteropServices;

namespace ConsoleApp5
{
    internal class Program
    {
        // 替换为你实际的导出函数名、调用约定、参数签名
        // CallingConvention需和DLL编译约定匹配,C++默认是Cdecl,若使用WINAPI则改为StdCall
        [DllImport("PCLService.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "你的导出函数名")]
        public static extern int 你的导出函数名(参数列表);

        static void Main(string[] args)
        {
            // 直接调用声明的方法即可
            var result = 你的导出函数名(参数);
            Console.WriteLine(result);
            Console.ReadLine();
        }
    }
}

2. 动态加载调用(适配需要动态判断函数是否存在的场景)

和C项目中调用Win32 API加载DLL的逻辑一致,先导入Kernel32的加载相关API,再手动完成加载、取函数地址、调用逻辑,用法示例:

using System;
using System.Runtime.InteropServices;

namespace ConsoleApp5
{
    internal class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr LoadLibrary(string dllPath);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool FreeLibrary(IntPtr hModule);

        // 替换为和导出函数匹配的委托签名,调用约定和参数保持一致
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate int 导出函数委托类型(参数列表);

        static void Main(string[] args)
        {
            IntPtr dllHandle = LoadLibrary("PCLService.dll");
            if (dllHandle == IntPtr.Zero)
            {
                Console.WriteLine($"加载DLL失败,错误码:{Marshal.GetLastWin32Error()}");
                return;
            }

            IntPtr funcPtr = GetProcAddress(dllHandle, "你的导出函数名");
            if (funcPtr == IntPtr.Zero)
            {
                Console.WriteLine($"获取函数地址失败,错误码:{Marshal.GetLastWin32Error()}");
                FreeLibrary(dllHandle);
                return;
            }

            var func = Marshal.GetDelegateForFunctionPointer<导出函数委托类型>(funcPtr);
            var result = func(参数);
            Console.WriteLine($"调用结果:{result}");

            // 程序退出前释放DLL
            FreeLibrary(dllHandle);
            Console.ReadLine();
        }
    }
}
注意事项
  • 复杂参数(如字符串、结构体)需要手动指定封送规则,比如C++的char*对应C#的[MarshalAs(UnmanagedType.LPStr)] string,结构体需添加[StructLayout(LayoutKind.Sequential)]特性保证内存布局一致。
  • 确保运行环境已安装DLL编译时对应的VC++ Redistributable版本,否则会出现加载失败问题。

内容的提问来源于stack exchange,提问作者David Añez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 02:06:05