在VC++2008的项目中,如何显示地指定要使用的C++库的版本?

BoweirrKing 2008-08-25 12:18:23
在VC++2008的项目中,如何显示地指定要使用的C++库的版本?

开发环境:VS2008 SP1 + WINXP SP2
因为我的VS2008安装了SP1补丁,所以有了9.0.30729.1的MFC库文件(MFC90.DLL MSVCR90.DLL)。


新建了一个MFC应用程序,编译为RELEASE版本,叫做“test1.exe”,可以从程序中的清单文件(manifest)看到以下内容:
...
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type='win32' name='Microsoft.VC90.MFC' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
</dependentAssembly>
</dependency>
...


说明本程序需要引用版本号为9.0.21022.8的MFC库和运行时库。

问题一:为什么程序在运行的时候,载入的不是9.0.21022.8版本的却是9.0.30729.1版本的运行库?这是在哪里进行设置的?如何改变这个版本号?

问题二:(虽然貌似已经解决,但是我想知道的更深一点)
布署的时候,把X:\VS安装目录\VC\redist下对应的运行库和.manifest文件(都是9.0.30729.1版本的)复制到与test1.exe同一目录下。在一台完全干净的新系统中,会出现“应用程序配置不正确,应用程序未能启动”的错误。

后来,经过不断的试验,发现应用程序中的MANIFEST文件指定的是9.0.21022.8版本的运行库,然后我使用9.0.21022.8版本的Microsoft.VC90.CRT.manifest文件替换9.0.30729.1版本的Microsoft.VC90.CRT.manifest,配合上30729版本的MFC90.DLL,程序就可以正常运行了。

如果以上说的还不清楚的话,说的简单一点,就是,对于一个使用了新版本DLL功能的应用程序,有以下情况:
应用程序中的MANIFEST文件[使用了使用了新版本DLL的功能 却指定了旧的版本号] + 新版本的运行库MANIFEST文件 + 新版本的运行库DLL --> 不可以运行
应用程序中的MANIFEST文件[使用了使用了新版本DLL的功能 却指定了旧的版本号] + 旧版本的运行库MANIFEST文件 + 旧版本的运行库DLL --> 不可以运行
应用程序中的MANIFEST文件[使用了使用了新版本DLL的功能 却指定了旧的版本号] + 旧版本的运行库MANIFEST文件 + 新版本的运行库DLL --> 可以运行

注:运行库MANIFEST文件是指Microsoft.VC90.CRT.manifest和Microsoft.VC90.MFC.manifest,运行库DLL是指MSVCR90.DLL MFC90.DLL

出现这种现象的原因是什么?我遍寻MSDN未果,特此请教高人~~
...全文
6430 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Conggang 2010-06-29
  • 打赏
  • 举报
回复
mark
LunarShaddow 2010-03-19
  • 打赏
  • 举报
回复
不是直接在程序属性中改用静态dll就可以了么???
teleinfor 2010-01-04
  • 打赏
  • 举报
回复
帮我解决问题了,谢谢哦。。。
songking5566 2009-11-24
  • 打赏
  • 举报
回复
mark
red_berries 2009-04-23
  • 打赏
  • 举报
回复
matk
geoh 2008-11-06
  • 打赏
  • 举报
回复
最后拷贝到别人电脑上面的exe程序根本不需要manifest文件
geoh 2008-11-06
  • 打赏
  • 举报
回复
简单一点 把WinSxS里面关于VC90的非Debug的文件和文件夹全部拷贝出来
(当然也要筛选,如果你没用到CRT MFCLOC OPENMP,就不用拷贝了)
全部文件采用Winrar固实压缩后 才4.2M,复制到目标文件即可

然后你使用Release发布程序,然后发布只要exe和dll就可以了

运行的exe程序根本不需要manifest文件

我列一个清单给你

