Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# COM无法启动进程外.Net服务器编译为AnyCPU_C#_.net_Windows_Com - Fatal编程技术网

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

C# COM无法启动进程外.Net服务器编译为AnyCPU,c#,.net,windows,com,C#,.net,Windows,Com,我正在尝试让COM启动进程外.NET COM服务器。如果服务器进程是用x64编译的,那么它可以工作,但是如果我使用AnyCPU(这是我想要的),那么它会挂起一段时间,最终以0x80005失败(CO_E_server_EXEC_FAILURE)。我怎样才能让它工作 我在64位计算机上运行:Windows7和VisualStudio2008SP1 我可以在任务管理器中看到它确实启动了我的服务器。所以我想问题在于COM和服务器之间的通信(类注册) 我的测试客户机应用程序是用C#编写的,但不管它是为x

我正在尝试让COM启动进程外.NET COM服务器。如果服务器进程是用x64编译的,那么它可以工作,但是如果我使用AnyCPU(这是我想要的),那么它会挂起一段时间,最终以0x80005失败(CO_E_server_EXEC_FAILURE)。我怎样才能让它工作

  • 我在64位计算机上运行:Windows7和VisualStudio2008SP1
  • 我可以在任务管理器中看到它确实启动了我的服务器。所以我想问题在于COM和服务器之间的通信(类注册)
  • 我的测试客户机应用程序是用C#编写的,但不管它是为x86还是x64编译的。这个问题也发生在32位C++中的一些东西。
  • 如果我使用x64重新构建服务器并运行它,然后作为AnyCPU重新构建,那么COM可以启动它。重新启动会使我回到原来的状态。也许COM事先不知道要使用什么比特率,而先前的执行会有所帮助
  • 我找到并尝试将CLSCTX_ACTIVATE_64位_服务器传递给CoCreateInstance(),但这会在前面触发一个故障:0x80040154(REGDB_E_CLASSNOTREG)。我的COM注册有问题吗?你可以在下面看到它非常简单。以64位运行时会发生注册,当客户端为64位时会发生问题,因此不应涉及Wow6432Node
另一个家伙有一个问题,但MSFT的答案令人困惑。他似乎建议它只能通过DCOM(见链接)或COM+工作。我怀疑这两种方法都会非常麻烦,而且比分发构建为x64和x86的.exe要糟糕得多

您可能想知道我为什么要实现IPersistFile。这是因为我真正的问题是让BIDMuniKe()从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程序集。它还将选择正确的注册表路径并执行其他一些操作

例如:

Assembly currentAssembly = Assembly.GetExecutingAssembly();
System.Runtime.InteropServices.RegistrationServices regAsm = new System.Runtime.InteropServices.RegistrationServices();
bool isRegistered = regAsm.RegisterAssembly(currentAssembly, System.Runtime.InteropServices.AssemblyRegistrationFlags.SetCodeBase);
另外,我认为,根据.NET com服务器,.NET客户端程序集有一些问题,但我找不到任何资源


希望,它会有帮助…

我想问题出在运行时。我创建了一个COM服务器,它使用C++库进行注册(注册完成得很好)。我在从.NET(CS)切换到任何CPU时遇到问题

架构:

  • C++库接口COM(在x64和x86平台上构建)
  • 网络库包装器(CS)(正确实例化所需的X64/x86 C++库)
  • .NET应用程序(CS)-COM客户端或COM服务器
将.NET应用程序注册为“AnyCPU”时,会发生一些不好的事情。一旦COM客户端通过DCOM调用COM服务器,服务器应用程序将启动,但客户端收到COM服务器无法启动的错误

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

  • x86在classes\wow6432节点中注册类
  • x64和AnyCPU在类中注册类(在x64 windows机器上,键完全相同;我打赌x86和AnyCPU在x86机器上注册相同的键)
现在,我做了更多的实验:x86/x64/AnyCPU COM客户端可以毫无问题地连接到任何x86/x64 COM服务器,但它无论如何都无法连接到AnyCPU COM服务器

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

  • 注册x86 COM服务器,用AnyCPU COM服务器替换可执行文件:COM客户端正在启动x86 COM服务器,但没有通信。。。它一次又一次地启动服务器
  • 注册x64 COM服务器,用AnyCPU COM服务器替换可执行文件:COM客户端正在启动x64 COM服务器,但没有通信。。。它一次又一次地启动服务器
  • 注册AnyCPU COM服务器,将可执行文件替换为x86 COM服务器:COM客户端能够成功启动并连接到x86 COM服务器
  • 注册AnyCPU COM服务器,用x64 COM服务器替换可执行文件:COM客户端能够成功启动并连接到x64 COM服务器
  • 注册x86 COM服务器,用x64 COM服务器替换可执行文件:COM客户端能够成功启动并连接到x64 COM服务器
  • 注册x64 COM服务器,用x86 COM服务器替换可执行文件:COM客户端能够成功启动并连接到x86 COM服务器
  • 沟通问题到底在哪里?这很奇怪。。。所提供的解决方案(CLSCTX\u激活\u 64位\u服务器、PreferredServerBitness或corflags)都没有帮助


    还有谁在这件事上取得了一些进展?我们应该联系微软吗?

    听起来像是AnyCPU世界中的某些东西默认使用x86,而且只需要一个流氓就可以搞定整个事情。我认为在激活调用中传递CLSCTX\u ACTIVATE\u 64位\u服务器将不起作用,除非您在注册调用中将其传递给RegisterTypeForComClient。我怀疑构建为x64并运行,然后为x86重建,之所以有效,是因为您注册了类对象,但没有注销它,因此注册会保留在全局类对象表中。我发现AnyCPU是一个难题,我只在100%.NET项目中使用它(即几乎从未使用过!)。感谢@Ciaran,也许这归结为COM不够聪明,无法智能地解释CLR.exe头中的AnyCPU标志。我尝试将CLSCTX_ACTIVATE_64位_服务器传递给RegisterTypeForComClient,但它抛出了E_INVALIDARG。我并不感到惊讶,因为当我调用时,我已经以64位运行了,函数可以很容易地确定这一点,那又怎样呢