Как установить и зарегистрировать 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
Ключ себя. Это можно сделать следующим образом:
- В проекте установки откройте редактор реестра. Создать новый ключ с именем
CLSID
подHKEY_CLASSES_ROOT
щелкнув правой кнопкой мыши наHKEY_CLASSES_ROOT
папку, затем выберите "Новый", а затем "Ключ". - Под
CLSID
ключ, добавьте новый ключ с именем для вашего GUID, включая фигурные скобки. - Под новым ключом 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 или ниже, вам нужно будет включить следующее:
Подробное объяснение того, как развернуть его, дано Диво здесь.
Если вы не примените это исправление, все будет зарегистрировано правильно, и вы даже сможете успешно добавить свою надстройку автоматизации - все выглядит нормально - но ваши функции листа не будут работать, и вы все равно получите #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 оказались неожиданно трудными.
СК