1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Windows下解决依赖动态库问题:bat脚本实现自动复制dll文件

Windows下解决依赖动态库问题:bat脚本实现自动复制dll文件

时间:2022-07-31 10:16:21

相关推荐

Windows下解决依赖动态库问题:bat脚本实现自动复制dll文件

1. 问题

Windows下,exe文件在设计实现时可能依赖某些动态库(*.dll文件),这些在调试台调试或在本机运行因为指定了包含库文件或者指定了环境变量,使得运行时可以找到并调用这些文件。但是环境变化,很容易找不到。报错找不到dll文件。

对现成的exe文件,解决方法一般是根据报错信息,找到dll文件,设置好环境变量,或者直接复制dll文件到exe所在目录解决依赖问题。

其实主要是编译得到exe文件想要移到其他电脑上运行,解决依赖库问题。

2. 解决

1)思路

将依赖动态库复制到 exe 目录下,很简单的工作,用 bat 脚本自动实现。

分析依赖库找到对应的 dll 文件目录,找不到则记录复制到当前目录下分析结果可能不够,提供补充工具,根据名字找到并复制到当前目录下

2)方法

Vistual Studio 提供 dumpbin.exe 工具,可以分析依赖库

该 exe 在 VS\VC\bin 下,可 cd 至此或者打开 VS 命令行工具。输入

dumpbin.exe /dependents xxx\xxx.exe

即可得到依赖库信息。用 findstr 工具匹配一下文本可以得到正确的 dll 依赖库文本,例如

findstr "\.dll$" test.txt

即可匹配到具有“.dll”字符串的行。用通道和重定向可以很方便输出全部为dll名字的 txt 文本

用 where 工具找到本机上 dll 文件目录

【问题】如果没有设置环境变量,自然是找不到。如果设置了,自然又不缺 dll 。

所以这个工具也只是实现复制的作用,供移动到其他电脑方便使用。

where xxx.dll

用 copy 工具复制文件

copy realdir\xxx.dll .\dlls\xxxxx.dll

3)bat脚本

a. get_dll.bat

需搭配add_process.bat使用,即保持同一目录

功能:

复制exe到该目录下解析dll依赖复制dll到该目录下

@echo offecho 应用: 利用vs的dumpbin工具解析依赖dll,并复制到.\dll_date目录下。echo 原理: 用vs的dumpbin解析dll依赖,where找到dll路径,copy过来。echo 使用:1. cmd下 this + exe file direcho 2. 提示输入路径。echo 补充: 运行时可能仍然缺少某些dll文件,运行add_dll.bat手动补充。SETLOCAL ENABLEDELAYEDEXPANSIONset exe_path=%1set exe_name=%~n1%~x1set /p copy_exe=复制%1到 %~p0 exe_%date:~5,10% 下(y or n)?if %copy_exe%==y ( md .\exe_%date:~5,10% 2>nulcopy %1 .\exe_%date:~5,10%\%exe_name%)set dll_path=dll_%date:~5,10%set /p vs_root_path=visual studio 安装根目录(eg.E:\VS):::set vs_root_path=E:\VSset dumpbin_path=%vs_root_path%\VC\bin\echo Step1. set dumpbin root: %dumpbin_path%echo Step2. set exe file path: %exe_path%md .\%dll_path%>nulecho Step3. 开始解析依赖dll%dumpbin_path%dumpbin.exe /dependents %exe_path% | findstr "\.dll$" >.\%dll_path%\_dependent_dll_log.txtecho 解析完毕,总计type .\%dll_path%\_dependent_dll_log.txt | find /v /c ""set /p showlog=展示全部(y or n)?if %showlog%==y ( type .\%dll_path%\_dependent_dll_log.txt)echo Step4. 复制全部dll到 .\%dll_path%\set /p copyAll=确定(y or n)?if not %copyAll%==y ( echo 清除缓存del .\%dll_path%\*.*rd .\%dll_path%echo 清理完毕,再见goto end )for /f %%i in (.\%dll_path%\_dependent_dll_log.txt) do ( WHERE %%i 1> .\%dll_path%\temp.txt 2>nulif errorlevel 1 ( echo 找不到%%i,记录于.\%dll_path%\copy_error_log.txtecho %%i>>.\%dll_path%\copy_error_log.txt )call add_process.bat %%i -off)del %dll_path%\temp.txtecho 复制工作结束:endpause

