vc runtime deployment问题

    vc8以后的运行时部署有两种方式:shared assembiles 和 private assembiles. 当我们的exe(dll)包含的manifest文件对应的vc runtime版本只有一个时使用private assembiles较为方便,当runtime版本为一个新版本和至少一个旧版本(这里只的是同一个dll的版本)推荐使用shared assembiles。他们都是基于Micrsoft vc runtime side by side(SxS),也就是为了避免dll的版本冲突造成程序运行的不确定性。他们的解决办法是在每个exe(dll)中内嵌(或者附带)一个标记所需运行时版本的manifest文件(一个xml文件),在vista以后exe(dll)嵌入的dll有更高的优先级。

 

SxS系统通过解析这些manifest,有时需要结合系统中的policy文件,来找到对应版本的runtime。那么private assembiles 是指每个应用程序有自己的一份runtime,通常在exe(dll)的Microsoft.VC80.CRT(MRC.ATL)文件夹下,文件夹中为开发时所用的runtime版本,这些在vc开发包里可以找到(在有多版本runtime时不能使用),详细见第三部分。相反shared assembiles 指的是所用软件共享统一的runtime,它们在系统的%SystemDir%\Windows\winsxs(Win7 Vista), %SystemDir%\Windows\WinSxS(XP),里面的一些文件夹对应着不同版本的runtime,他们的名字包含runtime类型,版本,标识码,当SxS解析manifest文件时会在这里找有没有对应的文件夹,进而找到对应的运行时。SxS是按照一个固定的顺序来搜索runtime的,这和系统加载dll时的顺序有很大区别,详细内容请点我

如果没有找到对应版本的runtime或者没有找到文件的manifest文件,那么exe加载失败(dll Loadlibrary失败),通常表现为”应用程序无法正常运行,请重新安装……”。如果遇到上述问题说明项目的部署不正确,这时需要有一台干净的机器和一台开发机器来重新部署,具体的部署方式见这里,这里是一些例子。如果觉得msdn的解释不够清楚,我收集到了了两种方式很好的资料。

请看下面:

Creating your MSI installer using Visual Studio 2008 (shared assembiles )

As we know from reading the Application Packaging Requirements Guide (http://appdeveloper.intel.com/en-us/article/packaging-requirements), we must provide our entry in a MSI format for Windows entries. I have received numerous requests for assistance in doing this. Here is a simple step by step to create your MSI installer.

Step 1 Create a Setup and Deployment Project

Let's create our new project. Right click on your solution in the Solution Explorer on the right hand side of your Visual Studio IDE and select Add -> New Project. From the list of project types, choose Other Project Types -> Setup and Deployment -> Setup Project.

Step 2 Setup Properties

We would like everyone to know who created this installer. Click on your new Setup and Deployment project in the solutions explorer. Now you will see in the Properties windows (Just below the Solutions Explorer usually), settings for Manufacturer, Author, and Title. Fill these in as appropriate.

Step 3 Add Project Output & Content

We want to include our project .exe and all required content files. Right click on your Setup and Deployment project in the Solution Explorer and choose View -> File System. Right click on the Application Folder node and choose Add -> Project Output. Choose Primary Output, this will include your .exe. Repeat this step and choose Content Files if your project has required content such as images, audio, etc.

* Special Note: In your Application project, ensure all required files are marked as Content. This can be done by selecting the file in the Solution Explorer and setting the Content property to True.

We need to include our icon to use in our shortcut later. Right click on the Application Folder node and choose Add -> File. Browse to your icon file and click OK.

Step 4 Create Shortcuts

Another requirement is to include a shortcut to our application. Fortunately this is quite simple. With the Setup and Deployment File System tab still open, right click in the right hand pane to bring up a context menu. Choose Create New Shortcut. From this dialogue, navigate into the Application Folder, and choose Primary Output from "Project name" (Active). This will point the shortcut to your .exe. Click OK to accept this selection.

Let's give that shortcut an icon as well. Click on the shortcut you just created in the right hand pane. From the Properties window you may select an icon. Click Browse, and navigate to the Application Folder, and select the icon you added to the File System back in Step 3.

If you wish to have a shortcut in the users Start Menu, repeat the steps above, substituting the User's Programs Menu node instead of User's Desktop node.

Step 5 C++ Runtime (CRT)

This step is critical for validation. The ATOM SDK requires the C++ Runtime to execute. Fortunately our Setup and Deployment project makes this an easy addition. Right click on your Setup and Deployment project in the Solution Explorer and choose Add -> Merge Module. You want to add two merge modules, one for CRT Release, and one for CRT Debug. These are labeled:

Microsoft_VC90_CRT_x86.msm
Microsoft_VC90_DebugCRT_x86.msm

* Special Note: If your application requires additional merge modules or runtime that is not automatically detected, this would be the time to add them

Step 6 Build

The easiest part of this exercise. Right click on your Setup and Deployment project and choose Build. If all went well, you will have a nicely packaged MSI in your output folder ready to upload to the App Store.

IMPORTANT DETAILS ON SILENT INSTALL REQUIREMENT

One critical requirement in the validation process is that your MSI installed silently. You can test this by opening a command prompt, and executing your MSI using the /qn switch.

Example: c:\MyApp.msi /qn

If it installs without displaying any user interface, you have succeeded in this part of the validation

* Note: The use of the /qn switch has not been confirmed by Intel yet.

If you have any problems please do not hesitate to ask. Best of luck!

Fortunately this is quite simple and should not cause most installers implementation problems (See below if you find yourself in this situation)

1.) Open your Visual Studio Package and Deployment project.

