Как запустить скомпилированный AnyCPU COM-сервер

Я использую пример Microsoft для COM-сервера: Вне процесса C# COM-сервер (CSExeCOMServer)

Простой консольный COM-клиент должен просто запустить сервер и использовать его методы, свойства и события.

    static void Main(string[] args)
    {            
        Type type = Type.GetTypeFromCLSID(new Guid(SimpleObject.ClassId));

        if (type == null)
        {
            throw new Exception("ClientObject component is not registered");
        }

        ISimpleObject comObject = (ISimpleObject)Activator.CreateInstance(type);

        string what = comObject.HelloWorld();

        float fvalue = (float) 2.22;
        comObject.FloatProperty = fvalue;
        fvalue = (float)3.33;
        fvalue = comObject.FloatProperty;
    }

Это на самом деле работает напрямую. Сервер перешел на 32-битную версию из-за настроенной цели платформы x86. Но у меня есть 64-битная ОС, и теперь я хотел, чтобы она работала в 64-битной версии. Регистрация выполняется в событии пост-сборки сервера. Поэтому я изменил регистрацию (используя Framework64 regasm.exe), чтобы сервер также был зарегистрирован в 64-битной версии. Затем я изменил цель платформы на AnyCPU. Если я сейчас запускаю клиент, он висит в строке

    ISimpleObject comObject = (ISimpleObject)Activator.CreateInstance(type);

Но я могу видеть в диспетчере задач, что сервер был правильно запущен в 64 битах. Примерно через 1 мин я получаю следующее исключение:

Получение фабрики классов COM для компонента с CLSID {DB9935C1-19C5-4ED2-ADD2-9A57E19F53A3} не удалось из-за следующей ошибки: 80080005 Ошибка выполнения сервера (исключение из HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).

на System.RuntimeTypeHandle.CreateInstance(типа RuntimeType, Boolean, Boolean publicOnly NOCHECK, Boolean& canBeCached, RuntimeMethodHandleInternal& CTOR, Boolean& bNeedSecurityCheck) в System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, булевой skipCheckThis, булевой fillCache, StackCrawlMark& ​​stackMark) в System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& ​​stackMark)
в System.Activator.CreateInstance(тип Type, логический nonPublic) в System.Activator.CreateInstance(тип Type) в ConsoleClient.Program.Main(String[] args) в C:\Source\User\MaLe\Tests\CSExeCOMServer\C#\ConsoleClient\Program.cs: строка 17 в System.AppDomain._nExecuteAssembly(сборка RuntimeAssembly, аргументы String []) в System.AppDomain.ExecuteAssembly(файл String assemblyFile, доказательство assemblySecurity, String[]) в Microsoft.VisualStudio.HostingProccess.Hec..RunUsersAssembly()
в System.Threading.ThreadHelper.ThreadStart_Context(состояние объекта)
в System.Threading.ExecutionContext.RunInternal(ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, Boolean preserveSyncCtx) в System.Threading.ExecutionContext.Run(обратный вызов ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта, Boolean Prext. (ExecutionContext executeContext, обратный вызов ContextCallback, состояние объекта) в System.Threading.ThreadHelper.ThreadStart()

Если я запускаю exe-сервер вручную и снова пытаюсь подключиться к нему через COM, я вижу в диспетчере задач, что Клиент запускает второй сервер, а не подключается к первому. Это действительно 64-битная версия, но возникает исключение, и после закрытия клиента второй сервер также закрывается. Если я заставлю Сервер быть 32-битным в AnyCPU с 32-битным флагом Prefere, то все будет нормально, но в 32-битном. Если я установлю целевую платформу на x64, то все будет работать нормально и на 64-битной. Так что он не работает только в конфигурации AnyCPU, если он запускается в 64-битной.

У кого-нибудь есть идеи, что я делаю не так? Мне действительно нужен COM-сервер для работы в конфигурации AnyCPU даже с 64-битной версией. Я на самом деле не хочу иметь отдельные 32-битные и 64-битные exe-файлы. Который работал также, когда я проверял это кстати.

Спасибо за помощь.

1 ответ

Решение

У кого-нибудь есть идеи, что я делаю не так? Мне действительно нужен COM-сервер для работы в конфигурации AnyCPU даже с 64-битной версией. Я на самом деле не хочу иметь отдельные 32-битные и 64-битные exe-файлы.

COM требует отдельной регистрации COM для 32-битных и 64-битных и двух разных внепроцессных COM-серверов; поэтому вам требуется 32-битный COM-файл, а также 64-битный. Вы не можете иметь один для обоих.

Вы увидите примеры этого везде, как:

  • битовая версия расширений оболочки для Windows Explorer. например, TortoiseSVN; TortoiseGit. Проводник Windows, работающий на 64-битной Windows, принимает только 64-битные расширения; аналогично для работы на 32-битной Windows

  • отдельные 32- и 64-битные версии Microsoft Office (который уже некоторое время является COM/Ole) с одинаковой разрядностью для надстроек COM

Единственный способ, которым вы можете обойти, скажем, желание 32-битного клиента подключиться к 64-битному серверу, - это если вы добавите соответствующие регистрации DCOM и запустите свой сервер на другом компьютере (под управлением 64-битной Windows) с подключением вашего клиента к нему по сети. Хотя это, вероятно, не особенно полезно.

Другие вопросы по тегам