【问题标题】:Unable to cast COM object of type 'System.__ComObject' with STAThread attribute无法使用 STAThread 属性强制转换类型为“System.__ComObject”的 COM 对象
【发布时间】:2016-05-13 16:13:16
【问题描述】:

我编写了一个 Windows 服务,它使用防火墙 COM 库 Interop.NetFwTypeLib 来管理 TCP 传输的规则。在两台机器上部署不会报告问题,但我最近在另一台计算机上安装它并收到异常:

无法将“System.__ComObject”类型的 COM 对象转换为接口类型“NetFwTypeLib.INetFwRule3”。此操作失败,因为 IID 为“{B21563FF-D696-4222-AB46-4E89B73AB34A}”的接口的 COM 组件上的 QueryInterface 调用因以下错误而失败:不支持此类接口(来自 HRESULT 的异常:0x80004002 (E_NOINTERFACE))

看完这篇文章后:

我将 STAThreadAttribute 设置为这段代码的 Main 方法,以测试我是否解决了问题,但没有任何解决方案:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        try{
            var type = Type.GetTypeFromProgID("HNetCfg.FWRule");
            var instance = (INetFwRule3) Activator.CreateInstance(type);

            Console.WriteLine("OK");
        }
        catch (Exception exception){
            Console.WriteLine(exception);
        }
    }
}

令我惊讶的是,我运行此脚本以在注册表中查找 CLSID,并且在两台计算机上都没有返回任何结果,无论在哪里工作,哪里都不工作。:

reg query HKCR\CLSID | find /i "{B21563FF-D696-4222-AB46-4E89B73AB34A}"

这些是来自服务所在计算机的信息:

**OS**
Windows Server 2012 R2 Standard

**FirewallAPI.dll file on Windows/system32**
File version: 6.3.9600.17415
Product version: 6.3.9600.17415
Size: 736 kb 
Date modified: 4/28/2015 8:51 PM

来自服务失败的计算机的信息:

**OS**
Windows Server 2011 Service Pack 1

**FirewallAPI.dll file on Windows/system32**
File version: 6.1.7600.16385
Product version: 6.3.7600.16385
Size: 730 kb 
Date modified: 7/13/2009 8:51 PM

问题:

  • 可能是FirewallAPI.dll的版本不同导致的问题?
  • 如果是这样,更新 dll 就足够了,尽管注册表上可能存在不一致似乎有点危险?

【问题讨论】:

  • 这是简单的解释,INetFwRule3 接口是在 Windows 8 和 Server 2012 中添加的。不知道“Windows Server 2011”可能是什么,但它肯定是 1。你需要将自己限制在 INetFwRule2 或更少。 Fwiw,HKCR\CLSID 键是类 guid 的主页,而不是接口 guid。
  • 我会按照你的建议试试,你知道操作系统对INetFwRule2接口的限制吗?
  • 就是RTFM,界面看MSDN文章底部。
  • 您的解释对我有用,感谢您的时间和知识,请在您有响应时间时将其写为答案。
  • 其实不需要我写,自己写就行了。

标签: c# com windows-firewall-api


【解决方案1】:

感谢@Hans cmets,我可以写出这个答案。

阅读MSDN上的文档后:

我找到了每个接口支持的最低客户端和服务器。

var osVersion = Environment.OSVersion.Version;

if(osVersion.Major < 6)
    throw new Exception("INetFwRule is not available for current OS version. Minimun OS version required is Windows Vista or Windows Server 2008.");

if (osVersion.Major == 6)
{
    switch (osVersion.Minor)
    {
        case 0:
            //INetFwRule is available. Windows Server 2008 or Windows Vista
            break;
        case 1:
            //INetFwRule2 is available. Windows 7 or Windows Server 2008 R2 
            break;
        default:
            //INetFwRule3 is available. Windows 8.1, Windows Server 2012 R2, Windows 8 or Windows Server 2012.
            break;
        }
    }
    else
    {
        //INetFwRule3 is available. Windows Server 2016 Technical Preview or Windows 10.
    }

如果您不需要INetFwRule2INetFwRule3 的额外功能,您可以在您的应用程序上降级到INetFwRule

【讨论】:

    猜你喜欢
    • 2016-02-02
    • 1970-01-01
    • 2018-06-05
    • 2018-06-20
    • 2018-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多