Sunday, November 16, 2008

.net程序的运行问题:This application has failed to start because the application configuration is incorrect

在运行.net编译的程序时出现问题:This application has failed to start because the application configuration is incorrect, reinstalling the application may fix this problem:

这个问题大部分是因为使用了managed code导致的,对我来说已经非常常见了-_-b,解决方法有三种:
在出现问题的机器重新编译原工程;
用程序打包的方式发布程序到出现问题的机器;
尝试采用静态连接MFC的方式编译工程;
或是直接在出现问题的机器上安装vc redistribution package(vcredist.exe)

下面是篇有用的转载文章,可以参考。
from: http://tydbits.org/This-application-has-failed-to-start-because-the-application-configuration-is-incorrect

So we’ve created our managed C++ application, using Visual Studio 2005, and it was fun and surprisingly easy thanks to the C++/CLI, so we happily gave it to the QA or a customer, and— well, it didn’t take off, the operating system just refused to launch it. And the error message wasn’t very descriptive either:

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'cpp.managed, Version=..., Culture=..., PublicKeyToken=...' or one of its dependencies. <…>
---> System.Runtime.InteropServices.COMException (0x800736B1): This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem. (Exception from HRESULT: 0x800736B1)
at app.Main(String[] argv)

It’s a little bit less of information, than is needed to get clear understanding of what’s going on.

Configuration

Let’s imagine that we have the following components:

app.exe
cpp.managed.dll
cpp.native.dll

I.e. a managed application app.exe, which depends on a C++/CLI cpp.managed.dll, which in turn depends on a native cpp.native.dll.

Finding out what’s wrong

First of all, let’s open the Event Viewer, and try to find error messages with the Source = SideBySide.

Windows XP or Windows Server 2003

We are likely to get several entries in the “System” Event Log, neither of which has full version information of the missing dependency:

Generate Activation Context failed for cpp.managed.dll. Reference error message: The referenced assembly is not installed on your system.

Resolve Partial Assembly failed for Microsoft.VC80.CRT. Reference error message: The referenced assembly is not installed on your system.

Dependent Assembly Microsoft.VC80.CRT could not be found and Last Error was The referenced assembly is not installed on your system.

Vista

There we should find in the Event Log something like follows:

Activation context generation failed for "cpp.managed.dll". Dependent Assembly Microsoft.VC80.CRT, processorArchitecture="x86", publicKeyToken="1fc8b3b9a1e18e3b", type="win32", version="8.0.50727.762" could not be found. Please use sxstrace.exe for detailed diagnosis.

Fixing it

All we need is to deploy VC++ runtime to the target system.

For the purpose of our example let’s imagine that we didn’t want to redistribute VC++ CRT as shared assemblies (installing it into C:\Windows\WinSxS), but instead decided to redistribute them as private assemblies. Here’s how it can look like:

app.exe
cpp.managed.dll
cpp.native.dll
Microsoft.VC80.CRT.manifest
msvcm80.dll
msvcp80.dll
msvcr80.dll

How it can fail again, or split dependencies

Of course the life is not always easy. We did the above, and it still fails with the same error message. Well, now we know what to do, and we rush to the Event Viewer.

Windows XP or Windows Server 2003

In this case Event Log has something along the following lines:

Generate Activation Context failed for cpp.native.dll. Reference error message: A component version required by the application conflicts with another component version already active.

Unfortunately, the message does not mention neither the dependencies, nor their versions which conflict. To find that out we have several options of inspecting the cpp.native.dll manifest: * taking a look at the *.intermediate.manifest or *.embed.manifest files in the intermediate build directory, * using a resource editor or some other tool to view the manifest, actually embedded into the cpp.native.dll, * or we could just use a text viewer, and search for the “dependentAssembly” string in the binary.

E.g. here’s the output of a combination of strings and grep utilities (reformatted for readability):

> strings cpp.native.dll | grep dependentAssembly














Isn’t it strange, that we have dependency on two different versions of Microsoft.VC80.CRT? Well, with Visual Studio 2005 SP1 out it’s quite possible, and in our case cpp.native.dll indeed was linked with some static libraries, compiled with pre-SP version of Visual Studio 2005.

Vista

Due to the Vista improved side-by-side errors diagnostics, there Event Log should contain just enough information to understand what’s going on:

Activation context generation failed for "cpp.native.dll". Error in manifest or policy file “” on line . A component version required by the application conflicts with another component version already active. Conflicting components are:.
Component 1: C:\Windows\WinSxS\manifests\ x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.312_none_10b2ee7b9bffc2c7.manifest.
Component 2: Microsoft.VC80.CRT.MANIFEST.

Fixing it (again)

An obvious (and correct) solution is to rebuild all the libraries with the new version of Visual Studio 2005. If we cannot do it, or just want to save some time during development, and postpone rebuilding the dependencies for later time, we’d want to try workarounds, mentioned by Nikola Dudar in his blog:

  • Workaround#1:

    Install the newer version (8.0.50727.762 in this case) of VC++ MSMs or VCRedist.EXE on a machine where your application is going to run. Once policy for VC++ assemblies is installed on that machine they are going to redirect all loads of older versions (8.0.50608.0) to the newest version available on the machine.

Note that to apply this workaround we’d need to download the updated vcredist.exe.
  • Workaround#2:

    If you are redistributing VC++ libraries in application’s local folder, you need to add an application configuration file that redirects an attempt to load 8.0.50608.0 version to 8.0.50727.762 version. Configuration file has to have same name as the exe plus .config extension and has to be right next to exe or embedded into the EXE. Here is an example of a configuration file that one would use to resolve issue with the manifest from above:

For this to work in our case we’d need to apply some magic.

No comments:

Post a Comment