2.) Right click on your project in the Solution Explorer and select View -> User Interface

3.) Remove all dialogues

4.) Recompile and test for validation compliance (* See above)

Deploying Visual C++ Runtime Files as Private Assemblies (private assembiles.)

If you create a C++ project in Visual Studio and configure it to "Use MFC in a Shared DLL" (the default) you need to make sure the C runtime (CRT) and the MFC libraries are installed in the correct versions on the end user's computer. That can be difficult.

There are three ways to install the libraries on target computers. In this article I focus on the "private assembly" method where the libraries are stored in your application's directory. Some of its advantages are that you can run the program from any location, even a network share, without installing parts of it to the user's SxS folder first. And you need not worry about calling VC_Redist from your setup.

What you do is simple:

Locate the appropriate folders in C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\x86\ (or AMD64 if you build a 64-bit version). In many cases, when using the runtime and MFC you need Microsoft.VC90.CRT and Microsoft.VC90.MFC. Copy these folders to you application's binary folder, for example:

C:\MyAppFolder\Application.exe

C:\MyAppFolder\Microsoft.VC90.CRT

C:\MyAppFolder\Microsoft.VC90.MFC

That is all. Redistribute/install your application like this.

Caveats

Your executable's manifest (incorporated into your EXE file as a resource) lists the versions of the runtime libraries it requires. The versions listed in the manifest are the initial versions installed on your development machine, though. In the case of Visual Studio 2008 these are the versions of the pre-SP1 libraries. Once you install Service Pack 1 you get the newer libraries in the folder C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\redist\x86, but the manifest in your own binary still demands the original library versions.

That does not work. In fact, it crashes your application when run on a "clean" system.

What you need to do is tell the compiler you want to depend on the newest versions of the libraries. You do that by including the following lines at the very top of Stdafx.h of every binary:

  1: #define _BIND_TO_CURRENT_CRT_VERSION 1
  2: 
  3: #define _BIND_TO_CURRENT_ATL_VERSION 1
  4: 
  5: #define _BIND_TO_CURRENT_MFC_VERSION 1
  6: 
  7: #define _BIND_TO_CURRENT_OPENMP_VERSION 1

or, a combination of all these:

  1: #define _BIND_TO_CURRENT_VCLIBS_VERSION 1

