免注册 COM 在本地机器上运行,但在 Azure App Service 中抛出异常

Registration-free COM works on a local machine, but throws exception in Azure App Service

正在尝试在 Azure 应用服务中使用 COM 库。该库是 32 位的,服务在 32 位中也配置为 运行。

为了在本地机器上 运行 无需注册,我创建了一个清单文件,并从 https://www.manifestmaker.com/sxs/help/iis_aspnet.htm 中的示例中复制了自定义激活码。这样 dll 就可以在没有 COM 注册的本地机器上成功加载和激活。

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
  <assemblyIdentity name="pp_cli_com_lib" version="1.0.0.0" type="win32" />
  <file name="pp_cli_com.dll" asmv2:size="460800">
    <hash xmlns="urn:schemas-microsoft-com:asm.v2">
      <dsig:Transforms>
        <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
      </dsig:Transforms>
      <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <dsig:DigestValue>JQXRI2IOR9A7KAn4+yW8n9pGMz0=</dsig:DigestValue>
    </hash>
    <typelib tlbid="{85796a56-cee8-426a-81e2-c896d7b3dbbd}" version="1.0" helpdir="" resourceid="0" flags="HASDISKIMAGE" />
    <comClass clsid="{6d7c883b-9cca-4fc1-badb-fdc367b44ae7}" threadingModel="Apartment" tlbid="{85796a56-cee8-426a-81e2-c896d7b3dbbd}" progid="Pp_cli_com.KCP.1" description="KCP Class" />
  </file>
</assembly>
            var wmh = new WebManifestHelper();
            var activated = wmh.ActivateWebManifest("pp_cli_com_lib.manifest");
            if (!activated)
            {
                throw new InvalidOperationException($"Unable to activate! Error code: {wmh.dwError}.");
            }
            var kcpObject = new PP_CLI_COMLib.KCP();

然而,当尝试在 Azure 应用服务中执行相同操作时,出现以下错误:

[FileLoadException: Retrieving the COM class factory for component with CLSID {6D7C883B-9CCA-4FC1-BADB-FDC367B44AE7} failed due to the following error: 8007045a A dynamic link library (DLL) initialization routine failed. (Exception from HRESULT: 0x8007045A).] System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +122 System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +239 System.Activator.CreateInstance(Type type, Boolean nonPublic) +85 System.Activator.CreateInstance(Type type) +12

这是否意味着这个特定的 COM 库与 Azure 应用服务沙箱环境不兼容?

创建Azure应用服务器时,Publish的默认选项是使用沙箱环境的代码。

所以默认创建的webapp不支持免注册com.

但是Azure App Service supports Windows Containers,你可以自定义容器。

为了 运行 Azure 应用服务中的免注册 COM,采取了以下步骤:

  1. 按照https://docs.microsoft.com/en-us/azure/app-service/quickstart-custom-container?pivots=container-windows
  2. 中所述创建和发布自定义容器
  3. 将应用程序池切换到 32 位模式
  4. 将 Visual C++ 可再发行组件添加到容器映像(此特定 COM 库需要)

生成的 Dockerfile:

FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'SilentlyContinue'; $ProgressPreference = 'SilentlyContinue';"]
ADD https://download.microsoft.com/download/C/6/D/C6D0FD4E-9E53-4897-9B91-836EBA2AACD3/vcredist_x86.exe /vcredist_x86.exe
RUN Start-Process -filepath C:\vcredist_x86.exe -ArgumentList "/install", "/passive", "/norestart", "'/log vcredist-setup.log'" -PassThru | wait-process
RUN "C:\Windows\System32\inetsrv\appcmd.exe set apppool /apppool.name:DefaultAppPool /enable32BitAppOnWin64:true"
ARG source
WORKDIR /inetpub/wwwroot
COPY ${source:-obj/Docker/publish} .