Newsgroup: it.comp.programmare.win32
Titolo: Come ottenere la lista delle DLL utilizzate da un programma ?

Vorrei sapere se esiste un modo per conoscere il nome delle DLL che un
programma utilizza durante l'esecuzione.
Io sono già in grado di conoscere queste informazioni in modo statico, cioè
controllando il .exe generato, mentre per creare un file di Log, vorrei
creare una funzione generica da inserire nei miei programmi del tipo.
void GetVersionAllDll()
{
 OttieniListaDllUtilizzate();  // *** Devo implementare questa funzione
 for ( scansione lista Dll utilizzate ){
   ...ottieni percorso file Dll..
   LeggiVersione( Dll );
   printf("Dll %s Versione %s",
     PathDll,
     VersioneDll );
 }
}
Spero di essere stato abbastanza chiaro.
Grazie
Massimo Dedin

 
Per farlo dovresti "agganciare" una tua funzione al posto di LoadLibrary  
che provveda a loggare la chiamata e a richiamare la vera loadlibrary 
(ci dovrebbe essere un articolo di Pietrek su MSDN che spiega come 
sviluppare un "monitor" delle varie chiamate API e illustra questa 
tecnica, purtroppo non ho link sottomano).
-- 
Valter Minute
min...@inwind.it
 (the reply address of this message is invalid)

che provveda a loggare la chiamata e a richiamare la vera loadlibrary 
Hmmm... se ci si limita a visualizzare quelle linkate
staticamente, comunque, la cosa e' molto piu' semplice.
Basta elencare i vari moduli con le API ToolHelp sotto 9x/2K
e PSAPI sotto NT.
--
CyberWalkie - walkietalkie(at)
libero.it

cyber...@cyberwalkie.cyb (CyberWalkie) wrote in
news:3b4d9a9...@news.libero.it
: 

Con ToolHelp e PSAPI elenchi anche quelle caricate dinamicamente. 
Il problema però è che in questo modo puoi vedere solo quali DLL sono 
caricate in un certo istante e, anche effettuando un polling piuttosto 
stretto, potresti perderti qualche DLL che viene caricata per pochissimo 
tempo (ex un oggetto COM). 
Ovviamente anche il metodo da me descritto riporterà solo le DLL 
effettivamente caricate durante l'utilizzo del programma e quindi non 
garantisce al 100% che questo corrisponda al totale.
L'unica alternativa che mi viene in mente è disassemblare i vari moduli 
(man mano che vengono trovati) e cercare le chiamate a LoadLibrary in 
modo che sia poi possibile (tramite l'hook descritto prima) verificare 
quando siano state effettivamente richiamate tutte... anche se è 
possibile che alcune delle chiamate siano nel codice ma non vengano mai 
eseguite...


L'unica alternativa che mi viene in mente è disassemblare i vari moduli 
E a questo punto, inserorabilmente, la mannaia del Sig.
QuantoNeValgaLaPena, scende a tagliare le teste dei poveri
torelli sacrificali :-)
--
CyberWalkie - walkietalkie(at)
libero.it

 
Vero.
E' comunque divertente risolvere questo tipo di problemi quando sei 
sicuro che non sarai tu a dover implementare la soluzione :)



Grazie per l'incoraggiamento.
Scherzi a parte, grazie per le dritte.Per quello che devo fare penso siano
sufficienti le
API ToolHelp.
Vi farò sapere se risolverò il problema.
Ciao Massimo Dedin


Scusate, probabilmente ci avete già pensato, ma "debuggare il processo" -
usando CreateProcess con il flag DEBUG_PROCESS o DEBUG_ONLY_THIS_PROCESS?
Dopo si potrebbe chiamare WaitForDebugEvent, che tra le altre cose ritorna
con una struct DEBUG_EVENT nel caso si verifichi un evento di debug. Tra gli
eventi di debug ci sono (vedi l'SDK - struttura DEBUG_EVENT) gli eventi
LOAD_DLL_DEBUG_EVENT e UNLOAD_DLL_DEBUG_EVENT, con tanto di nome della Dll.
Mi sembra più semplice.
Saluti
Zello


void CAppInfoDlg::OnBtEnumProcess()
{
	const DWORD bSize = 4096;
	DWORD
buff[bSize];
	DWORD dwNeeded;
	m_tcProcesses.SetRedraw(FALSE);
BeginWaitCursor();
	m_tcProcesses.DeleteAllItems();
EnumProcesses(buff, bSize, &dwNeeded);
	INT nProcesses = dwNeeded /
sizeof(DWORD);
	HANDLE hProcess;
	INT nModules;
	const DWORD
STR_SIZE = 4096;
	//not used...
	//TCHAR ModName[STR_SIZE];
	TCHAR
ModFileName[STR_SIZE];
	//item index for the list control...
	HTREEITEM
htItem;
	for(INT i = 0; i < nProcesses; ++i)
	{
		hProcess =
OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, buff[i]);
if(hProcess == NULL)
			AfxMessageBox(_T("Not Valid"));
		if (hProcess
!= NULL)
		{
 
			const DWORD bModSize = 2048;
			HMODULE
Modbuff[bModSize];
			DWORD dwModNeeded;
			if
(EnumProcessModules(hProcess, Modbuff, sizeof(Modbuff), &dwModNeeded))
{
				nModules = dwModNeeded / sizeof(HMODULE);
GetModuleFileNameEx(hProcess, Modbuff[0], ModFileName, STR_SIZE);
htItem = m_tcProcesses.InsertItem(ModFileName);
 
				for(INT j = 1;
j < nModules; ++j)
				{
					if (Modbuff[j] != NULL)
					{
//GetModuleBaseName(hProcess, Modbuff[j], ModName, STR_SIZE);
GetModuleFileNameEx(hProcess, Modbuff[j], ModFileName, STR_SIZE);
m_tcProcesses.InsertItem(ModFileName, htItem);
					}
				}
			}
		}
CloseHandle(hProcess);
	}
	m_tcProcesses.SetRedraw(TRUE);
EndWaitCursor();
}
Qualche giorno fa ho scritto questo codice, popola
un TreeCtrl con tutti i processi attivi ed enumera i moduli caricati da
ciascun processo.
Ciao, Davide.
--------------------------------
Inviato via 
http://usenet.iol.it
 


