Как установить и зарегистрировать COM-сервер для Excel, написанный на VB.NET, в списке серверов автоматизации?

Версии

Excel 2007, Windows Vista, VB.NET, Visual Studio 2008 с.NET 3.5 sp2, установочный пакет MSI.

Что я пытаюсь сделать

У меня есть Excel UDF, который написан на VB.NET. Он отображается как COM-сервер, потому что вы не можете напрямую создавать пользовательские функции Excel на языках.NET. Установка - настоящая боль, потому что ни одна из настроек установки, кажется, не делает это правильно; Ни один из них не дает вам инсталляционного пакета, который помещает COM-сервер на клиентский компьютер с зарегистрированным сервером, зарегистрированной библиотекой типов и компонентом, видимым в списке серверов автоматизации Excel 2007.

Что я пробовал

Вот параметры установки для библиотек типов, с их дефектами, очевидными во время компиляции и во время установки:

vsdrfComSelfReg

  • нет предупреждения во время компиляции проекта установки
  • Модуль xxx.tlb не удалось зарегистрировать. HRESULT -2147024703
  • ProgID и GUID компонента задаются в реестре, но компонент не отображается в списке серверов автоматизации.

vsdrfDoNotregister

  • нет предупреждения во время компиляции
  • установка работает но конечно TLB не зарегистрирован

vsdrfCOM

  • Предупреждение во время компиляции: ПРЕДУПРЕЖДЕНИЕ: невозможно создать регистрационную информацию для файла с именем "xxx.tlb"
  • библиотека типов не зарегистрирована во время установки

Правильная настройка должна быть vsdrfCOM, как описано здесь:

В. Может кто-нибудь сказать, что означает vsdrfCOM в проекте установки Visual Studio? Это доступно, когда я проверяю свойство "Регистрация" среди свойств добавленных файлов в проекте установки.

О. Это означает, что Visual Studio извлечет данные регистрации COM во время сборки и поместит их в файл MSI (в основном это таблица реестра файла MSI, но также и таблица классов). Поэтому, когда вы устанавливаете его, ваш код не нуждается в самостоятельной регистрации, поскольку файл копируется на диск и создаются записи реестра. Это также создаст регистрацию библиотеки типов, добавив запись в таблицу TypeLib MSI.

Многие из трудностей, кажется, специфичны для Vista. В частности, использование утилиты REGCAP для создания файла.REG из файла.TLB не работает в Vista. Если бы не это, возможно, этот совет был бы полезен. Вместо этого он создает пустые файлы.REG, когда он вообще работает.

Я испробовал все советы в этом посте Stackru. Этот пост имеет довольно хорошее описание технической проблемы:

Записи в диалоговом окне "Ссылки" поступают из раздела реестра HKCR\TypeLib, а не из HKCR\CLSID. Если ваша сборка не отображается в диалоговом окне "Ссылки", но скомпилированные DLL могут по-прежнему использовать вашу COM-сборку, это означает, что классы и интерфейсы были правильно зарегистрированы для вашей сборки, но сама библиотека типов не была.

Вопрос

У кого-нибудь есть идея, как заставить установку зарегистрировать компонент и библиотеку типов? У меня нет доступа к машине с Windows XP.


Разработка, почему это отстой

.TLB не обязателен для вызова скомпилированного кода. Я не пробовал развертывать надстройку Excel Automation, как вы делаете, но я предполагаю, что пользовательские функции должны загружаться и работать очень хорошо.

Это не совсем так в Excel.

  • Пользователь открывает рабочий лист и пытается сослаться на UDF. Не найден, потому что DLL не загружена. ПОТЕРПЕТЬ ПОРАЖЕНИЕ
  • Пользователь переходит в раздел Домашняя страница | Параметры Excel | Надстройки | Надстройки Excel +Go, и COM-сервер не отображается в диалоговом окне "Надстройки". ПОТЕРПЕТЬ ПОРАЖЕНИЕ
  • Затем пользователь нажимает серверы автоматизации, чтобы получить список доступных серверов автоматизации. DLL там нет. ПОТЕРПЕТЬ ПОРАЖЕНИЕ
  • Пользователь возвращается в диалоговое окно "Надстройки" и выбирает "Обзор", переходит в каталог установки и выбирает либо DLL ("XXX не является допустимой надстройкой"), либо библиотеку типов ("Выбранный вами файл не содержит новый сервер автоматизации, или у вас недостаточно прав..."). ПОТЕРПЕТЬ ПОРАЖЕНИЕ

