[VC++ 2010] jak zaczac tworzenie komponentow COM+

0

Witam,
poszukuję jakichś materiałów, książek, kursów, cokolwiek na temat COM+ w praktyce. Muszę ogarnąć tworzenie tych komponentów i MTS, a nic sensownego nie mogę znaleźć.

Z góry dzięki za pomoc :)

0
quetzalcoatl napisał(a)

podbije Ci temat: zacznij od tworzenia sensownych topikow. Tym razem jako ze masz dosc nieczęste pytanie, poprawilem go za Ciebie

Dzięki :)

W między czasie znalazłem taki tutorial (jeszcze przez niego się nie przekopałem, ale na wstępie wydaje się nawet ok) http://www.tenouk.com/visualcplusmfc/visualcplusmfc23.html (niestety po angielsku).

*EDIT: tu COM przy użyciu ATL: http:*www.tenouk.com/download/pdf/visualcplusmfc28.pdf Imho dość jasno i przystępnie wszystko wytłumaczone

Dopadłem też książkę COM+ Kompendium Programisty John Paul Mueller - niestety jest to stara książka, dodatkowo przeznaczona dla osób już znających COM i po przeczytaniu połowy nie zobaczyłem ani linijki przykładowego kodu - sama teoria. Jak dla mnie trochę bezużyteczna książka.

Mam nadzieję, że ten tutorial wyjaśni wystarczająco co i jak pisać w COM.
Jeszcze przydałoby się coś na temat Microsoft Transaction Server (MTS) i Microsoft Message Queue (MSMQ). Jak sam coś znajdę sensownego to dorzucę do tego postu/tematu.

0

Szukam szukam i nie mogę znaleźć.
Dlaczego w tym kodzie funkcja CoCreateInstance się "wiesza" - nigdy nie kończy działania?
Zaznaczam, że sam komponent jest napisany jako ATL COM exe service i ma tylko ten 1 interfejs (oprócz standardowych) z jedną funkcją nic nie robiącą na pokładzie.

CoInitialize(NULL);

Itest *p;
CLSID clsid;
HRESULT hr;

hr = CLSIDFromProgID(OLESTR("comexesvr.test"), &clsid);
if(FAILED(hr))
	AfxMessageBox(L"CLSIDFromProgID Err");
else
	AfxMessageBox(L"CLSIDFromProgID OK");

hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_Itest, (void**)&p);	
if(FAILED(hr))
{
	AfxMessageBox(L"Err");
}
else
{
	AfxMessageBox(L"OK");
	p->Release();
}

CoUninitialize();

//i przepraszam za post pod postem, ale chyba nikt tu nie zagląda, a nowy post może kogoś zachęci ;)

0

zaglada zaglada.. tylko nie mialem nic sensownego do podrzucenia..
zaznaczam, ze sie nie znam, ostatni raz dlubalem przy com/+/dcom za czasow vc6.. dinozaury biegaly wtedy mi pod oknem co wieczor, tak wiec i pamiec i 'wiedze' moge miec juz pomieszana

