Znáte knihu Dalibor Kačmář - Programujeme COM - COM+ ? Hned první projekt mně nefunguje. Jde o komponentu inprocess (DLL) která impl. generator náhodných čísel a klient , kterej jí pak používá. Podařilo se to někomu rozchodit? Já bych potřeboval, kdyby jste to někdo mohl dát do .raru, a upnout někam na uložto atp. Nemusí to bejt přesně z týhle knihy, ale klidně něco jinýho podobně "základního". Tady sem alespoň upnul to co mně nejde k nakouknutí http://uloz.to/x4UtssEG/komponenta-com-zdroj-kod-rar . Je tam i típnutej obr. z registru, jak sem to měl zareg. A buď jestli mně ste schopnej někdo říct co je tam špatně, nebo ideálně poslat nějakej váš starší projekt podobnýho typu, kterej ale funguje. Dík.
Fórum › C / C++
COM/COM+ Zákl. Inprocess Komponenta a Klient, který ji používá.
Pro liborb: ten projekt jsem upnul na ulozto odkaz je uvedenej v prvním příspěvku!
Včera se mně podařilo najít kód kterej funguje(sou tam i části v POWERBasicu, těch jsem si nevšímal). Tady jsou stránky: http://www.jose.it-berater.org/smfforum/index.php?topic=2980.0 .
Ještě sem neměl čas, ale pokusim se porovnat proč ty zdrojovy soub. z těch stránek výše fungují a ty moje původní ne. Když na něco smysluplnýho přijdu tak sem napíšu.
Takze problem byl - protoze já sem si tam teda taky dost hral s těma STDAPI a HRESULT __stdcall, ale nakonec to vypada, ze tam muzou bejt oba tvary - asi nejspis jen v tom, ze jsem nemel nastavenou cestu(plnou) k Definicnimu soub. DLL knihovny (.def). Ja to komp. ve VS 2003.net a tam je potřeba nastavit ve vlastnostech DLL soub. (v Solution Exploreru RMB na soub. pak Properties) plnou cestu k tomu .def. Když to neudelate tak se ty funkce na samoregistraci a vytvoreni instance tr. komp. nevyexportujou spravne.
V Dependency Walkeru pak je ve sloupci PI "C"v cervenym ramecku u funkce kterou nejakej soub., importuje(asi ji teda vola) a ocekava ze nas soub. ji spravne exportuje. A kdyz ne, tak v pripade spatne vyexport. reg. fci. neproběhne registrace( tu muzete udelat i rucne jako ja na zacatku), ale inst.tr.komp. stejne nevytvoříte.
Po zadani cesty k tomu souboru to zaclo fungovat. Část bez samoreg. jsem pouzil z Kačmáře a tu registracni část (nemel sem CD ke knize kde je prej prilozena) jsem do projektu pridal podle navodu z toho Jose Rocca Software (to zni jak nejaky porno stranky:-), odkaz je v mem prispevku vyse.
Jinak ten Kačmář me namich protože o vytvareni .def souboru mluvi na str. 70 a 76, ale nezminuje, ze se musí ve vyvoj. prostředí nastavit cesta k souboru. Jak sem to mel sakra vedet?
Az se dostanu k tem zdrojovejm soub.(mam je na jinym kompu), tak je sem třeba hodim. Čus.
Funkcni kod i s samoregistraci je zde: http://uloz.to/xxqxNixF/1-2-8-1-komponenta-v-jazyce-c-rar .
A dal sem ho i sem. Nejdriv kod komponenty:
generator.idl :
import "unknwn.idl";
[ object, uuid(12345678-0000-0000-0000-000000000001)]
interface IGenerator : IUnknown
{
HRESULT Reset();
HRESULT NastavMeze([in] float dolni, [in] float horni);
HRESULT DejCislo([out, retval] float* cislo);
}
generator.def :
LIBRARY Generator.dll
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
DllInstall PRIVATE
Registry.h :
#ifndef _REGISTRY_H_
#define _REGISTRY_H_
#pragma warning (disable: 4267)
//#include <basetyps.h> // pro pouziti STDAPI misto HRESULT __stdcall
HRESULT RegisterServer(HMODULE hModule, const CLSID& clsid, const char* szFriendlyName,
const char* szVerIndProgID, const char* szProgID);
HRESULT UnregisterServer(const CLSID& clsid, const char* szVerIndProgID,
const char* szProgID);
HRESULT __stdcall DllRegisterServer();
HRESULT __stdcall DllUnregisterServer();
#endif
Registry.cpp:
// Registry.cpp
#include <objbase.h>
#include "Registry.h"
const int CLSID_STRING_SIZE = 39;
BOOL setKeyAndValue(const char* szKey, const char* szSubkey, const char* szValue)
{
char szKeyBuf[1024];
long lResult;
HKEY hKey;
strcpy(szKeyBuf,szKey); //Copy keyname into buffer.
if(szSubkey!=NULL) // Add subkey name to buffer.
{
strcat(szKeyBuf, "\\") ;
strcat(szKeyBuf, szSubkey ) ;
}
//Create and open key and subkey.
lResult=RegCreateKeyEx(HKEY_CLASSES_ROOT,szKeyBuf,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,NULL);
if(lResult!=ERROR_SUCCESS)
return FALSE ;
if(szValue!=NULL) //Set the Value.
RegSetValueEx(hKey,NULL,0,REG_SZ,(BYTE*)szValue,strlen(szValue)+1);
RegCloseKey(hKey);
return TRUE ;
}
void CLSIDtochar(const CLSID& clsid, char* szCLSID, int length) // Convert a CLSID to a char string.
{
LPOLESTR wszCLSID=NULL;
HRESULT hr;
hr=StringFromCLSID(clsid,&wszCLSID); // Get CLSID
if(SUCCEEDED(hr))
{
wcstombs(szCLSID, wszCLSID,length); // Covert from wide characters to non-wide.
CoTaskMemFree(wszCLSID); // Free memory.
}
}
LONG recursiveDeleteKey(HKEY hKeyParent, const char* lpszKeyChild) // Key to delete
{
char szBuffer[256];
DWORD dwSize=256 ;
HKEY hKeyChild;
FILETIME time;
LONG lRes;
lRes=RegOpenKeyEx(hKeyParent,lpszKeyChild,0,KEY_ALL_ACCESS,&hKeyChild); //Open the child.
if(lRes!=ERROR_SUCCESS)
return lRes;
while(RegEnumKeyEx(hKeyChild,0,szBuffer,&dwSize,NULL,NULL,NULL,&time)==S_OK) //Enumerate all of the decendents of this child.
{
lRes=recursiveDeleteKey(hKeyChild,szBuffer); //Delete the decendents of this child.
if(lRes!=ERROR_SUCCESS)
{
RegCloseKey(hKeyChild); //Cleanup before exiting.
return lRes;
}
dwSize=256;
}
RegCloseKey(hKeyChild); // Close the child.
return RegDeleteKey(hKeyParent,lpszKeyChild); //Delete this child.
}
HRESULT RegisterServer(HMODULE hModule,const CLSID& clsid,const char* szFriendlyName,const char* szVerIndProgID,const char* szProgID)
{
char szCLSID[CLSID_STRING_SIZE];
char szModule[512];
char szKey[64];
if(GetModuleFileName(hModule,szModule,sizeof(szModule)/sizeof(char)))
{
CLSIDtochar(clsid, szCLSID,sizeof(szCLSID)); //Get server location &Convert the CLSID into a char.
strcpy(szKey, "CLSID\\"); //Build the key CLSID\\{...}
strcat(szKey,szCLSID);
setKeyAndValue(szKey,NULL,szFriendlyName); //Add the CLSID to the registry.
setKeyAndValue(szKey, "InprocServer32", szModule); //Add the server filename subkey under the CLSID key.
setKeyAndValue(szKey, "ProgID", szProgID); //Add the ProgID subkey under the CLSID key.
setKeyAndValue(szKey,"VersionIndependentProgID",szVerIndProgID); //Add the version-independent ProgID subkey under CLSID key.
setKeyAndValue(szVerIndProgID, NULL, szFriendlyName); //Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
setKeyAndValue(szVerIndProgID, "CLSID", szCLSID);
setKeyAndValue(szVerIndProgID, "CurVer", szProgID);
setKeyAndValue(szProgID, NULL, szFriendlyName) ; //Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
setKeyAndValue(szProgID, "CLSID", szCLSID) ;
}
else
return E_FAIL;
return S_OK ;
}
HRESULT UnregisterServer(const CLSID& clsid, const char* szVerIndProgID, const char* szProgID)
{
char szCLSID[CLSID_STRING_SIZE];
char szKey[64];
LONG lResult;
CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)); //Convert the CLSID into a char.
strcpy(szKey, "CLSID\\"); //Build the key CLSID\\{...}
strcat(szKey, szCLSID) ;
lResult=recursiveDeleteKey(HKEY_CLASSES_ROOT, szKey); //Delete the CLSID Key - CLSID\{...}
lResult=recursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID); //Delete the version-independent ProgID Key.
lResult=recursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID) ; //Delete the ProgID key.
return S_OK ;
}
//End Registry.cpp
generator.cpp :
///////////////////////////////////////////////////////////////p
// In-process komponenta generátoru náhodných cisel.
// Soubor: generátor.cpp
//
// Autor: Dalibor Kacmar
//
// (C) 2000
///////////////////////////////////////////////////////////////
#include "generator_h.h" // Vygenerovano kompilatorem MIDL
#include <stdlib.h> // Pro praci s srand() a rand()
#include <time.h> // Pro praci s time()
#include <iostream> // Pro praci s vystupnim proudem cout
#include "Registry.h"
// Globals
HINSTANCE g_hModule = NULL; //Store dll instance handle
const char g_szFriendlyName[] = "Generator"; //Store friendly name of component
const char g_szVerIndProgID[] = "Gen.Generator"; //Store Version Independent ProgID
const char g_szProgID[] = "Gen.Generator.1"; //Store Versioned Program ID.
long g_cLocks = 0; // pocitadlo pro uzamceni komponenty v pameti
// CLASS ID komp. {12345678-0000-0000-0000-000000000002}
const CLSID CLSID_Generator = {0x12345678,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}};
// Prototypy
HRESULT __stdcall DllGetClassObject(REFCLSID clsid, REFIID riid, void** ppv);
HRESULT __stdcall DllCanUnloadNow();
HRESULT __stdcall DllInstall(char* s);
class CGenerator : public IGenerator
{
public :
// Metody rozhrani IUnknown
ULONG __stdcall AddRef();
ULONG __stdcall Release();
HRESULT __stdcall QueryInterface(REFIID riid, void** ppv);
// Metody rozhrani IGenerator
HRESULT __stdcall Reset();
HRESULT __stdcall NastavMeze(float dolni, float horni);
HRESULT __stdcall DejCislo(float * cislo);
CGenerator() : m_cRef(1), m_fDolni(0), m_fHorni(1)
{
g_cLocks++; // pocitadlo instanci komponenty
Reset();
}
~CGenerator() { g_cLocks--; }
private:
ULONG m_cRef; // pocitadlo referenci na konkretni instanci
float m_fDolni, m_fHorni; // horni a dolni mez generovanych cisel
};
// Metoda inkrementuje počitadlo referenci
ULONG CGenerator::AddRef()
{
return ++m_cRef;
}
// Metoda dekrementuje počitadlo ref. a připadne uvolňuje instanci z paměti
ULONG CGenerator::Release()
{
if (--m_cRef != 0) // Je to jiz poslední instance?
return m_cRef; // Jeste ne
delete this; // Nikdo jiný tuto instanci neuvolní -> SAMODESTRUKCE
return 0;
}
// Metoda zjistuje existenci požadovaného rozhráni na zaklade IID a vraci na
// nej ukazatel
HRESULT CGenerator::QueryInterface(REFIID riid, void** ppv)
{
if ( riid == IID_IUnknown) // Implementujeme jen IUnknown
*ppv = (IUnknown*)this;
else if ( riid == IID_IGenerator) // nebo IGenerator
*ppv = (IGenerator*)this;
else
{
*ppv = NULL;
return E_NOINTERFACE; // Konstanta signálizujici neexistujici rozhráni
}
AddRef();
return S_OK;
}
// Metoda nastaví horni a dolni nterval, z nehoz budou cisla generovaná
HRESULT CGenerator::NastavMeze(float dolni, float horni)
{
m_fDolni = dolni ;
m_fHorni = horni;
return S_OK;
}
// Metoda inicializuje generátor náhodných cisel
HRESULT CGenerator::Reset()
{
srand((unsigned)time(NULL));
return S_OK;
}
// Metoda generuje další náhodné cislo v určeném rozsahu
HRESULT CGenerator::DejCislo(float * cislo)
{
*cislo = rand()/(float)RAND_MAX*(m_fHorni - m_fDolni)+ m_fDolni;
return S_OK;
}
// Class Factory pro konstrukci instanci tridy CGenerator
class CGeneratorFactory : public IClassFactory
{
public:
// IUnknown
ULONG __stdcall AddRef();
ULONG __stdcall Release();
HRESULT __stdcall QueryInterface(REFIID riid, void** ppv);
// IClassFactory
HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter,
REFIID riid, void** ppv);
HRESULT __stdcall LockServer(BOOL bLock);
CGeneratorFactory() : m_cRef(1) { g_cLocks++; }
~CGeneratorFactory() { g_cLocks--; }
private:
ULONG m_cRef;
};
ULONG CGeneratorFactory::AddRef()
{
return ++m_cRef;
}
ULONG CGeneratorFactory::Release()
{
if (--m_cRef != 0)
return m_cRef;
delete this;
return 0;
}
HRESULT CGeneratorFactory::QueryInterface(REFIID riid , void** ppv)
{
// Podporujeme pouze IUnknown
if (riid == IID_IUnknown)
*ppv = (IUnknown*) this;
// a IClassFactory
else if (riid == IID_IClassFactory)
*ppv = (IClassFactory*)this;
// jiné ne!
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
// Metoda slouzi pro zakládáni instaci tridy CGenerator, tedy instanci
// našeho COM objektu.
HRESULT CGeneratorFactory::CreateInstance(IUnknown *pUnknownOuter, REFIID riid, void** ppv)
{
// Zatim nepodporujeme agregaci
if(pUnknownOuter != NULL)
return CLASS_E_NOAGGREGATION;
// Novy objekt
CGenerator *pGenerator = new CGenerator;
if (pGenerator == NULL)
return E_OUTOFMEMORY;
// Jeste ziskat ukazatel na požadované rozhraní
HRESULT hr = pGenerator->QueryInterface(riid, ppv);
pGenerator->Release();
return hr;
}
// Funkce uzamyká nebo odemyká server v paměti. Pozor inkrementálně!
HRESULT CGeneratorFactory::LockServer(BOOL bLock)
{
if (bLock)
g_cLocks++;
else
g_cLocks--;
return S_OK;
}
// Funkce zjistuje, zda je server mozne odstraniz z paměti.
HRESULT __stdcall DllCanUnloadNow()
{
if(g_cLocks == 0)
return S_OK;
else
return S_FALSE;
};
// Funkce zakládá instanci požadované Class Factory a vraci ukazatel na
// jeji rozhráni IClassFactory.
HRESULT __stdcall DllGetClassObject(REFCLSID clsid, REFIID riid, void** ppv)
{
// Kontrola na požadovanou Class Factory.
// Jinou nez pro CLSID_Generator tato komponenta neposkytuje!
if (clsid != CLSID_Generator)
return CLASS_E_CLASSNOTAVAILABLE;
// Nova instance Class factory
CGeneratorFactory* pFactory = new CGeneratorFactory;
if (pFactory == NULL)
return E_OUTOFMEMORY;
// riid je pravděpodobné IID_IClassFactory.
HRESULT hr = pFactory->QueryInterface(riid, ppv);
pFactory->Release();
return hr;
};
HRESULT __stdcall DllRegisterServer() //created - which creation causes memory allocations for
{ //both the class's VTable pointers and the VTables
return RegisterServer //themselves. Further, class CA implements the abstract
( //base classes I_X and I_Y, and pointers to the
g_hModule, //implementations of the pure virtual functions contained
CLSID_Generator, //within these base classes are placed in the respective
g_szFriendlyName, //VTable of each interface. At this point we have an
g_szVerIndProgID, //object in memory which can be called to do work for us.
g_szProgID
); //DllRegisterServer() and DllUnregisterServer are for
} //adding or eliminating class ids, program ids, etc.,...
HRESULT __stdcall DllUnregisterServer() //relating to the component from the registry. They are
{ //called by the RegSvr32.exe Windows component. For
return UnregisterServer //example, on this development machine CA.dll is in
( //C:\Code\VStudio\VC++6\Projects\COM\ComObjects\CA\Release\CA.dll
CLSID_Generator, //I'd register it by doing this...
g_szVerIndProgID,
g_szProgID //RegSvr32 C:\Code\VStudio\VC++6\Projects\COM\ComObjects\CA\Release\CA.dll
);
} //Having done that I thankfully saw a message box telling...
HRESULT __stdcall DllInstall(char* s) {
return S_OK;
};
// VSTUPNI BOD DO DLL
BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved)
{
switch (reason) //me registration was successful. Registry code is pretty
{ //horrible and in this code was relegated to Registry.cpp
case DLL_PROCESS_ATTACH: //Note that that code needs the dll's instance handle
g_hModule=hInst; //and that is saved just at left in DllMain in a global
break; //variable just for that purpose.
case DLL_PROCESS_DETACH:
break;
}
return TRUE; //Returning FALSE cause
}
// End generator.cpp
A nasleduje kod klienta. Jinak ke klientovi i k budouci DLL si musite ještě pripnout nektery soubory co generuje MIDL z IDL souboru. Na to uz kazdej pride a ja to z hlavy stejne nevim.
klient2.cpp :
#define _WIN32_DCOM
#include <iostream>
#include "stdio.h"
using namespace std;
#include "generator_h.h" // Generován překladačem MIDL
#include "generator_i.c"
void ErrorDescription(HRESULT hr);
// {12345678-0000-0000-0000-000000000002}
const CLSID CLSID_Generator = {0x12345678,0x0000,0x0000,
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02}};
void main()
{
IClassFactory * pIFactory = NULL;
IGenerator * pGen = NULL;
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
cout << "Nelze inicializovat apartment." << endl;
hr = CoGetClassObject(CLSID_Generator, CLSCTX_INPROC_SERVER, NULL,
IID_IClassFactory, (void**)&pIFactory);
if (FAILED(hr))
cout << "Nelze zalozit Class Factory komponenty." << endl;
ErrorDescription(hr);
if (SUCCEEDED(hr))
{
hr = pIFactory->CreateInstance(NULL, IID_IGenerator, (void**)&pGen);
pIFactory->Release();
if (FAILED(hr))
cout << "Nelze vytvorit instanci komponenty tridy Generator." << endl;
if (SUCCEEDED(hr))
{
float cislo;
hr = pGen->NastavMeze(-100, 100);
if (SUCCEEDED(hr))
cout << "Nastaveny meze generatoru na <-100,100>" << endl;
cout << "Generuji 10 cisel: " << endl;
for (int i = 0; i < 10; i++)
{
hr = pGen->DejCislo(&cislo);
if(SUCCEEDED(hr))
cout << cislo << endl;
}
pGen->Release();
}
}
CoUninitialize();
int n; cin >> n;
}
void ErrorDescription(HRESULT hr)
{
if(FACILITY_WINDOWS == HRESULT_FACILITY(hr))
hr = HRESULT_CODE(hr);
char* szErrMsg;
if(FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&szErrMsg, 0, NULL) != 0)
{
printf("%s", szErrMsg);
LocalFree(szErrMsg);
}
else
printf("[Could not find a description for error # %#x.]\n", hr);
}
Ty funkce ErrorDescription() si nemusíte všímat, ja ji pouzival když to nefungovalo. Zdar!
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Kód, který edituje/píše kód, který se hned dá spustit — založil Kartik
Jak se to používá? — založil Jimosona
Kde sa pouziva C/C++? — založil Tom@sQo
Začátečník, MinGW - jak se používá? — založil Marek
Čo znamena "locale" v jave a na čo sa používa? — založil Viki
Moderátoři diskuze