免注册 com dll 要求安装 .net framework 3.5,而它在注册时工作正常

Posted

技术标签:

【中文标题】免注册 com dll 要求安装 .net framework 3.5,而它在注册时工作正常【英文标题】:Registration free com dll asks for .net framework 3.5 installation while it is working fine when registered 【发布时间】:2018-01-07 04:50:35 【问题描述】:

我有一个用 c# 编写的 COM DLL。我已经尝试注册它并且它工作正常。我正在尝试免费注册使用它。

我完全按照this MSDN 教程进行操作。

SideBySide DLL 源代码

using System;
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: Guid("C49B4D72-DEB3-41F3-87DE-9AA0E0E99809")] //LIBID_SideBySide

namespace SideBySide

    [Guid("1289C276-6CF8-456F-9CD3-14363BA5BEB5")] //IID_ISideBySideClass
    public interface ISideBySideClass
    
        string Version();
    

    [Guid("16AD5303-E154-44B4-A72B-C129859714AD")]  //CLSID_SideBySideClass
    public class SideBySideClass : ISideBySideClass
    
        public string Version()
        
            return "1.0.0-C#";
        
    

SideBySide.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
  manifestVersion="1.0">
<assemblyIdentity
            type="win32"
            name="SideBySide"
            version="1.0.0.0" />
<clrClass
            clsid="16AD5303-E154-44B4-A72B-C129859714AD"
            progid="SideBySide.SideBySide"
            threadingModel="Both"
            name="SideBySide.SideBySideClass" >
</clrClass>
</assembly>

应用程序清单 Client.exe.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
   manifestVersion="1.0">
<assemblyIdentity
            type = "win32"
            name = "client"
            version = "1.0.0.0" />
<dependency>
            <dependentAssembly>
                        <assemblyIdentity
                                    type="win32"
                                    name="SideBySide"
                                    version="1.0.0.0" />
            </dependentAssembly>
</dependency>
</assembly>

用法

Method1 是教程建议使用 DLL 的方式。我已经探索并提出了使用激活上下文的方法2。

方法1

/*
Using CreateInstance
*/
int method1()

    CoInitializeEx(0, COINIT_MULTITHREADED);
    ISideBySideClassPtr ptr;
    HRESULT hr = ptr.CreateInstance(__uuidof(SideBySideClass));
    if (SUCCEEDED(hr))
    
        cout << ptr->Version() << endl;
    
    else 
    
        //The dialog box asking for .net framework 3.5 installation comes up here
    
    CoUninitialize();
    return 1;

方法二

/*
Using Activation context
*/
int method2()

    HRESULT _hr = CoInitializeEx(0, COINIT_MULTITHREADED);
    if( _hr != S_OK)
    
        return FALSE;
    

    DWORD cookie = 0;

    ACTCTX actctx;
    actctx.cbSize = sizeof(ACTCTX) ;
    actctx.lpSource = L"SideBySide.dll";
    actctx.lpResourceName = //_T("SideBySide"); //error
        MAKEINTRESOURCE(1); //This alone worked for CreateActCtx
        //MAKEINTRESOURCE(2); //error
    actctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID ;

    HANDLE hActCtx = CreateActCtx(&actctx);
    if( hActCtx == INVALID_HANDLE_VALUE)
    
        //This usually fails here.
        //But with the above mentioned values this succeeds
        return E_FAIL;
    

    BOOL fOK = ActivateActCtx(hActCtx, &cookie);
    if (!fOK)
       
        return E_FAIL;
    

    CComPtr<ISideBySideClass> spCSharpTest;
    HRESULT hr = spCSharpTest.CoCreateInstance(__uuidof(SideBySideClass));

    if (hr != S_OK)
    
        //The dialog box asking for .net framework 3.5 installation comes up here
    
    else
    
        cout << "Load Successfully : SideBySideClass" << endl;
        spCSharpTest->Version();
        //Need not release. CComPtr will take care of it
    

    DeactivateActCtx(0, cookie);
    ReleaseActCtx(hActCtx);
    CoUninitialize();
    return 0;

问题

当我尝试创建类的实例时,这两种方法都失败并给出以下错误 0x80131700 (2148734720)(没有描述),然后出现以下对话框,提示安装 .net framework 3.5 :

我在 SideBySide C# 项目的 Properties->Application 中将“Target framework”指定为 .NET framework 4.5,并且在注册 com dll 时它可以正常工作。我不明白为什么它在尝试未经注册的情况下使用时要求使用旧版本。

我应该在清单文件的任何位置指定 .net 框架版本吗? 可能是什么问题呢?任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

是的,您需要在使用 .NET 4.0 或更高版本时指定运行时版本。如果服务器清单中缺少此信息,则激活上下文将查找 .NET 4.0 之前可用的最高运行时版本,即版本 3.5。

只需添加所需的 .NET 运行时版本如下(注意runtimeVersion 属性):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
  manifestVersion="1.0">
<assemblyIdentity
            type="win32"
            name="SideBySide"
            version="1.0.0.0" />
<clrClass
            clsid="16AD5303-E154-44B4-A72B-C129859714AD"
            progid="SideBySide.SideBySide"
            threadingModel="Both"
            name="SideBySide.SideBySideClass"
            runtimeVersion="v4.0.30319" >
</clrClass>
</assembly>

【讨论】:

谢谢,这两种方法都有效!但是现在我们是否限制 dll 仅在安装了 .NET Framework v4.0.30319 时才能工作?是否可以要求它使用任何可用的框架,可能就像提到runtimeVersion="*" runtimeVersion="v4.0.30319" 没有定义特定的构建,因为此版本号在所有 .NET 4.x 运行时版本之间共享。因此,您将能够使用任何可用的 .NET 4.x 版本。

以上是关于免注册 com dll 要求安装 .net framework 3.5,而它在注册时工作正常的主要内容,如果未能解决你的问题,请参考以下文章

可以将免注册 COM 应用于 DLL 吗?

免注册 COM/DLL?

使用 C#/托管代码为免注册 COM 互操作设置 DLL

无需生成清单的免注册 COM

SilverLight 组件能否实例化免注册的 COM 可见 .NET 对象

.NET Framework 3.5免重启方法