【问题标题】:Can't load .NET dll from ruby无法从 ruby​​ 加载 .NET dll
【发布时间】:2017-04-29 21:05:04
【问题描述】:

我已按照此问题中描述的步骤进行操作:

Can Ruby import a .NET dll?

所以,我有这个 c# 代码:

using System;
using System.IO;

namespace ComLib
{
    public class LogWriter
    {
        public void WriteLine(string line)
        {
            using (var log = new StreamWriter(File.OpenWrite(@"c:\log.file")))
            {
                log.WriteLine(line);
            }
        }
    }
}

在名为:RubyToCSharp的解决方案下

我在 VS 中检查了 Register for COM interop 并创建了以下 ruby​​ 代码:

require "win32ole"

lib = WIN32OLE.new('RubyToCSharp.ComLib.LogWriter')
lib.WriteLine('calling .net from ruby via COM, hooray!')

现在我尝试从 powerShell 运行此 ruby​​,但我不断收到此错误:

./exmpl.rb:4:in `initialize': unknown OLE server: `RubyToCSharp.ComLib.LogWriter' (WIN32OLERuntimeError)
    HRESULT error code:0x800401f3
      Invalid class string
        from ./exmpl.rb:4:in `new'
        from ./exmpl.rb:4:in `<main>'

对我在这里错过了什么有什么想法吗?

编辑

检查我的dll是否根据this SO question注册后, 看来我的 dll 确实已注册,但仍然发生同样的错误。

这里真是一头雾水……

【问题讨论】:

    标签: c# ruby dll com win32ole


    【解决方案1】:

    只有标记为 ComVisible 的类才会在注册期间导出到相应的键。拥有一个 Guid 属性而不是采用在每次编译期间都可以更改的默认值也是一个非常非常好的主意(我会说是强制性的)。您也可以拥有自己的 ProgId 属性,但通常默认的 Namespace.ClassName 就足够了(其中 Namespace 是您的类所在的命名空间,ClassName 是您的类的名称)。

    试试这个:

    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    
    namespace ComLib
    {
        [ComVisible(true)] // needs to be marked ComVisible 
        [Guid("ad4c28c9-4612-4ac3-8ca4-04a343f4f2b9")] // generate your own
        public class LogWriter
        {
            public void WriteLine(string line)
            {
                using (var log = new StreamWriter(File.OpenWrite(@"c:\log.file")))
                {
                    log.WriteLine(line);
                }
            }
        }
    }
    

    这就是我从 .NET 方面看到的。我没有任何尝试使用 Ruby 的经验。

    如果您的 Ruby 进程是 32 位,它也会有所帮助。 VIsual Studio 通常只在 64 位操作系统上向 32 位运行时系统注册类。

    对于 IDE 之外的独立注册,请使用以下内容:

    regasm.exe /tlb /codebase YourDll.dll
    

    确保将 regasm.exe 用于正确的 .NET 运行时和正确的 32/64 位版本。

    如果您的 DLL 正确注册到 COM,它应该可以通过 VBScript 调用。制作一个名为 Test.vbs 的简单 VBScript:

    Dim obj
    set obj = CreateObject("ComLib.LogWriter")
    MsgBox TypeName(obj)
    

    如果您在资源管理器中双击文件名,或者只是从命令行 shell 中键入 test.vbs,它将尝试在 c:\windows\system32\wscript.exe 中运行带有 wscript.exe 的 VBS 程序。

    它可能会在 64 位操作系统上失败,因为默认情况下 VS 只为 32 位子系统注册 COM 的 .NET 程序集。要尝试在 32 位子系统上运行它,请尝试:

    c:\windows\syswow64\wscript.exe test.vbs
    

    如果其中任何一个方法失败,则说明您的 DLL 未正确注册。

    【讨论】:

    • 感谢乔的回答,有几件事:1) [assembly: ComVisible( false )] 可能位于 AssemblyInfo.cs 文件中,并使所有类 com 可见(我已配置)我的项目。 2)我需要了解,如果它是通过 VS15 注册的,这是否意味着这个 dll 在整个操作系统中都可用?还是仅在 VS15 目录中“活着”?
    • 假设您以提升的管理员身份运行 VS,COM 所需的注册表项将遍布整个操作系统。测试它是否正常工作的一个快速技巧是编写一个 VBS 脚本:Dim objset obj = CreateObject("ComLIb.LogWriter")MsgBox TypeName(obj) 遇到问题...通过 c:\windows\system32\wscript.exe 运行它并通过 c:\ 运行它windows\SysWow64\wscript.exe 默认情况下,它应该与 SysWow64 目录中的那个一起成功。这会告诉你它是否注册正确。
    • 好的,再次感谢...仍然不知道这里出了什么问题。似乎我在做我应该做的一切。
    • 你仍然应该为你的班级声明一个 Guid。
    【解决方案2】:

    解决了它,似乎是一个相当奇怪的解决方案。

    改变了这个:

    lib = WIN32OLE.new('RubyToCSharp.ComLib.LogWriter')
    

    到这里:

    lib = WIN32OLE.new('ComLib.LogWriter')
    

    一切正常。

    【讨论】:

      猜你喜欢
      • 2010-10-21
      • 2022-11-22
      • 2016-09-17
      • 1970-01-01
      • 1970-01-01
      • 2012-04-12
      • 2019-08-21
      • 2023-01-20
      • 1970-01-01
      相关资源
      最近更新 更多