Использование .NET компонентов при помощи COM
От: Алексей Дубовцев Россия  
Дата: 27.04.02 19:37
Оценка: 160 (10)
Статья:
Использование .NET компонентов при помощи COM
Автор(ы): Алексей Дубовцев
Дата: 19.11.2001


Авторы:
Алексей Дубовцев

Аннотация:
В этой статье мы с вами обсудим вопросы взаимодействия с компонентами .NET при помощи COM. Прочитав и осмыслив то, что здесь изложено, вы сможете с легкостью использовать компоненты .NET в ваших приложениях при помощи COM. А значит, сможете из любого вашего старого приложения, использующего WinApi, использовать практически все современные средства .NET.
Еще
От: Sport Россия  
Дата: 28.04.02 19:42
Оценка:
К п.3:
Или файл сборки должен лежать в путях прописанных.
Добавление
От: Sport Россия  
Дата: 28.04.02 19:37
Оценка:
3 ошибки:

1. Писать нужно так:
[assembly:AssemblyKeyFileAttribute("../Orbit.snk")];
[assembly:AssemblyVersionAttribute("1.0.0.1")];

2. Генерация ключа так:
sn.exe -k Имя_вашего_файла_с_ключом.snk

3. Чтобы скрипт сработал надо зарегистрировать сборку как общую:
gacutil /i TestComponent.dll
Re: Использование .NET компонентов при помощи COM
От: Rodion Online Россия  
Дата: 31.10.03 13:53
Оценка:
Может кто занет почему у меня не проходит по этому условию. Вроде все правильно делаю.

//Создаём объект
//и сразу же получаем интересующий нас интерфейс ITestComponent
if (FAILED(CoCreateInstance(clsidOrbit,0,CLSCTX_ALL,__uuidof(ITestComponent),(void**)&pIOrbit)))
return;

Пути я прописывал, например, во так:
#import "C:\\3\\net\\My\\bin\\Release\\My.tlb" raw_interfaces_only Это нормально?

В командной строке я могу писать так: C:\5\sn.exe -k my.snk ?
Re[2]: Использование .NET компонентов при помощи COM
От: MACTEP Россия  
Дата: 19.05.04 17:08
Оценка:
Здравствуйте, Rodion Online, Вы писали:

RO>Может кто занет почему у меня не проходит по этому условию. Вроде все правильно делаю.


RO> if (FAILED(CoCreateInstance(clsidOrbit,0,CLSCTX_ALL,__uuidof(ITestComponent),(void**)&pIOrbit)))

RO> return;

у меня тоже так не работает — говорит, класс незарегистрирован

если положить Some.dll в тот каталог, где и клиент, то работает
PS пробовал делать и так gacutil /i Some.dll
всё равно не работает........
Правило наименьшего удивления: Программа должна работать так, чтобы это вызывало наименьшее удивление у пользователя.
Построй свой мини-горд на http://rumactep.myminicity.com/
Re[3]: Использование .NET компонентов при помощи COM
От: MACTEP Россия  
Дата: 19.05.04 17:15
Оценка:
Здравствуйте, MACTEP, Вы писали:

MAC>если положить Some.dll в тот каталог, где и клиент, то работает

MAC>PS пробовал делать и так gacutil /i Some.dll
MAC>всё равно не работает........
PPS кстати, сборка видна в GacCash [\WINDOWS\assembly]
Правило наименьшего удивления: Программа должна работать так, чтобы это вызывало наименьшее удивление у пользователя.
Построй свой мини-горд на http://rumactep.myminicity.com/
Re[3]: Использование .NET компонентов при помощи COM
От: kuj  
Дата: 19.05.04 19:46
Оценка:
Здравствуйте, MACTEP, Вы писали:

MAC>если положить Some.dll в тот каталог, где и клиент, то работает