WinSxS
├─Manifests
│ x86_Microsoft.VC90.ATL_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_312cf0e9.cat
│ x86_Microsoft.VC90.ATL_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_312cf0e9.manifest
│ x86_Microsoft.VC90.ATL_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_d01483b2.cat
│ x86_Microsoft.VC90.ATL_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_d01483b2.manifest
│ x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375.cat
│ x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375.manifest
│ x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30411.0_x-ww_71382c73.cat
│ x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30411.0_x-ww_71382c73.manifest
│ x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e.cat
│ x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e.manifest
│ x86_Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_11f3ea3a.cat
│ x86_Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_11f3ea3a.manifest
│ x86_Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_9.0.30411.0_x-ww_b29f1338.cat
│ x86_Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_9.0.30411.0_x-ww_b29f1338.manifest
│ x86_Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_b0db7d03.cat
│ x86_Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_b0db7d03.manifest
│ x86_Microsoft.VC90.MFC_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_a173767a.cat
│ x86_Microsoft.VC90.MFC_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_a173767a.manifest
│ x86_Microsoft.VC90.MFC_1fc8b3b9a1e18e3b_9.0.30411.0_x-ww_421e9f78.cat
│ x86_Microsoft.VC90.MFC_1fc8b3b9a1e18e3b_9.0.30411.0_x-ww_421e9f78.manifest
│ x86_Microsoft.VC90.MFC_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_405b0943.cat
│ x86_Microsoft.VC90.MFC_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_405b0943.manifest
│ x86_Microsoft.VC90.OpenMP_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_ecc42bd1.cat
│ x86_Microsoft.VC90.OpenMP_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_ecc42bd1.manifest

├─Policies
│ ├─x86_policy.9.0.Microsoft.VC90.ATL_1fc8b3b9a1e18e3b_x-ww_9e7eb501
│ │ 9.0.21022.8.cat
│ │ 9.0.21022.8.policy
│ │ 9.0.30729.1.cat
│ │ 9.0.30729.1.policy
│ │
│ ├─x86_policy.9.0.Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_x-ww_b7353f75
│ │ 9.0.21022.8.cat
│ │ 9.0.21022.8.policy
│ │ 9.0.30411.0.cat
│ │ 9.0.30411.0.policy
│ │ 9.0.30729.1.cat
│ │ 9.0.30729.1.policy
│ │
│ ├─x86_policy.9.0.Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_x-ww_b8438ace
│ │ 9.0.21022.8.cat
│ │ 9.0.21022.8.policy
│ │ 9.0.30411.0.cat
│ │ 9.0.30411.0.policy
│ │ 9.0.30729.1.cat
│ │ 9.0.30729.1.policy
│ │
│ ├─x86_policy.9.0.Microsoft.VC90.MFC_1fc8b3b9a1e18e3b_x-ww_4ee8bb30
│ │ 9.0.21022.8.cat
│ │ 9.0.21022.8.policy
│ │ 9.0.30411.0.cat
│ │ 9.0.30411.0.policy
│ │ 9.0.30729.1.cat
│ │ 9.0.30729.1.policy
│ │
│ └─x86_policy.9.0.Microsoft.VC90.OpenMP_1fc8b3b9a1e18e3b_x-ww_6ad67377
│ 9.0.21022.8.cat
│ 9.0.21022.8.policy

├─x86_Microsoft.VC90.ATL_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_312cf0e9
│ atl90.dll

├─x86_Microsoft.VC90.ATL_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_d01483b2
│ atl90.dll

├─x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375
│ msvcm90.dll
│ msvcp90.dll
│ msvcr90.dll

├─x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30411.0_x-ww_71382c73
│ msvcm90.dll
│ msvcp90.dll
│ msvcr90.dll

├─x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e
│ msvcm90.dll
│ msvcp90.dll
│ msvcr90.dll

├─x86_Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_11f3ea3a
│ mfc90chs.dll
│ mfc90cht.dll
│ mfc90deu.dll
│ mfc90enu.dll
│ mfc90esn.dll
│ mfc90esp.dll
│ mfc90fra.dll
│ mfc90ita.dll
│ mfc90jpn.dll
│ mfc90kor.dll

├─x86_Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_9.0.30411.0_x-ww_b29f1338
│ mfc90chs.dll
│ mfc90cht.dll
│ mfc90deu.dll
│ mfc90enu.dll
│ mfc90esn.dll
│ mfc90esp.dll
│ mfc90fra.dll
│ mfc90ita.dll
│ mfc90jpn.dll
│ mfc90kor.dll

├─x86_Microsoft.VC90.MFCLOC_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_b0db7d03
│ mfc90chs.dll
│ mfc90cht.dll
│ mfc90deu.dll
│ mfc90enu.dll
│ mfc90esn.dll
│ mfc90esp.dll
│ mfc90fra.dll
│ mfc90ita.dll
│ mfc90jpn.dll
│ mfc90kor.dll
│ mfc90rus.dll