wieszanie sie mi przywodzi tylko na mysl nieprawidlowa inicjalizacje com (coinitialize - sprawdzales co zwraca? -> http://msdn.microsoft.com/en-us/library/ms678543(VS.85).aspx), jakis konflikt miedzy sta/mta, nie ten model runtime'u (acz chyba juz w kompilatorze nie masz opcji crt singlethreaded), oraz dziwne przypadki gdzie cos-jeszcze-nie-bylo-zainicjalizowane, np odpalilo sie w/przed dll/main()'em.. gdzies mignelo mi na google teraz, ze komus sie przytrafialo to przy niewlasciwym CLSCTX_LOCAL/REMOTE, ale u Ciebie wyglada na wlasciwe. Mowisz ze komponent nie ma wielkiego interfejsu i przychodzi jako exe, ale moze jednak musisz dorzucic CLSCTX_INPROC_HANDLER do flag. Pewnie juz tam byles, ale obadaj dokladnie opis wszystkich flag: http://msdn.microsoft.com/en-us/library/ms693716(VS.85).aspx
zerknij rowniez na CoInitializeEx, szczerze mowiac czesciej ja widywalem, wersja bez -Ex implikuje ze uruchomiles sie w STA, konflikt STA/MTA pasuje mi do zawieszki.. i moze po prostu musisz lepiej okreslic swoj threadingmodel, sprobuj uzyc wersji -Ex oraz MULTITHREADED z enum COINIT. Zwroc tez uwage, ze i CoInitialize i -Ex powinny byc wywolywane dla kazdego watku ktory chce uzywac COM, wiec jesli w kliencie masz jakiekolwiek watek poza glownym -- moze go pominales? ..ot takie luzne mysli, nie koniecznie sensowne ani trafione

0

CoInitialize(Ex) przechodzi elegancko(zwraca S_OK).
Co do kontekstu sprawdzałem już różne kombinacje i właśnie to co zaproponowałeś, w aplikacji testowej nie mam wątków. To jest prosty projekt mfc oparty na dialogu, a próbuję dostać się do tego interfejsu już w wywołaniu OnInitDialog.
Jeżeli dobrze pamiętam to serwer jest jako apartment - dawno nie używałem ang., więc jeszcze nie bardzo ogarnąłem te zawiłości za apartamentami itd.

Stworzę od nowa cały projekt komponentu i się pobawię ustawieniami odnośnie wątków, bo google też nie podpowiada nic innego jak ewentualne problemy z tym. No ale to już jutro, bo dzisiaj już tylko więcej błędów mogę narobić :)

0

apartament - mozna to tlumaczyc jako systemowy kontener/pudelko, w ktorym dany komponent bedzie przez system trzymany. Cos w koncu musi utrzymywac ten komponent, jakis proces. Bedzie to albo:

  • specjalna struktura stworzona wewnatrz Twojego proces ktory chce tego componentu uzywac, zostanie zaladowany DLL tego
  • inny proces chodzacy u Ciebie na kompie, ktory juz ma zaladowana DLL z tymże komponentem, i udziela go innym, byc moze zbiorczy proces-serwer utrzymujacy wiele uslug/komponentow a'la svchost.exe
  • dedykowany proces-serwer a'la Twoj component, zajmujacy sie tylko tym jednym compo, jest to .exe ktory po prostu chodzi w tle i sie tylko tym zajmuje
  • "zdalny" proces-serwer, czyli chodzacy na innym kompie, nie wazne czy wielo- czy jedno- komponentowy

Wywolania metod komponentow utrzymywanych przez w/w moga byc albo odpalane wprost, albo kolejkowane.
Ty jako program, w momencie odpalania obslugi COM poprzez CoInitialize/Ex tworzysz u siebie 'apartament'/kontener/pudelko ktore pozwala Ci ladowac komponenty in-proc, dostarcza komunikacji z komponentami out-of-proc (czyli utrzymywanych przez inne procesy, w tym zdalne) itede. Ow 'apartament'/pojemnik moze dzialac w trybie jednowatkowym (STA, single threaded apartament) albo MTA (multithreaded apartament). Kazdy komponent COM takze takie cos sobie definiuje na swoim starcie - one tez sa zobowiazane do CoInitialize/Ex. Wiec, tak jakby, Twoj program tez staje sie komponentem gadajacym do innych..

Tak czy owak, inicjalizacja jak oSTA oznacza, ze dany komponent ma w nosie wielowatkowosc, ze zaklada, ze NIKT nie ma prawa jednoczesnie wolac dwoch+ jego metod, etc. Dzieki temu, podsystem COM wie, ze ma wlaczyc mega-ochrone i kolejkowanie wiadomosci, tak, zeby w czasie obslugi żądania byly obslugiwane jednowakowo, nigdy podczas mielenia jednego wywolania metody interfejsu nie przyjdzie nagle nowe rownolegle wywoalnie. Dzieki temu, kod komponentu jest idiotycznie prosty, nie ma potrzeby zadnych lockow/semaforow/critsection itp. I jest wolniejszy niż..