Насколько я могу судить, пользователь должен запустить regasm.exe из командной строки, чтобы сделать сервер Excel UDF/COM доступным. Как вы относитесь к тому, чтобы заставить людей запускать regasm из командной строки для установки надстройки в Excel?


Редактировать 2009-10-04

Комментарии и указания Майка ниже потрясающие. Ключевой вещью, которую я не знал, было то, что в программе установки есть встроенный редактор реестра для добавления ключей реестра. Да, и что установочная функция Microsoft не вызывала функцию установки с атрибутом ComRegisterFunctionAttribute. У меня уже были инструкции по написанию функций установщика из источников, которые он цитировал.

2 ответа

Решение

Я сделал снимок при развертывании надстройки автоматизации в выходные дни. Оказывается, это чрезвычайно сложно (не удивительно для вас!), И я не смог найти абсолютно никаких источников в интернете о том, как это сделать правильно. Никто.

Есть источники, которые описывают, как использовать RegAsm, но ни как правильно использовать проект установки для регистрации надстройки автоматизации, которая немного отличается от вашей стандартной надстройки COM.

К счастью, мне удалось это решить. Вот что я узнал:

Если вы прочитаете некоторые статьи о том, как создать и зарегистрировать надстройку C# для автоматизации, вы увидите, что вам нужно добавить раздел реестра с именем Programmable в HKEY\_CLASSES\_ROOT\CLSID\\{GUID}, где {GUID} GUID вашего COM-видимого класса.

Обычно это делается путем добавления пары методов, помеченных ComRegisterFunctionAttribute и ComUnregisterFunctionAttribute. Хорошим примером этого является статья Габхана Берри " Написание пользовательских функций рабочего листа Excel на C# ":

// C#:

[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type type) {
  Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type));
}

[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type type) {
  Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type), false);
}

private static string GetSubKeyName(Type type) {
  string s = @"CLSID\{" + type.GUID.ToString().ToUpper() + @"}\Programmable";
  return s;
}

В переводе на VB.NET это работает для:

'VB.NET:

<ComRegisterFunctionAttribute()> _
Public Shared Sub RegisterFunction(ByVal type As Type)
    Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type))
End Sub

<ComUnregisterFunctionAttribute()> _
Public Shared Sub UnregisterFunction(ByVal type As Type)
    Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type), false)
End Sub

Private Shared Function GetSubKeyName(ByVal type As Type) As String
    Dim s As String = ("CLSID\{" _
                + (type.GUID.ToString.ToUpper + "}\Programmable"))
    Return s
End Function

Метод отмечен ComRegisterFunctionAttribute автоматически вызывается RegAsm когда сборка для этого класса зарегистрирована. Метод отмечен ComUnregisterFunctionAttribute автоматически вызывается RegAsm когда сборка для этого класса не зарегистрирована через /u переключатель.

Проблема в том, что ComRegisterFunctionAttribute а также ComUnregisterFunctionAttribute полностью игнорируются при установке через проект установки Visual Studio.

Поначалу это кажется удивительным, потому что запускается проект установки Visual Studio RegAsm с использованием /regfile Переключитесь, чтобы сгенерировать файл.REG, содержащий все необходимые ключи реестра. Именно этот файл.REG затем используется, после чего на клиентском сайте запускается пакет.MSI.

Из сборки и развертывания сборки.NET COM Фила Уилсона:

Как Visual Studio работает с записями регистрации класса COM? Хорошо, если вы настроили Fusion Log Viewer (Fuslogvw.exe в.NET 2.0 SDK) для записи загрузки сборки, запустите ее после сборки вашей установки, и вы заметите, что Regasm.exe действительно запускается во время сборки вашей сборки. Настройка проекта. Тем не менее, он не выполняет никакой регистрации. Что происходит, так это то, что Visual Studio запускает Regasm с /regfile возможность создать файл.reg, содержащий записи реестра, необходимые для получения информации для шага 1, и этот файл.reg внутренне импортируется в проект установки. Поэтому, если вы хотите увидеть, какие записи регистрации классов Visual Studio создаст в настройке MSI, вы можете запустить Regasm самостоятельно с помощью команды /regfile вариант

