主要对Windows
平台上C++
项目开发过程中库目录进行梳理及程序发布要注意的相关事项进行总结,希望对其他开发者有一定的借鉴意义。
1.问题的提出
在最近的项目中,主要工作是为SketcchUp
平台开发基于Ruby
的扩展功能库,这种库文件是以.so
为后缀的形式提供,用C++
语言来编写实现。当我在自己的电脑环境下测试成功无问题后,进行发布时,就需要打包自己电脑上的相关依赖dll
文件。我的电脑是64位Win10
操作系统,当时我直接复制了我自己电脑C:\Windows\SysWOW64
目录下的dll
文件,进行发布,当其它同事使用时,.so
文件无法加载,于是就报了LoadError:193: %1 is not a valid Win32 application
的错误。
出现此类错误的最根本原因在于,自己对于Windows
系统的库文件目录理解不清,甚至理解错误,那么对于32位
和64位
操作系统中的System
、System32
和SysWOW64
这几个目录的含义与区别是什么是呢?
2.System
、System32
和SysWOW64
目录的含义
对于32位
操作系统:
它可以同时运行32位
和16位
的代码程序,并且系统在如何允许32位
程序和16位
程序并存运行方面使用了很复杂的机制。在32位
系统的Windows
文件夹下,有System
和System32
两个文件夹,分别用来存放16位
和32位
的dll
文件,因此,从这方面来看,System32
文件夹下存放的是32位
的dll
文件;
对于64位
操作系统:
它可以直接运行64位
的程序代码,同时通过WOW64(Windows on Wondows)
也能运行32位
的程序代码。但是64位
的操作系统有一个很大的不同,即32位
代码与64位
代码单独运行,有两个Program Files
,有System32
和SysWOW64
两个库文件夹,甚至有两个注册表。通常的思维,按32位
系统的规律,存放64位
的dll
的文件夹应该叫System64
,但实际上,微软为了保持兼容性,64位
的dll
依然存放在System32
文件夹下,同时多了一个SysWOW64
文件夹。
对于SysWOW64
文件夹,这是用来适配系统运行的,因为32位
软件并不能直接运行在64位
系统中,故微软设计了SysWOW64
,通过Wow64.dll
、Wow64win.dll
、Wow64cpu.dll
三个dll
文件进行32位
与64位
系统的切换。
因此,在64位
系统中,发布时拷贝所依赖的dll
时,还是从System32
文件夹下拷贝。
3.C++
程序的发布部署方式
对于在程序发布时,在其它电脑上运行报应用程序无法正常启动(0xc000007b)
,这种错误是缺少相应的dll
库,解决这种错误可以将VS
安装目录下的运行时库
拷贝到程序的同级目录。
如我用的VS2019
编译环境,64位
系统,可以将
D:\VS2019\VC\Redist\MSVC\14.28.29910\x64\Microsoft.VC142.CRT
目录下的dll
文件全部拷贝到程序的同级目录,如下图所示:
对于程序发布时缺少api-ms-win-crt-runtimel1-1-0.dll
等文件时,这是因为目标机上未安装相应的SDK Kit
,这时我们程序发布时将自己电脑上的SDK
文件夹下的41
个接口dll
文件拷贝到程序同级目录。
如我用的S2019
编译环境,SDK
版本是10.0.19
,可以将
C:\Program Files (x86)\Windows Kits\10\Redist\10.0.19041.0\ucrt\DLLs\x64
目录下的dll
文件全部拷贝到目标程序的同级目录,如下图所示:
我们在发布程序时,一般会将上面提到的两个目录中的全部dll
文件拷贝到目标程序的同级目录中,一同发布,以防止客户目标机上未安装对应的环境,导致目标程序无法运行。
另外一种发布方式是,在发布目录程序时,可以将VS
安装目录下的vcredist_x64.exe
,一同发布,用户在使用程序时,可以先运行安装对应的库文件,再使用目标程序。
如我使用的VS2019
编译环境,可以将D:\VS2019\VC\Redist\MSVC\v142
目录下的文件一同发布,如下图所示:
总之,在发布自己开发的程序时,一定要注意依赖的dll
的版本问题,各个dll
的位数一定要匹配,否则会出现找不到dll
而报各种各样的错误。