Regasm и Com Interop ложные негативы - PullRequest
1 голос
/ 30 октября 2009

Я пытаюсь выставить нашу библиотеку через 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 работает

EDIT: Используя изменения, предложенные Кевом, я не мог избежать предупреждений от VS2008, но на самом деле я мог получить что-то зарегистрированное в реестре, используя regasm напрямую (ничего в реестре только от интеграции VS2008).

Затем я попытался удалить простой класс, чтобы у меня была пустая сборка. Запуск regasm по этому поводу не сообщал о каких-либо предупреждениях, только «Типы зарегистрированы успешно». Я вижу предупреждения, такие как «RegAsm: предупреждение RA0000: типы не были зарегистрированы» при запуске RegAsm на некоторых других моих сборках, которые могут быть неправильно выставлены COM. Что здесь происходит, могу ли я доверять чему-либо, кроме реестра, и как насчет предупреждений о включении / выключении от regasm?

1 Ответ

2 голосов
/ 30 октября 2009

Я создал проект библиотеки классов на основе вашего кода следующим образом:

На странице свойств проекта выберите вкладку Подписи. Установите флажок «Подписать сборку» и выберите <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. Если вы зарегистрировали сборку с использованием 32-битного RegAsm.exe (на C:\Windows\Microsoft.NET\Framework\v2.0.50727), вам нужно запустить 32-битный интерпретатор CScript на c:\Windows\SysWOW64.

...