b. add_process.bat

附加处理工具,主要工作是获得txt文本中第一行,并复制dll文件

@echo offset dll_name=%~n1%~x1for /f %%j in (.\%dll_path%\temp.txt) do ( if %2==-on echo 开始复制,复制对象:%%jcopy %%j .\dll_%date:~5,10%\%dll_name%goto add_end ):add_end::end add_process to break for loop and get only the first line.

c. add_dll.bat

补充工具

功能:

根据输入dll名字,自动查找并复制到该目录下dll存放文件夹中

使用:

直接运行即可

@echo offset dll_path=dll_%date:~5,10%set temp=%dll_path%\temp.txtmd .\%dll_path% 2>nulecho 应用:复制dll文件到%dll_path%目录下:add_startset /p dll_name=输入dll文件名(eg. gflags.dll),q to quit:if %dll_name%==q ( goto add_end)where %dll_name% 2>nul 1>%temp%if errorlevel 1 ( echo 未找到%dll_name%,请重新输入goto add_start )else ( echo 找到%dll_name% 于type %temp% )call add_process.bat %dll_name% -onset /p flag=继续复制dll文件(y or n)?if %flag%==y ( goto add_start )else ( echo 再见)del .\%temp%:add_endpause

3)小结

算是完整地实现一个功能,对简单的问题有简单的解决方法。

为了应付多种情况所以复杂了一些。调试bat的过程也感到十分地亲切。

也对网络资源的一点点补充。是bat的练手,bat语法奇葩但高效,以行为处理单位,对字符串直接进行运行,对空格敏感。

小结用到的语法如下

用到的bat语法1) 变量与赋值 set定义,%名字%调用,set /p 提示输入%加数字是批处理后面的参数,以空格间隔。0表示本身的完全路径。利用%数字 和 其他处理手段,可以方便地处理参数和路径 /article/52744.htm2) 管道与重定向 |>>>>&1> 2>|组合 >重定向 >>追加重定向 数字表示句柄,代表信息级别。1<&3 3的指向复制给1 1> 一般为标准输出级别 2为错误信息级别 0为输入。>nul 是windows下空设备。3) if else。if [not] ==if [not] exist "%filepath%" ()需要有空格才能识别else以及括号里的命令。4) for 循环与内部变量一般的环境变量需延迟定义。这里失败了,用了别的方法,call第二个bat。5) call gotocall调用第二个bat 结束后返回。使for循环有效continue。goto跳转到其他代码,一旦跳出for将不再返回,为break。对于for循环内部循环赋值变量,可见这个变量是临时性的。传入第二个for循环进行处理,并且这里不是环境变量,而是循环变量。天然支持随循环变化。主要用来解决:第一个for循环得到文本内每一行,第二个循环得到由一个循环的一行字符串处理得到的一个新文本的第一行。两个for循环一样的语法,只是第二个for循环只需得到第一行即可,故而goto,break for。goto对循环非常非常轻松地实现。6) 字符串处理findstr + 正则表达式。其以行为处理单位。7) 使用errorlevel判断命令是否执行成功

还想做的

把dumpbin独立出来

4)其他

果然是太简单以至于网上都没有类似脚本

用vs编译程序可以直接使用生成事件自动复制依赖库,且依赖库是原生设置的,更为准确。

参考博客:VS编译后直接复制DLL库文件到其他目录下/94cool/p/8274964.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。