DLL错误之——无法加载DLL"***.dll":找不到指定的模块(异常来自HRESULT:0x8007007E)问题的终极感悟

1、前奏
          最近帮老师用opencv做一个东西,在VS2013中配置了opencv 的经典版本opencv2.4.9,做了一个视频解帧的工作,封装成了C++的dll,以供对方公司使用C#语言调用,所以我需要用C#测试我的dll
C#语言真是难缠,dll缺失或者dll中内部有错误都只给你一个信息那就是:“无法加载DLL"***.dll":找不到指定的模块(异常来自HRESULT:0x8007007E)”,真是令人头大
2、解决办法
         我是尝试遍了所有的这个错误的解决办法,依然不能挽救错误,还是报同样的错误。
        C#中调用C++的dll也有两种方式,一种是静态调用,一种是动态调用,我先使用的静态调用,网上的静态调用方式下出这个错误的方法已试完看到网上最好的那个帖子:
帖子如下地址如下:http://blog.youkuaiyun.com/peng825223208/article/details/38069779
这篇帖子我以为很吊,相信读我博客的你应该也会看到。由于不懂C#,就把它的代码敲进去进行尝试调用,什么改@“xxxx.dll”这样的绝对路径一点用都没有,还是找不到dll,它里面说的托管和非托管我百度了一下也没看明白,都是官方解释,到底什么样的dll是托管的什么样的dll是不托管的,对于一个C#初次接触的人来说不是很明白,代码敲进去也有错,所以就不用它的方法了,写的又不清楚。
 接下来我贴一下我的dll的代码和我用C#调用这个dll的代码,供大家参考自己的改,然后我会给出可能出错的原因,90%错误都在其中。


2、利用C++写的dll代码(配置了opencv库):
/*
该函数主要功能为将输入的视频分解成帧,有三个输入参数
char*inputPath:输入视频
char*ouputPath:输出帧目录
int maxFrame:想要分解出的帧数,从第一帧算起
返回值为int类型,表示最终分解出的帧的个数,如果maxFrame大于视频实际帧数,返回实际帧数,如果小于则返回maxFrame帧
date:2017/10/26
author:tonglewang
address:ECNU
*/
#include "stdafx.h"
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
extern "C" __declspec(dllexport)int videoTransferToImage(char*inputPath, char*ouputPath,int maxFrame){
    cout <<"already acesss the entrypoint!" <<endl;
    char fileName[1000];
    Mat frame;
    int i = 1;
    VideoCapture inputVideo(inputPath);
    if (!inputVideo.isOpened()){
        return 0;
    }
    cout << "xunhuan entrypoint!" << endl;
    while (1){
        cout << "acess xuhuan!" << endl;
        inputVideo >> frame;
        if (frame.empty())
            break;
        sprintf_s(fileName, "%s%d.jpg", ouputPath, i);
        imwrite(fileName, frame);
        if (i==maxFrame)
            break;
        i++;
    }
    int frames = inputVideo.get(CV_CAP_PROP_FRAME_COUNT);
    if (frames >= maxFrame)
        return maxFrame;
    else
        return frames;
}

3.1 C#写的静态调用代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
namespace VideoTranferToImageTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string videoPath = "D:\\workspace\\program\\VideoTranferToImage\\Test\\videoPath\\test.mp4";
            string picturePath = "D:\\workspace\\program\\VideoTranferToImage\\Test\\picturePath\\";
            int maxFrame = 100;
            int frames = Test.videoTransferToImage(videoPath,picturePath,maxFrame);
            Console.WriteLine("total frames=" + frames.ToString());
            Console.ReadLine();
        }
    }
    class Test {
//下面的"VideoTransferToImage.dll"为你的dll的存放路径,C#的话就存在项目的/bin/debug/目录下就好了,加什么@加不加都无所谓,路径中是不是用“//”双斜线都无所谓。
        [DllImport("VideoTransferToImage.dll", EntryPoint = "videoTransferToImage",CallingConvention = CallingConvention.Cdecl)]
        public static extern int videoTransferToImage(string inputPath, string ouputPath,int maxFrame);
    }
}

3.2 C#写的动态调用代码