├─x86_Microsoft.VC90.MFC_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_a173767a
│ mfc90.dll
│ mfc90u.dll
│ mfcm90.dll
│ mfcm90u.dll

├─x86_Microsoft.VC90.MFC_1fc8b3b9a1e18e3b_9.0.30411.0_x-ww_421e9f78
│ mfc90.dll
│ mfc90u.dll
│ mfcm90.dll
│ mfcm90u.dll

├─x86_Microsoft.VC90.MFC_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_405b0943
│ mfc90.dll
│ mfc90u.dll
│ mfcm90.dll
│ mfcm90u.dll

└─x86_Microsoft.VC90.OpenMP_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_ecc42bd1
vcomp90.dll
BoweirrKing 2008-08-26
  • 打赏
  • 举报
回复
终于终于,在微软网站找到了关于这个问题的描述。
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=361682
这的确是个BUG,具体什么时候会修复就不知道了。。。。。。。。

所以,内嵌清单中的版本号只能为旧版本号,因此目前只能用,旧版本的运行库MANIFEST文件 + 新版本的运行库DLL ,才可以运行独立发布的程序了。。。
jameshooo 2008-08-26
  • 打赏
  • 举报
回复
内嵌清单也是资源,当然可以修改,但是不建议这么做,而且也没必要这么做。
jameshooo 2008-08-25
  • 打赏
  • 举报
回复
因为安装新版DLL后添加了版本映射项,使得旧版DLL被映射到了新版中,当程序需要加载旧版DLL时将自动加载新版DLL。在DLL大版本一致的情况下,所有导出的符号规范全部是一致的,仅仅是做了功能的改进或者BUG修复,这是版本映射成功的关键。
BoweirrKing 2008-08-25
  • 打赏
  • 举报
回复
MS为运行库提供了一种私有的,或者说“后备”加载方式。在WINSXS中找不到对应的库的时候,程序会在本目录中进行查找。这是已经试验得知的。
[B]应用程序中的MANIFEST文件[使用了使用了新版本DLL的功能 却指定了旧的版本号] + 旧版本的运行库MANIFEST文件 + 新版本的运行库DLL --> 可以运行 [/B]
并且,直接拷贝DLL是肯定有用的,不要POLICY文件也是可以的;但前提是要把相应的清单文件和DLL都复制到一起。

我就是不太明白,为什么 旧版本的运行库MANIFEST文件 + 新版本的运行库DLL 反而可以运行呢???
jameshooo 2008-08-25
  • 打赏
  • 举报
回复
去了解一下SideBySide部署吧,从vs.NET开始使用的系统库都采用这种部署方式(包括MFC),直接拷贝DLL是没有用的,需要用redist提供的安装包来安装支持库。
所有SideBySide部署的DLL都被安装在c:\windows\winsxs文件夹下,这种方式的优点是可以在同一个系统下安装不同版本的DLL,并采用版本映射的方式来定位实际需要加载的DLL,直接复制的DLL是没有版本映射的。版本映射是在一个独立的XML文件中描述的,你可以看看带Policy字样的文件内容。在同一个大版本情况下(比如9.0),旧的小版本可以映射到新的小版本(比如你在manifest中指定的是21022.8,可以自动映射到30729.1)。
BoweirrKing 2008-08-25
  • 打赏
  • 举报
回复
我又想了一下,会不会是 新版本的运行库DLL 对于 旧版本的运行库MANIFEST文件 中所描述的内容有一种自适应能力呢?因为新版本DLL总是“大于等于”旧版本DLL的。

又做了个实验:
程序的清单文件不要内嵌,而使用外置的MANIFEST文件,然后手工把生成的text1.exe.manifest中的version='9.0.21022.8'改成新版本号version='9.0.30729.1' ,就可以达到以下目标了:
应用程序 外置的MANIFEST文件[使用了使用了新版本DLL的功能 却指定了的版本号] + 新版本的运行库MANIFEST文件 + 新版本的运行库DLL --> 可以运行!

不过有个外置的文件,确实不爽啊。。。。。

jameshooo,您知道有什么方法可以修改内嵌清单文件中的版本号吗??
BoweirrKing 2008-08-25
  • 打赏
  • 举报
