草庐IT

c# - COM 无法启动编译为 AnyCPU 的进程外 .Net 服务器

coder 2023-11-10 原文

我试图让 COM 启动我的进程外 .NET COM 服务器。如果服务器进程是用 x64 编译的,它就可以工作,但如果我使用 AnyCPU(这是我想要的),那么它会挂起一段时间并最终失败并返回 0x80080005 (CO_E_SERVER_EXEC_FAILURE)。我怎样才能让它发挥作用?

  • 我在 64 位计算机上运行:Windows 7 和 Visual Studio 2008 SP1。
  • 我可以在任务管理器中看到它确实启动了我的服务器。所以我猜问题出在 COM 和服务器(类注册)之间的通信上。
  • 我的测试客户端应用程序是用 C# 编写的,但它是为 x86 还是 x64 编译的并不重要。用 32 位 C++ 编写的内容也会出现此问题。
  • 如果我使用 x64 重建服务器并运行它,然后重建为 AnyCPU,那么 COM 可以启动它。重新启动将使我回到原来的情况。也许 COM 事先不知道将使用什么位数,而之前的执行会有所帮助。
  • 我找到了 Andy McMullen's blog post并尝试将 CLSCTX_ACTIVATE_64_BIT_SERVER 传递给 CoCreateInstance(),但这会更早地触发故障:0x80040154 (REGDB_E_CLASSNOTREG)。我在 COM 注册中做错了什么吗?你可以在下面看到它非常简单。 64位运行时出现注册,客户端是64位时出现问题,所以应该不涉及Wow6432Node。

另一个人有一个 similar problem ,但 MSFT 的回答令人困惑。他似乎在暗示它只能通过 DCOM(参见链接)或 COM+ 工作。我怀疑两者都需要大量工作,而且比分发构建为 x64 和 x86 的 .exe 差得多。

您可能想知道我为什么要实现 IPersistFile。这是因为我真正的问题是让 BindMoniker() 从 32 位 C++ 程序工作到我的 AnyCPU .Net 程序。我已将我的问题简化为此处介绍的更简单的示例。