После запуска RegAsm сам, используя /regfile Переключатель, однако, я заметил, что Programmable выключатель не был включен. Затем я включил ведение журнала в мои методы, отмеченные ComRegisterFunctionAttribute а также ComUnregisterFunctionAttribute и обнаружил, что они оба вызваны при запуске RegAsm без /regfile переключаться, но не вызываются при запуске с /regfile и не вызываются при запуске через пакет.MSI, созданный проектом установки Visual Studio.

Файлы справки для Regasm.exe подтверждают это (выделение добавлено):

Вы можете использовать /regfile возможность создать файл.reg, содержащий записи реестра, вместо внесения изменений непосредственно в реестр. Вы можете обновить реестр на компьютере, импортировав файл.reg с помощью редактора реестра (Regedit.exe). Обратите внимание, что файл.reg не содержит обновлений реестра, которые могут быть сделаны пользовательскими функциями реестра.

Решение, таким образом, состоит в том, чтобы добавить Programmable Ключ себя. Это можно сделать следующим образом:

  1. В проекте установки откройте редактор реестра. Создать новый ключ с именем CLSID под HKEY_CLASSES_ROOT щелкнув правой кнопкой мыши на HKEY_CLASSES_ROOT папку, затем выберите "Новый", а затем "Ключ".
  2. Под CLSID ключ, добавьте новый ключ с именем для вашего GUID, включая фигурные скобки.
  3. Под новым ключом GUID, который вы добавили, добавьте ключ с именем Programmable, Вам не нужно указывать какое-либо значение в этом ключе; тем не менее, нам нужно заставить его быть созданным. Поэтому щелкните правой кнопкой мыши на Programmable ключ и выберите "Окно свойств". Затем измените AlwaysCreate собственность на True,

После того, как вы это сделали, вам больше не нужны методы, помеченные с помощью ComRegisterFunctionAttribute и ComUnregisterFunctionAttribute, но я все равно оставляю их в тех случаях, когда вы выполняете вызов через RegAsm, а не через проект установки.

На данный момент вы готовы к развертыванию. Создайте свое решение, а затем щелкните правой кнопкой мыши по проекту установки и выберите "Построить". Затем можно использовать созданные файлы Setup.exe и MSI для развертывания на клиентском компьютере.

Однако следует учитывать и то, что при добавлении надстройки автоматизации через диалоговое окно надстроек Excel будет отображаться сообщение об ошибке, в котором говорится, что "Mscoree.dll не найден. Удалить надстройку?" или что-то очень похожее. Это сообщение об ошибке можно игнорировать, и ваша надстройка будет работать независимо от того, что вы ответите, но это может вызвать тревогу у клиента, устанавливающего вашу надстройку.

Эта ситуация и объяснение того, как ее решить, хорошо описаны в статье Эрика Картера о написании пользовательских функций для Excel в.NET.

Проблема в том, что значение по умолчанию для InprocServer32 ключ просто mscorree.dll, что достаточно для.NET, чтобы найти его, но заставляет Excel жаловаться. Решение состоит в том, чтобы убедиться, что значение по умолчанию для ключа InprocServer32 включает полный путь к системному каталогу. Например, в 32-битных окнах он должен читать C:\Windows\system32\mscoree.dll, Однако этот путь должен меняться в зависимости от системы, в которой он установлен. Так что этот путь не должен быть жестко закодирован.

Эрик Картер обрабатывает это, изменяя методы, отмеченные ComRegisterFunctionAttribute а также ComUnregisterFunctionAttribute быть следующим:

// C#: 

[ComRegisterFunctionAttribute]
public static void RegisterFunction(Type type)
{

  Registry.ClassesRoot.CreateSubKey(
    GetSubKeyName(type, "Programmable"));
  RegistryKey key = Registry.ClassesRoot.OpenSubKey(
    GetSubKeyName(type, "InprocServer32"), true);
  key.SetValue("",
    System.Environment.SystemDirectory + @"\mscoree.dll",
    RegistryValueKind.String);
}

[ComUnregisterFunctionAttribute]
public static void UnregisterFunction(Type type)
{

  Registry.ClassesRoot.DeleteSubKey(
    GetSubKeyName(type, "Programmable"), false);
}