ausing System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
           string videoPath = "D:\\workspace\\program\\VideoTranferToImage\\Test\\videoPath\\test.mp4";
            string picturePath = "D:\\workspace\\program\\VideoTranferToImage\\Test\\picturePath\\";
            int maxFrame = 100;
            int hModule = NativeMethod.LoadLibrary("VideoTransferToImage.dll");
            if (hModule == 0) return;
            //2. 读取函数指针
            IntPtr intPtr = NativeMethod.GetProcAddress(hModule, "videoTransferToImage");
            //3. 将函数指针封装成委托
            videoTransferToImage  addFunction = (videoTransferToImage)Marshal.GetDelegateForFunctionPointer(intPtr, typeof(Add));
            //4. 测试
            Console.WriteLine(addFunction(videoPath, picturePath,maxFrame));
            Console.Read();
        }
        [UnmanagedFunctionPointerAttribute(CallingConvention.Cdecl)]
        delegate int videoTransferToImage(string inputPath, string ouputPath,int maxFrame);
    }
    public static class NativeMethod
    {
        [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
        public static extern int LoadLibrary(
            [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
        [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
        public static extern IntPtr GetProcAddress(int hModule,
            [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
        [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
        public static extern bool FreeLibrary(int hModule);
    }
}

4、我的经历
      我的最终错误是我前段时间还是做opencv开发dll的时候由于某种原因将系统中的msvcp120d.dll和msvcr120d.dll这两家伙给删了,因为C#它死活不报说缺两东西,死活就说你的"***.dll":找不到指定的模块(异常来自HRESULT:0x8007007E)找不到,所以这个问题一直没发现,使用depend walk工具查看结果也正常,没有显示缺这两个,我就怪了。最后我在偶然尝试一篇博客的动态调用的时候就跟着它的博客写了一个简单的a+b的dll,利用C#调用,因为这个根本不涉及dll,所以就暴露出来了,显示缺少上面两个dll,我最后才大工工程,整个问题持续一天才解决,因为我死活看我的dll就是在bin/debug目录下,就是在,为什么就是找不到呢?所以当你能够确定你的dll一定是在目录下的时候就不要去按照http://blog.youkuaiyun.com/peng825223208/article/details/38069779这篇博文去忙碌了,你该考虑另一个能99%造成这个错误的原因了,那便是你的dll调用了别的dll,或者你安装的操作系统里面根本就缺少一些dll,那怎么办呢?这两个办法各有妙招。办法如下:
4.1你的dll调用了别的dll
           终极杀手锏,下载安装depend walk查看依赖关系,看你的dll到底还调用了那些dll,以opencv 为例,如果缺失的是以opencv开头的,索性把opencv安装目录下面的build/x86/opencv12/bin目录下的所有dll拷贝到你的工程的bin/debug/目录下就好了。至于depend显示的
IESHIMS.DLL找不到文件就不要信息,好多dll都有这毛病,这不是本质愿意,还有下面弹出的一些您在所有人博客里面都能看到的提示错误,就不要关心了,我的时这样的,下面的红色都是无关紧要的错误。

depend walk 官方下面地址:http://www.dependencywalker.com/
4.2 你的系统缺少一些dll
         这个错误就得感谢我解决问题的那篇博客了,多谢这位博主的博客,给他点个赞博主文章地址:http://www.cnblogs.com/newstart/archive/2012/10/24/2736780.html
大家可以照着他的方法写一个add (a+b)的验证程序,因为这种简答的程序啥依赖的关键dll基本没有,依赖的都是系统相关的dll,所以很VS这是在运行就会告诉你,系统了缺少的一些dll,你就可以下载这些dll,放在您系统的windows目录下了,记住:64位系统放到这个C:\Windows\SysWOW64,32位系统放到这个C:\Windows\System32,不放心全都放吧。
5 总结
         所以归结起来就是两个重大的原因你都要普查清楚,也是别人博客里面说的很多的两个原因:
1、一定要将dll放在项目\bin\Debug目录下,然后仔细检查 [DllImport("VideoTransferToImage.dll", EntryPoint = "videoTransferToImage",CallingConvention = CallingConvention.Cdecl)中的路径是否写的正确。
2、如果你确认你的dll就是在\bin\Debug目录下,上面语句也没问题,那么十有八九就是你的dll依赖别的dll,一种是系统的dll,一种是你写你的dll程序时,调用到了别的dll,例如opencv你写的时候包含了好多头文件,用到了好多dll。虽然没有明显在调用调用,但是你的每一个函数都是在调用opencv的dll。另外就是调用到了系统的dll。这两种错因我都给了解决方案,希望在解决dll错误的路上您一路好走!
最后就说一下,不要相信这篇博客里面的内容了

说的啥根本不知道,可能是我太肤浅,但是我觉得估计很多人都不是这个问题。
 

<think>好的,我现在遇到了一个DllNotFoundException,提示无法加载名为“IKapBoard”的DLL错误代码是0x8007007E。首先,我需要弄清楚这个错误的原因。根据以往经验,这种异常通常发生在系统不到指定的动态链接库文件时。可能的情况包括DLL文件缺失、路径不正确、依赖项不全,或者架构不匹配等问题。 首先,我要确认DLL文件是否真的存在于应用程序的目录中。用户可能将DLL放在了项目文件夹里,但实际运行时,程序可能从生成目录(如bin/Debug或bin/Release)执行,需要确保DLL被正确复制到输出目录。此外,检查文件名是否正确,包括大小写是否匹配,因为有些系统对大小写敏感。 接下来,考虑依赖项的问题。使用Dependency Walker或者Visual Studio的Dependencies工具检查IKapBoard.dll是否有其他依赖的DLL文件缺失。有时候,主DLL可能依赖第三方库,如Visual C++ Redistributable,这时候需要安装相应的运行时库。 然后,检查系统架构是否匹配。如果应用程序是64位的,而DLL是32位的,或者相反,就会导致无法加载。需要确认两者的平台目标一致,比如都是x86或x64。 路径问题也是常见原因。如果DLL不在系统PATH环境变量包含的目录中,或者不在应用程序的工作目录下,系统就不到它。可以尝试将DLL放在应用程序的启动目录,或者修改PATH变量包含DLL所在路径。 权限问题也不能忽视。确保运行应用程序的用户有权限访问DLL文件,可能需要以管理员身份运行程序,或者调整文件的安全设置。 另外,检查DLL文件是否完整,是否被损坏。重新下载或从可靠来源获取DLL文件,替换现有文件试试看。 如果是使用.NET调用本地DLL,还要确认是否正确使用了DllImport属性,指定正确的入口点和字符集。例如: [DllImport("IKapBoard.dll", CharSet = CharSet.Auto)] public static extern void SomeFunction(); 最后,查看系统事件查看器或使用调试工具获取更多错误信息,可能会有更详细的日志帮助定位问题。 总结下来,解决步骤大致是:确认DLL存在且路径正确,检查依赖项,验证架构一致性,确保权限足够,排除文件损坏可能,并检查代码中的DllImport设置。如果这些步骤都做了还是不行,可能需要联系DLL的提供商获取支持,或者查看相关文档是否有特殊要求。</think>遇到 `DllNotFoundException: 无法加载 DLL“IKapBoard”` 错误时,通常是由于系统无法到或加载所需的动态链接库(DLL)文件。以下是逐步排查和解决方案: --- ### **1. 确认DLL文件是否存在** - **检查路径**:确保 `IKapBoard.dll` 文件位于以下位置之一: - 应用程序的启动目录(如 `bin\Debug` 或 `bin\Release`)。 - 系统目录(如 `C:\Windows\System32`,64位程序可能需要 `C:\Windows\SysWOW64`)。 - 环境变量 `PATH` 包含的目录。 - **文件名一致性**:检查代码中引用的DLL名称(如 `IKapBoard`)与实际文件名是否**完全一致**(包括大小写和扩展名)。 --- ### **2. 检查依赖项** - **依赖的DLL是否缺失**: 使用工具(如 [Dependency Walker](https://www.dependencywalker.com/) 或 [Dependencies](https://github.com/lucasg/Dependencies))分析 `IKapBoard.dll`,查看是否存在未安装的依赖库(如其他第三方DLL或系统组件)。 - **安装运行时库**: 如果DLL依赖某些运行时库(如 Visual C++ Redistributable),需从微软官网下载并安装对应版本。 --- ### **3. 平台架构匹配** - **32位 vs 64位**: 确保应用程序的目标平台(如 `x86` 或 `x64`)与DLL的编译架构一致。若不一致,需重新编译DLL或调整应用程序的目标平台。 --- ### **4. 权限问题** - **文件访问权限**: 检查当前用户是否有权限读取DLL文件。右键DLL文件 → 属性 → 安全 → 编辑权限。 - **管理员权限**: 尝试以管理员身份运行应用程序。 --- ### **5. 代码中的DllImport设置** - 如果通过C#调用DLL,检查 `DllImport` 属性是否正确: ```csharp [DllImport("IKapBoard.dll", EntryPoint = "YourFunction", CharSet = CharSet.Auto)] public static extern void YourFunction(); ``` - 确保未添加多余的扩展名(如 `.dll` 已隐含)。 - 指定正确的 `EntryPoint` 和 `CharSet`。 --- ### **6. 其他可能原因** - **DLL文件损坏**: 重新下载或从可靠来源获取 `IKapBoard.dll`。 - **杀毒软件拦截**: 暂时禁用杀毒软件或防火墙,测试是否被误判为恶意文件。 - **注册DLL(谨慎操作)**: 如果DLL需要注册,以管理员身份运行命令提示符并执行: ```bash regsvr32 IKapBoard.dll ``` (注意:仅适用于COM组件,普通DLL无需此操作) --- ### **7. 获取更多错误信息** - **查看详细日志**: 使用事件查看器(Windows)或调试工具(如Visual Studio)捕获更具体的错误信息。 - **联系DLL提供商**: 如果DLL来自第三方硬件/软件,检查官方文档或联系技术支持。 --- ### **总结步骤** 1. 确认 `IKapBoard.dll` 存在于应用程序目录。 2. 检查依赖项是否完整。 3. 确保平台架构一致。 4. 验证代码中的DLL调用方式。 5. 排除权限或安全软件干扰。 如果问题仍未解决,建议提供以下信息以便进一步分析: - 操作系统版本(如Windows 10/11)。 - 应用程序的目标平台(x86/x64)。 - DLL文件的来源(如硬件驱动、第三方库)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值