【问题标题】:How do I force a native application to use an older C runtime如何强制本机应用程序使用较旧的 C 运行时
【发布时间】:2010-06-22 22:22:52
【问题描述】:

Visual Studio 2010 安装版本 ...4974 的 VC9 运行时,其 .pdbs are unavailable。如何强制我的 GME.exe 使用较旧的 VC9 运行时?

我试过把这个放到GME.exe.config:

<?xml version="1.0"?>
<configuration>
  <windows>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <assemblyIdentity type="win32" name="GME" processorArchitecture="x86" version="1.0.0.1"/>
      <dependentAssembly>
        <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" publicKeyToken="1fc8b3b9a1e18e3b" processorArchitecture="x86" />
        <bindingRedirect oldVersion="9.0.21022.8-9.0.21022.4974" newVersion="9.0.30729.4148" />
        <bindingRedirect oldVersion="9.0.30729.0-9.0.30729.4974" newVersion="9.0.30729.4148" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity type="win32" name="Microsoft.VC90.MFC" publicKeyToken="1fc8b3b9a1e18e3b" processorArchitecture="x86" />
        <bindingRedirect oldVersion="9.0.21022.8-9.0.21022.4974" newVersion="9.0.30729.4148" />
        <bindingRedirect oldVersion="9.0.30729.0-9.0.30729.4974" newVersion="9.0.30729.4148" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity type="win32" name="Microsoft.VC90.ATL" publicKeyToken="1fc8b3b9a1e18e3b" processorArchitecture="x86" />
        <bindingRedirect oldVersion="9.0.21022.8-9.0.21022.4974" newVersion="9.0.30729.4148" />
        <bindingRedirect oldVersion="9.0.30729.0-9.0.30729.4974" newVersion="9.0.30729.4148" />
      </dependentAssembly>
    </assemblyBinding>
  </windows>
</configuration>

但是,sxstrace 报告:

INFO: Resolving reference Microsoft.VC90.CRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8"
....
INFO: Publisher Policy redirected assembly version.

&lt;dependentAssembly&gt; 下添加&lt;publisherPolicy apply="no"/&gt; 会导致ERROR: Activation Context generation failed. 在Windows 7 上没有其他有用信息。

请注意,这仅用于调试我的本地副本,而不是重新分发,因此我不担心安全更新或发布者政策的其他好处。