MAC>PS пробовал делать и так gacutil /i Some.dll
А regasm Some.dll?
... << RSDN@Home 1.1.3 stable >>
Re[4]: Использование .NET компонентов при помощи COM
От: MACTEP Россия  
Дата: 20.05.04 05:16
Оценка: +1
Здравствуйте, kuj, Вы писали:

kuj>А regasm Some.dll?


пробовал
но сейчас всё исправилось
использовалась какая-то старая версия Some.tlb
Правило наименьшего удивления: Программа должна работать так, чтобы это вызывало наименьшее удивление у пользователя.
Построй свой мини-горд на http://rumactep.myminicity.com/
Re: Добавление
От: pavel_k  
Дата: 25.03.05 14:31
Оценка:
Здравствуйте, Sport, Вы писали:

S>3 ошибки:


S>1. Писать нужно так:

S>[assembly:AssemblyKeyFileAttribute("../Orbit.snk")];
S>[assembly:AssemblyVersionAttribute("1.0.0.1")];

S>2. Генерация ключа так:

S>sn.exe -k Имя_вашего_файла_с_ключом.snk

S>3. Чтобы скрипт сработал надо зарегистрировать сборку как общую:

S>gacutil /i TestComponent.dll

всё круто. Только как запустить всё это out of proc ?
при помощи dllhost имею ввиду. У меня не пашет.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Re: Использование .NET компонентов при помощи COM
От: Hottabych1  
Дата: 16.07.05 20:04
Оценка:
Здравствуйте!
Кто-нибудь пробовал добавить в интерфейс свойство с типом string? У меня почему-то тогда не получается из клиента записать строку. То есть она вроде как записывается, но при попытке чтения значения свойства возвращается пустая строка
Re[2]: Использование .NET компонентов при помощи COM
От: TK Лес кывт.рф
Дата: 18.07.05 07:50
Оценка:
Hello, "Hottabych1"
> Кто-нибудь пробовал добавить в интерфейс свойство с типом string? У меня
> почему-то тогда не получается из клиента записать строку. То есть она
> вроде как записывается, но при попытке чтения значения свойства
> возвращается пустая строка

Обычно работает. Надо смотреть финальный код
Posted via RSDN NNTP Server 2.0 beta
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[3]: Использование .NET компонентов при помощи COM
От: Hottabych1  
Дата: 18.07.05 15:36
Оценка:
Здравствуйте, TK, Вы писали:

TK>Hello, "Hottabych1"

>> Кто-нибудь пробовал добавить в интерфейс свойство с типом string? У меня
>> почему-то тогда не получается из клиента записать строку. То есть она
>> вроде как записывается, но при попытке чтения значения свойства
>> возвращается пустая строка

TK>Обычно работает. Надо смотреть финальный код



Вот код сборки (файл Some.cs). Собственно, взят практически полностью из статьи. Только изменил свойство About.

using System;
using System.Reflection;
using System.Text;

//Данный атрибут определяет файл, в котором находится 
//пара личных криптографических ключей, 
//однозначно идентифицирующих сборку
//[assembly:AssemblyKeyFile("../Orbit.snk")]
//[assembly:AssemblyVersion("1.0.0.0")]

namespace TestComponentLib
{
    //Этот интерфейс нужен для взаимодействия
    //с COM 
    public interface ITestComponent
    {
        int Mul(int First, int Second);
        int Square { get; set; }
        String About { get; set; }
    }

    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    public class TestComponent : ITestComponent
    {
        private int m_iSquare;
        private string m_strAbout;

        public TestComponent()
        {
            m_iSquare = 0; 
        }

        // Implementing interface ITestComponent
        public int Mul(int First, int Second)
        {
            return First * Second;
        }

        public int Square
        {
            get
            {
                return m_iSquare;
            }
            set
            {
                m_iSquare = value * value;
            }
        }

        public string About
        {
            get
            {
                return "This component is written in C#." + m_strAbout;
            }
            set
            {
                m_strAbout = value;
            }
        }
    }
}



А вот код клиента на MFC:

// TestMFCNet.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "TestMFCNet.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#import "e:\Мои документы\Visual Studio Projects\TestComponent\bin\Debug\TestComponent.tlb" raw_interfaces_only

using namespace TestComponent;

// The one and only application object

CWinApp theApp;

using namespace std;

void DoWork()
{
    //Инициализируем СOM как STA, хотя значения это, в общем-то, не имеет,
    //так как наш компонент автоматически поддерживает обе потоковые модели.

    if (FAILED(CoInitialize(NULL)))
      return;

    _bstr_t bstrCLSID;
    CLSID   clsidOrbit;

    ITestComponent* pIOrbit;

    HRESULT hr;

    //Это ProgID нашего компонента.
    //Как видите, он складывается из области видимости и имени
    //самого компонента, записанных через точку.
    bstrCLSID = "TestComponentLib.TestComponent";

    //Получаем CLSID (Class ID) через ProgID
    if (FAILED(CLSIDFromProgID (bstrCLSID, &clsidOrbit)))
        return;

    //Создаём объект
    //и сразу же получаем интересующий нас интерфейс ITestComponent
    if (FAILED(CoCreateInstance(clsidOrbit, 0, CLSCTX_ALL, __uuidof(ITestComponent), (void**)&pIOrbit)))
        return;

    //BSTR  strAbout;
    LPWSTR strAbout;

    //Запрашиваем информацию о компоненте
    pIOrbit->put_About(L" HI!!!!!");
    pIOrbit->get_About(&strAbout);
    CW2CT str(strAbout);

    //Для вывода используем UNICODE-версию MessageBox
    long res = 0;
    pIOrbit->put_Square(232);
    pIOrbit->get_Square(&res);
    AfxMessageBox(str);

    CoUninitialize();
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;

    // initialize MFC and print and error on failure
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    {
        // TODO: change error code to suit your needs
        _tprintf(_T("Fatal Error: MFC initialization failed\n"));
        nRetCode = 1;
    }
    else
    {
        DoWork();
    }

    return nRetCode;
}
Re[4]: Использование .NET компонентов при помощи COM
От: TK Лес кывт.рф
Дата: 18.07.05 15:48
Оценка:
Hello, "Hottabych1"
>
> Вот код сборки (файл Some.cs). Собственно, взят практически полностью из
> статьи. Только изменил свойство About.

Не пробовал использовать нормальные BSTR? (для put_ особенно)
LPWSTR strAbout;

    //Запрашиваем информацию о компоненте
    pIOrbit->put_About(L" HI!!!!!");
    pIOrbit->get_About(&strAbout);
Posted via RSDN NNTP Server 2.0 beta
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[5]: Использование .NET компонентов при помощи COM
От: Hottabych1  
Дата: 18.07.05 17:06
Оценка:
Здравствуйте, TK, Вы писали:

TK>Hello, "Hottabych1"

>>
>> Вот код сборки (файл Some.cs). Собственно, взят практически полностью из
>> статьи. Только изменил свойство About.

TK>Не пробовал использовать нормальные BSTR? (для put_ особенно)

TK>
TK>LPWSTR strAbout;

TK>    //Запрашиваем информацию о компоненте
TK>    pIOrbit->put_About(L" HI!!!!!");
TK>    pIOrbit->get_About(&strAbout);
TK>


Вот это да! Сработало!!! Спасибо большое, уже мозги плавились ! А Вы не могли бы объяснить, почему так важно применять именно BSTR?
Re[6]: Использование .NET компонентов при помощи COM
От: TK Лес кывт.рф
Дата: 19.07.05 07:39
Оценка: 6 (1)
Hello, "Hottabych1"
>
> Вот это да! Сработало!!! Спасибо большое, уже мозги плавились !
> А Вы не могли бы объяснить, почему так важно применять именно BSTR?

