#4 vit24
Jeste jsem zapomel to nejdulezitejsi ta cesta kam v Properties zadate tu cestu k .def souboru je : \Configuration Properties \Linker \Input \Module Definition File
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!
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
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.
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.
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.
Sorry, ze sem neodpovidal, ale nemam pristup k internetu furt. A na tom pocitaci s internetem zase nemam ty kody. Ale uz sem to vyresil takze:
1) Nejdriv jsem dopsal u v "double" v overdraft.h / line 15.,
pak zkompiloval. Objevili se novy věci, který předtím nebyli videt, protože kvůli fatal error se to vlastne cely
nedokompilovalo.
2) vyjel novej seznam chyb:
c2065: "bal": undeclared identifier /line 43
c2065: "ovesBank": undeclared identifier /line19
c 3861: "bal": identifier not found even with argument-dependent lookup /line 45+47
(všechno v overdraft.cpp)
line 19. "ovesBank" jsem prepsal na owesBank,
line 43. chyba tady byla ze před prikazem "if" mne upne chybela deklarace a inicializace "bal",
takze takhle: double bal = Balance(); a pak az radek 43.
Nevim jestli to nekomu k necemu je, ale ma se sem psat reseni tak ho sem pisu. Cau.
Nevíte někdo proč tenhle kod háže tyhle chyby?:
[URL=http://www.nahraj-obrazek.cz/pm-1114035319971.png][IMG]http://www.nahraj-obrazek.cz/dm-1114035319971.png[/IMG][/URL]
[URL=http://www.nahraj-obrazek.cz/pm-14140353227212.png][IMG]http://www.nahraj-obrazek.cz/dm-14140353227212.png[/IMG][/URL]
[URL=http://www.nahraj-obrazek.cz/pm-214035323247.png][IMG]http://www.nahraj-obrazek.cz/dm-214035323247.png[/IMG][/URL]
[URL=http://www.nahraj-obrazek.cz/pm-14140353235413.png][IMG]http://www.nahraj-obrazek.cz/dm-14140353235413.png[/IMG][/URL]
[URL=http://www.nahraj-obrazek.cz/pm-114035323827.png][IMG]http://www.nahraj-obrazek.cz/dm-114035323827.png[/IMG][/URL]
[URL=http://www.nahraj-obrazek.cz/pm-714035324105.png][IMG]http://www.nahraj-obrazek.cz/dm-714035324105.png[/IMG][/URL]
Je to všechno podle učebnice, takže by to mělo bejt správně.
Děkuju.