这是客户端代码:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    [DllImport("ole32.dll", ExactSpelling = true, PreserveSig = false)]
    [return: MarshalAs(UnmanagedType.Interface)]
    static extern object CoCreateInstance(
       [In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
       [MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter,
       CLSCTX dwClsContext,
       [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);

    [Flags]
    enum CLSCTX : uint
    {
        CLSCTX_LOCAL_SERVER = 0x4,
        CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000,
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        IPersistFile pf = (IPersistFile)CoCreateInstance(
            new Guid("1984D314-FC8D-44bc-9146-8A13500666A6"),
            null,
            CLSCTX.CLSCTX_LOCAL_SERVER,
            new Guid("0000010b-0000-0000-C000-000000000046"));  // IPersistFile
        pf.Load("c:\\bozo", 0);
    }
}

这是服务器:

static class Program
{
    [STAThread]
    static void Main()
    {
        if (Environment.CommandLine.Contains("/reg")) {
            RegistryKey cls = Registry.LocalMachine.CreateSubKey(String.Format(
                "SOFTWARE\\Classes\\CLSID\\{0}", PersistFile.ClassID.ToString("B")));
            cls.SetValue("InprocHandler32", "Ole32.dll");
            RegistryKey ls32 = cls.CreateSubKey("LocalServer32");
            ls32.SetValue(null, '"' + Application.ExecutablePath + '"');
            ls32.SetValue("ServerExecutable", Application.ExecutablePath);
        }

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        RegistrationServices reg = new RegistrationServices();
        reg.RegisterTypeForComClients(
            typeof(PersistFile),
            RegistrationClassContext.LocalServer,
            RegistrationConnectionType.MultipleUse);

        Application.Run(new Form1());
    }
}

[ComVisible(true),
 Guid("1984D314-FC8D-44bc-9146-8A13500666A6"),
 ClassInterface(ClassInterfaceType.None)]
public class PersistFile : IPersistFile
{
    public static Guid ClassID
    {
        get
        {
            GuidAttribute a = (GuidAttribute)typeof(PersistFile).GetCustomAttributes(typeof(GuidAttribute), false)[0];
            return new Guid(a.Value);
        }
    }

    #region IPersistFile
    public void GetClassID(out Guid pClassID)
    {
        MessageBox.Show("GetClassID");
        pClassID = ClassID;
    }

    public int IsDirty()
    {
        MessageBox.Show("IsDirty");
        return 1;
    }

    public void Load(string pszFileName, int dwMode)
    {
        MessageBox.Show(String.Format("Load {0}", pszFileName));
    }

    public void Save(string pszFileName, bool fRemember)
    {
        MessageBox.Show("Save");
        throw new NotImplementedException();
    }

    public void SaveCompleted(string pszFileName)
    {
        MessageBox.Show("SaveCompleted");
        throw new NotImplementedException();
    }

    public void GetCurFile(out string ppszFileName)
    {
        MessageBox.Show("GetCurFile");
        throw new NotImplementedException();
    }
    #endregion
}

最佳答案

我想问题出在运行时。我已经创建了一个 COM 服务器,它使用 C++ 库进行注册(注册完美执行)。从 .NET (CS) 切换到 AnyCPU 时我遇到了问题。

架构:

  • 连接 COM 的 C++ 库(在 x64 和 x86 平台上构建)
  • .NET 库包装器 (CS)(正确实例化所需的 x64/x86 C++ 库)
  • .NET 应用程序 (CS) - COM 客户端或 COM 服务器

注册构建为“AnyCPU”的 .NET 应用程序时会发生丑陋的事情。一旦COM客户端通过DCOM调用COM服务器,服务器应用程序启动,但客户端收到无法启动COM服务器的错误。

我更进一步,使用 procmon 和其他工具分析了注册数据,我得出了同样的结论:

  • x86 在 CLASSES\Wow6432Node 中注册类
  • x64 和 AnyCPU 在 CLASSES 中注册类(在 x64 windows 机器上,完全相同的键;我打赌 x86 和 AnyCPU 会在 x86 机器上注册相同的键)

现在,我做了一些更多的实验:x86/x64/AnyCPU COM 客户端可以毫无问题地连接到任何 x86/x64 COM 服务器,但它无论如何都无法连接到 AnyCPU COM 服务器...

然后我执行了以下测试用例:

  1. 让 x86 COM 服务器注册,用 AnyCPU COM 服务器替换可执行文件:COM 客户端正在启动 x86 COM 服务器,但没有通信......它一遍又一遍地启动服务器......
  2. 让 x64 COM 服务器注册,用 AnyCPU COM 服务器替换可执行文件:COM 客户端正在启动 x64 COM 服务器,但没有通信......它一遍又一遍地启动服务器......
  3. 注册 AnyCPU COM 服务器,用 x86 COM 服务器替换可执行文件:COM 客户端能够成功启动并连接到 x86 COM 服务器。
  4. 注册 AnyCPU COM 服务器,将可执行文件替换为 x64 COM 服务器:COM 客户端能够成功启动并连接到 x64 COM 服务器。
  5. 注册 x86 COM 服务器,用 x64 COM 服务器替换可执行文件:COM 客户端能够成功启动并连接到 x64 COM 服务器。
  6. 注册 x64 COM 服务器,用 x86 COM 服务器替换可执行文件:COM 客户端能够成功启动并连接到 x86 COM 服务器。

通信问题到底出在哪里?这很奇怪……所提供的解决方案(CLSCTX_ACTIVATE_64_BIT_SERVER、PreferredServerBitness 或 corflags)都没有帮助。

其他人在这件事上取得了一些进展吗?我们应该联系 Microsoft 吗?

关于c# - COM 无法启动编译为 AnyCPU 的进程外 .Net 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9303814/

有关c# - COM 无法启动编译为 AnyCPU 的进程外 .Net 服务器的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  5. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  6. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  7. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  8. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  9. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  10. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

随机推荐