BSTR это не обычная строка, а скажем так, "паскалевская". это значит, что по
смещению [-1] хранится длина этой строки. Если маршалинг не используется, то
обычно это себя никак не проявляет. Однако, если возникает необходимость
маршалинга, то маршаллер считает мусор из [-1] смещения и получится то, что
получится...
Posted via RSDN NNTP Server 2.0 beta
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Использование .NET компонентов при помощи COM
От: oxid  
Дата: 28.09.05 16:39
Оценка:
А кто подскажет как это добро отлаживать?
Трудно быть богом(с) A.C. и Б.С.
Re: Еще
От: tripolox Россия  
Дата: 14.09.06 08:15
Оценка:
Здравствуйте, Sport, Вы писали:

S>К п.3:

S>Или файл сборки должен лежать в путях прописанных.

Я так понимаю Вы имеете в виду пути, прописанные в переменной среды %PATH% ?
Re: Добавление
От: tripolox Россия  
Дата: 14.09.06 08:28
Оценка:
Здравствуйте, Sport, Вы писали:

S>3. Чтобы скрипт сработал надо зарегистрировать сборку как общую:

S>gacutil /i TestComponent.dll

Необязательно

У regasm есть ключик /codebase
AndrewVK (с) http://rsdn.ru/Forum/?mid=1341772

Re: Использование .NET компонентов при помощи COM
От: Аноним  
Дата: 05.05.07 11:43
Оценка:
Здравствуйте, Алексей Дубовцев, Вы писали:

Не пойму, почему не работает. Вот код, который я пытаюсь отладить.
Изменения по отношению к оригиналу состоят только в форматировании.
Кроме того я перенес файл Orbit.snk в папку C# проекта,
а C#dll перед запуском переношу в ту же папку, где находится C++ Some.exe.
C++ программа прекращает работу на строке, отмеченной **.
Что сие и как с ним бороться?
Спасибо!

using System;
using System.Reflection;

// Определение файла личных криптографических ключей, идентифицирующих сборку
[assembly:AssemblyKeyFile("Orbit.snk")]
[assembly:AssemblyVersion("1.0.0.0")]
namespace TestComponentLib
{ public interface ITestComponent // Этот интерфейс нужен для взаимодействия с COM
{ int Mul(int First, int Second);
int Square { get; set; }
String About { get; }
}
public class TestComponent: ITestComponent // Данный класс реализует интерфейс ITestComponent
{ public TestComponent() { m_iSquare = 0; }
public int Mul( int First, int Second) { return First * Second; }
private int m_iSquare;
public int Square { get { return m_iSquare; } set { m_iSquare = value * value; } }
public String About { get { return "This component wrote on C#"; } }
}
}

#include <windows.h>
#include <stdio.h>
#include <comdef.h>
#import "Some.tlb" raw_interfaces_only

using namespace Some;
void main()
{ if (FAILED(CoInitialize(NULL))) return;
_bstr_t bstrCLSID;
CLSID clsidOrbit;
ITestComponent* pIOrbit;
// HRESULT hr;
bstrCLSID = "Some.TestComponent";
** if (FAILED(CLSIDFromString(bstrCLSID,&clsidOrbit))) return; // Здесь происходит выскок из программы
if (FAILED(CoCreateInstance(clsidOrbit,0,CLSCTX_ALL,__uuidof(ITestComponent),(void**)&pIOrbit))) return;
BSTR strAbout;
pIOrbit->get_About(&strAbout);
MessageBoxW(0,strAbout,0,0);
long lResult;
pIOrbit->Mul(5,4,&lResult);
printf("Multiply 5 * 4 = %d\n",lResult);
pIOrbit->put_Square(5);
pIOrbit->get_Square(&lResult);
printf("Printf square of 5 = %d\n",lResult);
pIOrbit->Release();
CoUninitialize();
}
Re[2]: Использование .NET компонентов при помощи COM
От: Аноним  
Дата: 16.05.07 06:50
Оценка:
Все получилось.
Оказывается надо прочесть инструкцию — вот блин, никогда бы не подумал.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.