private static string GetSubKeyName(Type type,
  string subKeyName)
{
  System.Text.StringBuilder s =
    new System.Text.StringBuilder();
  s.Append(@"CLSID\{");
  s.Append(type.GUID.ToString().ToUpper());
  s.Append(@"}\");
  s.Append(subKeyName);
  return s.ToString();
}  

В переводе на VB.NET это эквивалентно:

'VB.NET:

<ComRegisterFunctionAttribute()> _
Public Shared Sub RegisterFunction(ByVal type As Type)
    Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type, "Programmable"))
    Dim key As RegistryKey = Registry.ClassesRoot.OpenSubKey(GetSubKeyName(type, "InprocServer32"), true)
    key.SetValue("", (System.Environment.SystemDirectory + "\mscoree.dll"), RegistryValueKind.String)
End Sub

<ComUnregisterFunctionAttribute()> _
Public Shared Sub UnregisterFunction(ByVal type As Type)
    Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type, "Programmable"), false)
End Sub

Private Shared Function GetSubKeyName(ByVal type As Type, ByVal subKeyName As String) As String
    Dim s As System.Text.StringBuilder = New System.Text.StringBuilder
    s.Append ("CLSID\{")
    s.Append(type.GUID.ToString.ToUpper)
    s.Append ("}\")
    s.Append (subKeyName)
    Return s.ToString
End Function

Это работает, но имеет ту же самую проблему, когда сборка правильно регистрируется при запуске RegAsm на локальном компьютере, но не удается при попытке использовать это в проекте установки Visual Studio.

Решение, опять же, заключается в добавлении наших собственных ключей реестра. На этот раз, однако, нам придется создать значение по умолчанию, которое использует [SystemFolder] свойство, которое эквивалентно System.Environment.SystemDirectory вызов, используемый в коде Эрика Картера, выше.

Для этого добавьте ключ с именем InprocServer32 под вашим CLSID\\{GUID} ключ, который мы создали ранее. Затем щелкните правой кнопкой мыши на новом InprocServer32 ключ и выберите "New", а затем "String Value". Результатом будет новое значение с именем New Value #1, но вы будете в режиме редактирования, что позволит вам переименовать его. Здесь вы хотите удалить все символы и нажать Enter. Удаляя все символы из имени, вы создаете значение по умолчанию, а значок значения реестра будет автоматически переименован в "(По умолчанию)". Затем щелкните правой кнопкой мыши на значке по умолчанию и выберите "Окно свойств". В окне свойств установите для свойства Value значение "[SystemFolder]mscoree.dll" (без кавычек).

Затем вы можете щелкнуть правой кнопкой мыши по вашему проекту установки и выбрать "Build", после чего вы готовы к развертыванию.

Есть только одна последняя вещь, о которой нужно беспокоиться. Если вы устанавливаете в Excel 2007 или выше, вышесказанное будет работать на 100%. Если вы устанавливаете в Excel 2003 или ниже, вам нужно будет включить следующее:

ИСПРАВЛЕНИЕ: надстройки, смарт-документы или смарт-теги, созданные с помощью Microsoft Visual Studio 2005, не запускаются в Office

Подробное объяснение того, как развернуть его, дано Диво здесь.

Если вы не примените это исправление, все будет зарегистрировано правильно, и вы даже сможете успешно добавить свою надстройку автоматизации - все выглядит нормально - но ваши функции листа не будут работать, и вы все равно получите #NAME? ошибки в результате. (Но, опять же, вам не нужно это для Excel 2007 и выше.)

Итак, в конце концов, TLB не имеет значения. Во всех моих тестах я использовал RegAsm без ключа /TLB и не включал TLB при регистрации через проект установки. Поэтому у меня не было проблем с этим в Vista, которая имеет проблемы при попытке добавить файл TLB в проект установки.

Надеюсь, это поможет, Хью, и, надеюсь, кому-нибудь еще, кто может наткнуться на эту тему в будущем...

Майк

Поиск ответа именно на этот вопрос неоднократно приводил меня сюда, несмотря на то, что оригинальному сообщению уже более 13 лет (по состоянию на август 2023 года).

Множество очень полезной информации из этого и других источников позволило мне разработать надстройку UDF с более удобным для конечного пользователя установщиком, который устраняет необходимость запускать Regasm вручную.

Итак, обновлено для Windows 10 и Visual Studio 2022, https://github.com/Serialcomms/Excel-Automation-AddIn-with-Installer .

Надеюсь, это поможет всем, кто, как и я, обнаружил, что развертывание и установка надстроек автоматизации Excel оказались неожиданно трудными.

СК

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