Ложноотрицательные результаты Regasm и Com Interop
-
22-07-2019 - |
Вопрос
Я пытаюсь открыть доступ к нашей библиотеке через COM, но, похоже, я больше борюсь с инструментами, чем с реальной проблемой.Независимо от того, как я пишу свой класс, представленный COM, я получаю предупреждение:«XXX.dll не содержит типов, которые можно зарегистрировать для COM-взаимодействия» (в свойствах проекта проект помечен как «Зарегистрировать для COM-взаимодействия»).Даже простой класс ниже (как единственный класс в сборке, который подписан и помечен ComVisible(false)) предупреждение все равно сохраняется:
[Guid("77699130-7D58-4d29-BE18-385871B000D1")]
[ComVisible(true)]
public interface IExample
{
string GetText();
void SetText(string text);
}
[Guid("F91E5EE1-D220-43b5-90D1-A48E81C478B7")]
[ComVisible(true)]
public class Example : IExample
{
private string m_text = "default text";
public string GetText()
{
return m_text;
}
public void SetText(string text)
{
m_text = text;
}
}
Я попытался запустить regasm из командной строки, в выводе которой радостно указано «Типы зарегистрированы успешно».Однако при работе с ключом /verbose никакая дополнительная информация не отображается (кажется, я помню, что там указано имя или, возможно, просто количество зарегистрированных типов).Также попробовал запустить regasm с переключателем /regfile, чтобы сгенерировать regfile, который генерирует это:
[HKEY_CLASSES_ROOT\ComExample.Example]
@="ComExample.Example"
[HKEY_CLASSES_ROOT\ComExample.Example\CLSID]
@="{F91E5EE1-D220-43B5-90D1-A48E81C478B7}"
[HKEY_CLASSES_ROOT\CLSID\{F91E5EE1-D220-43B5-90D1-A48E81C478B7}]
@="ComExample.Example"
[HKEY_CLASSES_ROOT\CLSID\{F91E5EE1-D220-43B5-90D1-A48E81C478B7}\InprocServer32]
@="mscoree.dll"
"ThreadingModel"="Both"
"Class"="ComExample.Example"
"Assembly"="COMInteropTesting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8568e57f6b170d6c"
"RuntimeVersion"="v2.0.50727"
[HKEY_CLASSES_ROOT\CLSID\{F91E5EE1-D220-43B5-90D1-A48E81C478B7}\InprocServer32\1.0.0.0]
"Class"="ComExample.Example"
"Assembly"="COMInteropTesting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8568e57f6b170d6c"
"RuntimeVersion"="v2.0.50727"
[HKEY_CLASSES_ROOT\CLSID\{F91E5EE1-D220-43B5-90D1-A48E81C478B7}\ProgId]
@="ComExample.Example"
[HKEY_CLASSES_ROOT\CLSID\{F91E5EE1-D220-43B5-90D1-A48E81C478B7}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]
Я ни в коем случае не волшебник COM, но мне кажется, что регистрация действительна.Однако при запуске regasm сборки в реестре ничего не появляется.
Итак, мой вопрос: не упускаю ли я что-то в своем простом примере, чтобы регистрация работала, вижу ли я ложные показания, действительно ли регистрация правильна, и как мне лучше определить, действительно ли регистрация COM работает?
РЕДАКТИРОВАТЬ:Используя изменения, предложенные Кевом, я не смог избежать предупреждений от VS2008, но на самом деле я мог зарегистрировать что-то в реестре напрямую, используя regasm (в реестре ничего не было только из-за интеграции VS2008).
Затем я попытался удалить простой класс, чтобы получилась пустая сборка.Запуск regasm по этому поводу не выдал никаких предупреждений, только «Типы зарегистрированы успешно».Я вижу предупреждения типа «RegAsm:предупреждение RA0000:Никакие типы не были зарегистрированы» при запуске RegAsm на некоторых других моих сборках, которые могут быть неправильно представлены COM.Что здесь происходит, могу ли я доверять чему-либо, кроме реестра, и как насчет предупреждений о включении/выключении от регазма?
Решение
Я создал проект библиотеки классов на основе вашего кода следующим образом:
На странице свойств проекта выберите вкладку Подписание.Установите флажок «Подписать сборку» и выберите <New...>
из раскрывающегося списка «Выберите файл ключа строгого имени:».
Затем я добавил следующий класс (Example.cs)
:
[Guid("77699130-7D58-4d29-BE18-385871B000D1")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[ComVisible(true)]
public interface IExample
{
[DispId(1)]
string GetText();
[DispId(2)]
void SetText(string text);
}
[Guid("F91E5EE1-D220-43b5-90D1-A48E81C478B7")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Example : IExample
{
private string m_text = "default text";
[ComVisible(true)]
public string GetText()
{
return m_text;
}
[ComVisible(true)]
public void SetText(string text)
{
m_text = text;
}
}
Затем я собрал проект, а затем перешел в командную строку, где из сборки была выведена DLL.
Зарегистрироваться:
regasm.exe COMInteropTesting.dll /register /codebase /tlb
Если ваш компонент должен быть доступен нескольким приложениям:
gacutil.exe -i COMInteropTesting.dll
Все это отлично работало в 32-разрядной версии Windows 2003, 32-разрядной версии Windows 2008 и 64-разрядной версии Windows 7.
Однако есть одна проблема: если вы тестируете компонент, скажем, с помощью CScript в 64-битной системе, вам необходимо запустить правильный интерпретатор CScript.Если вы зарегистрировали сборку, используя 32bit RegAsm.exe
(в C:\Windows\Microsoft.NET\Framework\v2.0.50727
), то вам нужно запустить 32-битный интерпретатор CScript по адресу c:\Windows\SysWOW64
.