Please note: "Generated files (eg by MIDL) don't include stdafx.h, so putting _BIND_TO_CURRENT_VCLIBS_VERSION in stdafx won't work in this case. You must use _BIND_TO_CURRENT_VCLIBS_VERSION=1 in the C/C++ Preprocessor Definitions page of every project configuration." (Jon Baggott on http://msdn.microsoft.com/en-us/library/cc664727.aspx)

Updates, Patches and Service Packs

You may wonder what happens if you happily install the most current libraries on your users's computers and, some time later, an updated version is released by Microsoft. Will your application continue to use the then old and insecure version? Good question!

If a new version of the runtime library is pushed down via Windows Update and installed to %Windir%WinSxS, not only are the library binaries and their manifest updated, but also a policy file is installed that basically tells the loader to use the new version instead of the old version. See this example (from %Windir%\WinSxS\Manifests\x86_policy.9.0.microsoft.vc90.mfc_1fc8b3b9a1e18e3b_9.0.30729.1_none_7dd1e0ebd6590e0b.manifest):

  1: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  2: 
  3: <!-- Copyright (c) Microsoft Corporation. All rights reserved. -->
  4: 
  5: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  6: 
  7: <assemblyIdentity type="win32-policy" name="policy.9.0.Microsoft.VC90.MFC" 
  8:     version="9.0.30729.1" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
  9: 
 10: <dependency>
 11: 
 12: <dependentAssembly>
 13: 
 14: <assemblyIdentity type="win32" name="Microsoft.VC90.MFC" processorArchitecture="x86" 
 15:     publicKeyToken="1fc8b3b9a1e18e3b"/>
 16: 
 17: <bindingRedirect oldVersion="9.0.20718.0-9.0.21022.8" newVersion="9.0.30729.1"/>
 18: 
 19: <bindingRedirect oldVersion="9.0.30201.0-9.0.30729.1" newVersion="9.0.30729.1"/>
 20: 
 21: </dependentAssembly>
 22: 
 23: </dependency>
 24: 
 25: </assembly>

This tells the loader to use the version 9.0.30729.1 instead of the versions 9.0.20718.0 and 9.0.30201.0.

Nice, but how does this affect your application with its private assemblies (not tied to the WinSxS folder)? Simple, but effective solution: the loader always looks into the WinSxS folder first. So if your application needs mfc90.dll in version 9.0.30201.0 and version 9.0.30201.0 is what you have installed in your application folder, with the help of the policy file above Windows will load the newer version from SxS nevertheless.

For the sake of completeness here is simplest form of the assembly search sequence:

  1. Side-by-side searches the WinSxS folder.
  2. <appdir>\<assemblyname>.DLL
  3. <appdir>\<assemblyname>.manifest
  4. <appdir>\<assemblyname>\<assemblyname>.DLL
  5. <appdir>\<assemblyname>\<assemblyname>.manifest

And for those who still question the use of private assemblies: here is a list of products installed on my system that use them:

  • C:\Program Files (x86)\Citrix\ICA Client\msvcm80.dll
  • C:\Program Files (x86)\McAfee\Common Framework\Microsoft.VC80.CRT\msvcm80.dll
  • C:\Program Files (x86)\TechSmith\Camtasia Studio 6\Microsoft.VC90.CRT\msvcm90.dll
  • C:\Program Files (x86)\VMware\VMware Workstation\Resources\msvcm80.dll

And if we take a last look, at, for example, Camtasia Studio: its private version of msvcm90.dll is 9.0.21022.8, but when we examine its loaded DLLs in Process Explorer, we see it uses 9.0.30729.4926 from WinSxS. Magic!

Addendum: Application Crashes at Startup because MSVCR90.DLL is Not Found

Some time after implementing the solution described in this article for a medium-sized project I was made aware of a strange problem: on some machines the application crashes while loading before even being able to display any messages.

The usual debugging tools sxstrace and fuslogvw (Fusion log viewer) did not show anything useful, but Dependency Walker was helpful. It pointed out the problem right away:

Note: CoreFunctions.dll is one of the DLLs of our product. It is dependent on the Visual C runtime files (including msvcr90.dll) and msvcr90.dll is located in the subfolder Microsoft.VC90.CRT as described in this article. But still, msvcr90.dll is not found by the OS loader.

After some research I found out that this happens both on XP (SP3) and Vista (SP2) if and only if the application is started from a mapped network drive. Copying the application's folder to the local hard drive makes the problem go away. Another way to fix this is to put the VC runtime libraries directly into the application folder, not in the subdirectory Microsoft.VC90.CRT.

参考:

http://appdeveloper.intel.com/en-us/node/733

msdn library

http://www.codeproject.com/Articles/104529/Deploying-Visual-Cplusplus-Runtime-Files-as-Privat.aspx?display=Print

http://stackoverflow.com/questions/2335476/loadlibrary-fails-to-load-dll-with-manifest-and-private-assembly

原文地址:https://www.cnblogs.com/hucn/p/2054709.html