MTA, ktore informuje system tworzacy Twoje pudelko, ze ma ono dzialac wielowatkowo. Kolejkowanie wiadomosci jest minimalizowane, wiele watkow pudelka ma prawo chodzic rownolegle i przetwarzac i podawac rownolegle Twojemu komponentowi wiadomosci. Kazda Twoja metoda interfejsu moze byc wywolana w kazdym momencie. Komponent sam musi sie zatroszczyc o wewnetrzna synchronizacje operacji. Kod trudniejszy, ale komponent bedzie hulal duzo szybciej, i bedzie mogl byc uzywany przez wiele programow na raz lepiej.

To tyle z pamieci.. wiecej musisz sam doczytac, chyba ze ktos inny opisze.

hm.. a moze wlasnie Twoj komponent jest STA i cos go w tle aktywnie uzywa i blokuje?
Kolejna rzecz do sprawdzenia:)

btw. STA/MTA spotkac tez mozesz np. w .Net. Np. static void main ma domyslnie [STAThread] ktore wlasnie oznacza jak budowac pudlo COM wokol aplikacji, taki coinitializie

0

Wielkie dzięki :)

Miałem trochę czasu i znalazłem błąd - znajdował się między krzesłem a klawiaturą :D
W samym serwerze, w procedurze WinMain zabrakło:

CoInitialize(NULL);
_AtlModule.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);

I nie tyle co CoGetClassObject/CoCreateInstance się wieszało tylko dość długo czekało na to, aż serwer się odpali i zarejestruje interfejsy, a że się wysypywał no to nie mogło działać.

0

na codeproject.com jest cała masa tutoriali, ale w zasadzie to chciałem zapytać: musisz ogarnąć tworzenie komponentów COM+ używająć C++ czy po prostu nauczyć się tworzenia komponentów COM+?

Jeśli to drugie, to zaoszczędź sobie czasu i wysiłku, olej klasyczny C++/ATL i użyj .NET framework - zacznij od klasy ServicedComponent.

0

Hmmm... z .NETem nie miałem praktycznie nic do czynienia, ale i tak kiedyś będę musiał go poznać.
Nie lubię tutoriali, jak już chcę się czegoś konkretnie nauczyć to lece i kupuję książkę, ale poszukam tutków tam :) thx

W sumie już ogarnąłem idee i nie jest to takie straszne (bo nazwy funkcji jakoś mnie przerażały :D). Muszę jeszcze spróbować stworzyć sobie jakiś komponent jako remote_server. Jak się już opanuje samo tworzenie, rejestrowanie, udostępnianie i dobieranie się do komponentów z klienckich app to chyba wystarczy(no jeszcze Connection Points) - bo cała reszta jest raczej zwyczajna - dostęp do baz danych(ADO), wątki, itd. itp. (tak mi się wydaje)

0

właściwie to się zgodzę - w C#/.Net byłoby Ci prościej, gdyż ładnych parę rzeczy platforma za Ciebie odwali gdy tylko napiszesz w jednym miejscu kodu "[ComVisible]".. ale --- w C++ zobaczysz to z niższego punktu widzenia i w C# potem bedziesz mial wakacje + status experta implicit --"

0

Napotkałem na problem i nie bardzo mogę znaleźć rozwiązanie (być może po prostu nie da się tego zrobić?).
Mianowicie: mam out-of-process server jako dll (chyba nie ma to nawet znaczenia - równie dobrze może być exe), i teraz czy można się do niego dobrać z innej maszyny, ale podając klientowi adres ip, port serwera i nazwę oraz hasło użytkownika?
Domyślam się, że jeżeli jest to możliwe to trzeba odpowiednio zarejestrować taki komponent na maszynie klienta - niestety nie znalazłem żadnych informacji na ten temat.