Seguendo i Vostri preziosi suggerimenti ho implementato questa funzione che
ho provato su W98 e WNT:
Grazie a tutti coloro che hanno partecipato.
Ricordo che il mio scopo era di generare una lista delle dll caricate, per
ottenere un LOG
con tutte le informazioni di sistema necessarie, per trovare eventuali
problemi dei miei programmi installati su macchine diverse.
Per rendere al funzione compatibile con i diversi sistemi operativi carico
le librerie in
modo dinamico altrimenti avrei dovuto creare due copie di programma.
( Questa e' un estratto della funzione che utilizzo e quindi non e'
compilata )
typedef BOOL WINAPI (*procEnumProcessModules)(HANDLE,HMODULE
*,DWORD,LPDWORD );
typedef DWORD WINAPI (*procGetModuleFileNameExA)(HANDLE ,HMODULE ,LPSTR,
DWORD );
typedef HANDLE WINAPI (*procCreateToolhelp32Snapshot)( DWORD dwFlags, DWORD
th32ProcessID );
typedef BOOL WINAPI (*procModule32First)(HANDLE , LPMODULEENTRY32  );
typedef BOOL WINAPI (*procModule32Next)(HANDLE , LPMODULEENTRY32);
int GetModuliAttivi( )
{
   HINSTANCE  hInstKernel = LoadLibrary( "KERNEL32.DLL" );
   procCreateToolhelp32Snapshot pfCreateToolhelp32Snapshot =
procCreateToolhelp32Snapshot)GetProcAddress( hInstKernel,"CreateToolhelp32Sn
apshot" );
  if ( pfCreateToolhelp32Snapshot  == NULL ){
     // Sono su NT4 e la funzione non e' implementata
     // WINNT
     // CARICO PSAPI.DLL
     HINSTANCE  hInstPSAPI = LoadLibrary( "PSAPI.DLL" );
     procEnumProcessModules pfEnumProcessModules =
       (procEnumProcessModules)GetProcAddress( hInstPSAPI,
"EnumProcessModules" );
     // Bisogna controllare l'UNICODE e richiamare GetModuleFileNameExW
     procGetModuleFileNameExA pfGetModuleFileNameEx =
       (procGetModuleFileNameExA)GetProcAddress( hInstPSAPI,
"GetModuleFileNameExA" );
     if ( hInstPSAPI ){
       HANDLE hdl = OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
0,
         GetCurrentProcessId() );
       int    iErr = 0;
       HMODULE   LM[1000];
       DWORD        iTot;
       char      szPath[260];
       DWORD         cbNeeded;
      if ( hdl ){
        if ( (pfEnumProcessModules)(hdl, LM, 1000, &cbNeeded)
         for ( int ii = 0; ii < (cbNeeded / sizeof(HMODULE)); ii++ ){
           if ( (pfGetModuleFileNameEx)(hdl, LM[ii ], szPath, 260 ) ){
             OUT ( szPath + VersioneFile( szPath ) ;
           }
         }
       }
       CloseHandle( hdl );
      }
    }
    FreeLibrary(hInstPSAPI);
  }
  else{
   // SISTEMI W9x e NT5
   BOOL          bRet        = FALSE;
   BOOL          bFound      = FALSE;
   HANDLE        hModuleSnap = NULL;
   MODULEENTRY32 me32        = {0};
   procModule32First pfModule32First =
        (procModule32First)GetProcAddress( hInstKernel , "Module32First" );
   procModule32Next pfModule32Next =
        (procModule32Next)GetProcAddress( hInstKernel , "Module32Next" );
   // Take a snapshot of all modules in the current process.
   hModuleSnap = (pfCreateToolhelp32Snapshot)(TH32CS_SNAPMODULE, NULL );
   if (hModuleSnap == (HANDLE)-1)
     return 0 ;
   // Fill the size of the structure before using it.
   me32.dwSize = sizeof(MODULEENTRY32);
   // Walk the module list of the process, and find the module of
   // interest. Then copy the information to the buffer pointed
   // to by lpMe32 so that it can be returned to the caller.
   if ((pfModule32First)(hModuleSnap, &me32) ){
    do{
      OUT ( me32.szExePath + VersioneFile( me32.szExePath ) ;
    } while ( (pfModule32Next)(hModuleSnap, &me32));
   }
   CloseHandle (hModuleSnap);
 }
 FreeLibrary(hInstKernel );
}
Saluti Massimo Dedin

programma utilizza durante l'esecuzione.
confronta i risultati ottenuti da quello che sei riuscito a realizzare
tu con quelli dell'ottimo Dependency Walker:
http://www.dependencywalker.com/
-- 
Posted from 
mx1.aruba.it
 [62.149.128.130] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG


Il programma a prma vista sembra buono, e grazie per il  Link, anche se io
avevo bisogno
di un qualcosa che scrivesse il risultato su di un file testo di Log, e
sopratttuto devo
poterlo distribuire commercialmente.
Grazie di Nuovo e Ciao.
Massimo Dedin

e sopratttuto devo poterlo distribuire commercialmente.
 
DW non è distribuibile :(