回复
还是有点迷糊。。。。。您所说的安装新版DLL后添加了版本映射项,使得旧版DLL被映射到了新版中这句话中,在我实测的环境中,实际上是不存在“安装”这个动作的,我只是简单地复制文件。我的程序如何知道这种映射是在哪里进行的?是如何进行的?
【前言】 工作或学习可能需要实现基于VC读\写Excel文件的功能,本人最近也遇到了该问题。间虽经波折,但是最终还是找到了解决问题的办法。 在此跟大家分享,希望对跟我同样迷茫过的同学们有所帮助。 1、程序功能 1)打开一个excel文件; 2)显示到CListCtrl上; 3)新建一个Excel文件。 以上均在对话框实现。 2、平台 VC++2010 3、实现方法 常用的Excel打开方式有两种 1)通过数据打开; 2)OLE方式打开。 由于方式1)操作繁琐,经常出现莫名的错误,这里选用方式2). 4、准备步骤 首先新建一个Dialog窗体程序,添加list control和两个按钮 1)将ExcelLib文件夹拷贝到程序目录下; 2)将Export2Excel.h,Export2Excel.cpp两个文件添加到项目; 3)包含头文件,#include "ExcelLib/Export2Excel.h" 通过以上步骤在程序引入了可以读取Excle文件的CExport2Excel类; 5、打开excel文件 通过按钮点击打开 void CExcelTestDlg::OnBnClickedButtonOpenExcel() { //获取文件路径 CFileDialog* lpszOpenFile; CString szGetName; lpszOpenFile = new CFileDialog(TRUE,"","",OFN_FILEMUSTEXIST|OFN_HIDEREADONLY,"Excel File(*.xlsx;*.xls)|*.xls;*.xlsx",NULL); if (lpszOpenFile->DoModal()==IDOK) { szGetName = lpszOpenFile->GetPathName(); SetWindowText(szGetName); delete lpszOpenFile; } else return; //打开文件 //文件包含多个sheet时,默认打开第一个sheet CExport2Excel Excel_example; Excel_example.OpenExcel(szGetName); //获取sheet个数 int iSheetNum = Excel_example.GetSheetsNumber(); //获取已使用表格行列数 int iRows = Excel_example.GetRowCount(); int iCols = Excel_example.GetColCount(); //获取单元格的内容 CString cs_temp = Excel_example.GetText(1,1); //AfxMessageBox(cs_temp); //List control上显示 //获取工作表列名(第一行) CStringArray m_HeadName; m_HeadName.Add(_T("ID")); for (int i=1;iGetItemCount()>0) { m_list.DeleteColumn(0); } //初始化ClistCtrl,加入列名 InitList(m_list,m_HeadName); //填入内容 //第一行是标题,所以从第2行开始 CString num; int pos; for (int row = 2;row<=iRows; row++) { pos = m_list.GetItemCount(); num.Format(_T("%d"),pos +1); m_list.InsertItem(pos,num); for (int colum=1;columDoModal()==IDOK) { szGetName = lpszOpenFile->GetPathName(); SetWindowText(szGetName); delete lpszOpenFile; } else return; //文件全名称 CString csFileName = szGetName; //需要添加的两个sheet的名称 CString csSheetName = "newSheet"; CString csSheetName2 = "newSheet2"; // 新建一个excel文件,自己写入文字 CExport2Excel Excel_example; //新建excel文件 Excel_example.CreateExcel(csFileName); //添加sheet,新加的sheet在前,也就是序号为1 Excel_example.CreateSheet(csSheetName); Excel_example.CreateSheet(csSheetName2); //操作最开始添加的sheet:(newSheet) Excel_example.SetSheet(2); //添加表头 Excel_example.WriteHeader(1,"第一列"); Excel_example.WriteHeader(2,"第二列"); //添加核心数据 Excel_example.WriteData(1,1,"数据1"); Excel_example.WriteData(1,2,"数据2"); //保存文件 Excel_example.Save(); //关闭文件 Excel_example.Close(); } 7、注意事项 1)一般单个Excel文件包含多个sheet,程序默认打开第一个; 2)指定操作sheet,使用Excel_example.SetSheet(2)函数; 3)打开文件时最左侧的sheet序号为1,新建excel时最新添加的sheet序号为1. 【后记】 本程序主要基于网络CSDN---“Excel封装V2.0”---完成,下载地址是:http://download.csdn.net/detail/yeah2000/3576494,在此表示感谢!同时, 1)在其基础上作了小改动,改正了几个小错误,添加了几个小接口; 2)添加了如何使用的例子,原程序是没有的; 3)详细的注释 发现不足之处,还请大家多多指教!

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