Przeszukując sieć natrafiłem też na info, że udostępnić komponent innym maszynom może tylko serwerowa wersja windowsa. Powiedzmy Win 7 Pro nie da rady?

0

szukaj pod haslem nie COM/COM+, a DCOM -- czyli Distributed COM, czyli COM poza pojedynczym localhostem.
np: http://www.codeguru.com/cpp/com-tech/activex/article.php/c5547

0

Wszystko ładnie pięknie dopóki nie docieram do zabezpieczeń. Nie ważne jak poustawiam, zawsze mam E_ACCESDENIED :/
Lokalnie chodzi ładnie, ale jak tylko zmienię ip serwera z lokalnego na publiczne to pozamiatane :/ Nigdy nie chciałem iść w kierunku administracji.

Uprawnienia Uruchamiania, aktywacji i dostępu ustawione dla wszystkich, CoInitializeSecurity na serwerze i kliencie na jak najniższym poziomie i nic :/
A może to po prostu Win 7 Pro nie pozwala na udostępnianie obiektów com na zewnątrz?

//Ehh gdzie o tym nie czytam, to piszą, że nic nie sprawia więcej problemów od tej ochrony dostępu

0

widzisz.. w ogóle administracja uprawnieniami pod zadnym os'em nie jest sliczna jezeli chodzi o dostep do czegos zdalnie na innym komputerze majacym samodzielny os..

niestety, w temacie zabezpieczen/udostepniania kompletnie nic nie pamietam, a i w ogole robilem niewiele. domyslam sie jedynie, ze problem nie lezy w D/COM/+, ale w zwyklym systemowym ACL'u i kontach uzytkownikow..
Probujesz sie jakos 'impersonifikowac'? Moze Twoj i tamten komputer bylyby w tej samej domenie, moglbys latwo nadac odpowiednie prawa uzytkownikowi 'domena/blah' (chocby sztucznemu, byle by z obu strona na te sama nazwe sie personifikowac) -- u Ciebie pewnie komputery sa calkowicie samodzielne? to maja oddzielne nazwy uzytkownikow i jezeli u obu probujesz uzyc np. 'jarek' to token z kompa A bedzie inny niz z kompa B i mimo tej samej nazwy sie nie dogadaja. ktorys komp musi wybrac nazwe w postaci "nazwakompakolegi/jarek" lub "ip-kolegi/jarek" a kolega z kolei "jarek" albo "localhost/jarek" itp..

A moze user na koncie ktorego chodza programy jakims cudem maja w (Global/Local)SecPol'u zablokowane wystawianie/uzywanie RemoteComponent'ow?

nie wiem, i szczerze mowiac, nawet pomyslu sensownego nie mam.. hum - a co do win7pro - w ogole na pewno umozliwia, ale SecPole warto sprawdzic, domyslne ustawienia nie zdziwilbym sie gdyby blokowaly. Jesli zas probujesz pogadac z win7 z innym - np. xp albo 98 --- oo to juz moga byc schody wielkie.

0

Szkoda, że po prostu nie da się wyłączyć tych zabezpieczeń (na chwilę, chociaż). Próbowałem ustawiać nazwę użytkownika i pwd używają struktury COAUTHIDENTITY, ale też nie podziałało.
Na razie daruje sobie DCOM'a, akurat teraz nie jest mi koniecznie potrzebny - jestem zbyt zielony z systemów, a gdzie nie czytam to zawsze piszą, że co by nie było to ustawienie tego to horror ;)

Biorąc pod uwagę, że różnica jest głównie podczas tworzenia instancji obiektu, to nie jest to pilna sprawa.

1 użytkowników online, w tym zalogowanych: 0, gości: 1