【问题讨论】:

    标签: windows visual-c++ manifest config winsxs


    【解决方案1】:

    答案来自http://blog.kalmbachnet.de/?postid=80

    诀窍是从应用程序清单中删除 assemblyIdentity 上的 publicKey 属性,因此不使用 WinSxS。

    GME.exe.manifest:

    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
      <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
          <requestedPrivileges>
            <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
          </requestedPrivileges>
        </security>
      </trustInfo>
      <dependency>
        <dependentAssembly>
          <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.30729.4148" processorArchitecture="x86">
          </assemblyIdentity>
        </dependentAssembly>
      </dependency>
      <dependency>
        <dependentAssembly>
          <assemblyIdentity type="win32" name="Microsoft.VC90.MFC" version="9.0.30729.4148" processorArchitecture="x86">
          </assemblyIdentity>
        </dependentAssembly>
      </dependency>
      <dependency>
        <dependentAssembly>
          <assemblyIdentity type="win32" name="Microsoft.VC90.ATL" version="9.0.30729.4148" processorArchitecture="x86">
          </assemblyIdentity>
        </dependentAssembly>
      </dependency>
      <dependency>
        <dependentAssembly>
          <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*">
          </assemblyIdentity>
        </dependentAssembly>
      </dependency>
    </assembly>
    

    将清单嵌入GME.exe(用1代替2来修改dll):
    mt -manifest GME.exe.manifest -outputresource:GME.exe;1

    然后复制必要的dll:
    cp -a windows/winsxs/x86_microsoft.vc90.{atl,crt,mfc}*30729.4148*/*dll path-to-app/

    然后为每个未使用 SxS 的程序集创建清单,并将它们放在应用程序旁边。清单基于例如C:\Windows\WinSxS\Manifests\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.4148_none_5090ab56bcba71c2.manifest:
    Microsoft.VC90.CRT.Manifest:

    <?xml version="1.0"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.30729.4148" processorArchitecture="x86"></assemblyIdentity>
        <file name="msvcr90.dll"></file>
        <file name="msvcp90.dll"></file>
        <file name="msvcm90.dll"></file>
    </assembly>
    

    无法从应用程序清单中删除程序集引用,因为 CRT 抱怨它不是通过 SxS 加载的。

    不幸的是,似乎必须修改应用程序中每个依赖 dll 的清单,包括从 WinSxS 复制的 dll,否则可能会加载多个版本。

    这是一个对我有用的 bash 脚本,其中 ~/Documents/sxs-hack/ 包含 CRT dll 和修改后的清单:

    rm -rf bin
    mkdir bin
    cp -a ~/Documents/sxs-hack/* bin/
    find -iname \*.dll -or -iname \*.ocx -or -iname \*.exe | while read -r file; do
      cp -a "$file" bin/"$(basename $file)"
      export file=bin/"$(basename $file)"
      export res=$file\;2
      if [ ${file:${#file}-3} = "exe" ]; then export res=$file\;1; fi
      echo $file
      mt.exe -nologo -inputresource:"$res" -out:extracted.manifest &&
      perl -pli -e 's/(Microsoft.VC90.[^>]*)version="[^"]*"([^>]*)publicKeyToken="[^"]*"/$1 $2 version="9.0.30729.4148"/g;' extracted.manifest &&
      mt -nologo -manifest extracted.manifest -outputresource:"$res"
      regsvr32 /s "$file" || true
    done
    

    【讨论】:

      【解决方案2】:

      以下是让应用程序配置与 Win2003 及更高版本一起使用的技巧:

      http://www.tech-archive.net/Archive/VC/microsoft.public.vc.ide_general/2008-01/msg00033.html

      本质上,需要使用“EnableAppConfig”将应用添加到兼容性数据库中

      这在此处记录:

      http://msdn.microsoft.com/en-us/library/ee710783%28VS.85%29.aspx

      工作GME.exe.Config:

      <?xml version="1.0"?>
      <configuration>
        <windows>
          <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
              <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
              <publisherPolicy apply="no"/>
              <bindingRedirect oldVersion="9.0.21022.0-9.0.21022.4974" newVersion="9.0.30729.1" />
            </dependentAssembly>
            <dependentAssembly>
              <assemblyIdentity type="win32" name="Microsoft.VC90.MFC" publicKeyToken="1fc8b3b9a1e18e3b" processorArchitecture="x86"/>
              <publisherPolicy apply="no"/>
              <bindingRedirect oldVersion="9.0.21022.0-9.0.21022.4974" newVersion="9.0.30729.1" />
            </dependentAssembly>
            <dependentAssembly>
              <assemblyIdentity type="win32" name="Microsoft.VC90.ATL" publicKeyToken="1fc8b3b9a1e18e3b" processorArchitecture="x86"/>
              <publisherPolicy apply="no"/>
              <bindingRedirect oldVersion="9.0.21022.0-9.0.21022.4974" newVersion="9.0.30729.1" />
            </dependentAssembly>
      
          </assemblyBinding>
        </windows>
      </configuration>
      

      似乎也需要为加载的 .dll 执行此操作。

      【讨论】:

        【解决方案3】:

        如果你有源代码,你总是可以静态链接你想使用的 c-runtime 库......这并不总是最好的主意,但如果你继承了一个只能在调试模式下运行的怪物库,并且无法重新分发调试 CRT 它会解决问题...

        【讨论】:

        【解决方案4】:

        以下是在 Vista 或 7 上禁用发布者策略的方法:

        导航到 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide\Winners\x86_policy.9.0.microsoft.vc90.crt_1fc8b3b9a1e18e3b_none_02d0010672fd8219\9.0

        将默认键设置为您想要的版本,例如9.0.30729.4148。将您不想要的版本设置为 0,例如“9.0.30729.4974”=00。

        你必须对 crt、atl、mfc 等执行此操作。

        WinSxS 似乎缓存了策略。这对我有用:触摸(1)应用程序,然后将 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SideBySide\PublisherPolicyChangeTime 设置为较低的值,例如10.

        这将为整个系统禁用较新的运行时。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多