References/Verweise eines Projekts auslesen

DennisW

Grünschnabel
Hi zusammen.

In einem Projekt kann man sich ja alle References anschauen. Zu jeder Reference man dann die Eigenschaften einsehen, in denen ich z.B Pfad, Version und Description sehe. Ist es möglich an diese Informationen auch per Code zu kommen?
Ich möchte also per Code meine Verweise auslesen und die entsprechenden Attribute dazu einsehen können.

Vielen Dank schonmal im voraus!

MfG
Dennis
 

Norbert Eder

Erfahrenes Mitglied
Über AppDomain.GetAssemblies bekommst du alle geladenen Assemblies heraus. Jede Assembly hat nun eine Methode GetReferencedAssemblies, diese liefert dir die referenzierten Assemblies zu jeder ausgewählten Assembly.

Damit solltest du dein Vorhaben erledigen können.
 

DennisW

Grünschnabel
Vielen Dank erstmal! Ich habe nun ein Problem. Ich habe mir zu diesem Thema folgende Seite angeschaut:

http://msdn2.microsoft.com/en-us/library/system.appdomain.getassemblies(VS.80).aspx

Dort gibt es u.a. einen Beispielcode für VB.Net und C#. Ich habe beide ausprobiert und beide bleiben jeweils in der Zeile "currentDomain.Load("CustomLibrary",asEvidence)" hängen.
Die Fehlermeldung lautet "Die Datei oder Assembly CustomLibrary oder eine Abhängigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden.". Diese Meldung hilft mir jedenfalls nicht bei der Problemfindung.

Hast Du eine Idee woran das liegen könnte? In der Regel sollten die Beispielcodes von MSDN ja laufen, aber hier scheint das nicht der Fall zu sein.

Gruß,
Dennis.
 

Norbert Eder

Erfahrenes Mitglied
In diesem Beispiel wird eine vorhandene Assembly in eine Application Domain geladen. Diese nennt sich CustomLibrary. Und diese wird dann nach ihren referenzierten Assemblies durchsucht.

Du müsstest nun eine Assembly namens CustomLibrary anlegen, damit das funktioniert. Steht auch im Kommentar direkt über der Zeile:

C#:
//Create an assembly called CustomLibrary to run this sample.
currentDomain.Load("CustomLibrary",asEvidence);
 

DennisW

Grünschnabel
Ups sorry, dummer Fehler :-(

Ich bekomme nun 31 Referenzen zurückgegeben. Darunter ist u.a. die svhost.exe meines Projektes und z.B. eine DLL Namens "Microsoft.VisualStudio.HostingProcess.Utilities.dll".

Unter den Projekteigenschaften sehe ich diese allerdings nicht in den Verweisen. Gibt es eine Möglichkeit dies zu unterdrücken, so dass ich wirklich nur die Verweise bekomme, die in den Projekteigenschaften sichtbar sind?
 
L

lukoslav

Ich hoffe, ich darf den Thread nochmal rauskramen.

Gibt es auch eine Möglichkeit, References auszulesen, die ich noch nicht instanziert habe? Es handelt sich bei mir um die Excel-Interop-Bibliothek. Ich möchte vor dem Abprüfen ungern eine Instanz der Applikation erzeugen.

Viele Grüße!
 

Cromon

Erfahrenes Mitglied
Na klar, das ist kein Problem! Du kannst einfach einen IMetaDataAssemblyImport erstellen mit dem Speicher der Metadaten und dann über die referenzierten Assmblies iterieren.

Hier der Code meines nie fertig gestellten CLI-Teiles meines PE-Explorers. Relevant für dich ist die Funktion LoadAssemblyReference.

NETAnalyze.h
C++:
#pragma once

// CNetAnalyze command target

class CPEAnalyzeDlg;

class CNetAnalyze : public CObject
{
	PIMAGE_NT_HEADERS m_ntHeader;
	LOADED_IMAGE& m_image;

	IMetaDataImport2* m_importer;
	IMetaDataDispenserEx* m_dispenser;
	IMetaDataAssemblyImport* m_assemblyReader;

	CPEAnalyzeDlg* m_outDlg;

	void ParseTypeDef(mdTypeDef& def);
	void LoadMethods(mdTypeDef& def);
	void LoadMethodInfo(mdMethodDef& def, mdTypeDef& cld);
	void LoadTypeReferences();
	void ParseTypeReference(mdTypeRef& ref);
	void LoadTypes();
	void LoadAssemblyReferences();
	void ParseAssemblyReference(mdAssemblyRef& ref);

public:
	CNetAnalyze(IMAGE_NT_HEADERS* pHeader, LOADED_IMAGE* pImage, CPEAnalyzeDlg* pDlg);
	virtual ~CNetAnalyze();

	void LoadMetaData();
};

NetAnalyze.cpp
C++:
// NetAnalyze.cpp : implementation file
//

#include "stdafx.h"
#include "resource.h"
#include "PEAnalyzeDlg.h"
#include "NetAnalyze.h"


// CNetAnalyze

CNetAnalyze::CNetAnalyze(IMAGE_NT_HEADERS* pHeader, LOADED_IMAGE* pImage, CPEAnalyzeDlg* pDlg) : m_ntHeader(pHeader), m_image(*pImage), m_outDlg(pDlg)
{
	CoInitialize(NULL);
	HRESULT hRes = CoCreateInstance(CLSID_CorMetaDataDispenser, NULL, CLSCTX_INPROC_SERVER, IID_IMetaDataDispenserEx, (void**)&m_dispenser);
	if(FAILED(hRes) || m_dispenser == NULL)
	{
		m_outDlg->AppendOutputString(CString(_T("Failed to load MetaDataDispenser!")));
		return;
	}
	IMAGE_COR20_HEADER* netHeader = (IMAGE_COR20_HEADER*)ImageRvaToVa(m_ntHeader, m_image.MappedAddress, m_ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress, NULL);
	if(netHeader == NULL)
	{
		m_outDlg->AppendOutputString(CString(_T("No valid .NET-assembly!")));
		return;
	}

	LPCVOID metaData = (LPCVOID)ImageRvaToVa(m_ntHeader, m_image.MappedAddress, netHeader->MetaData.VirtualAddress, NULL);
	
	if(metaData == NULL)
	{
		m_outDlg->AppendOutputString(CString(_T("No metadata associated!")));
		return;
	}
	
	hRes = m_dispenser->OpenScopeOnMemory(metaData, netHeader->MetaData.Size, 0, IID_IMetaDataImport2, (IUnknown**)&m_importer);
	if(FAILED(hRes) || m_importer == NULL)
	{
		m_outDlg->AppendOutputString(CString(_T("Failed to open scope on metatdata memory!")));
		return;
	}

	hRes = m_dispenser->OpenScopeOnMemory(metaData, netHeader->MetaData.Size, 0, IID_IMetaDataAssemblyImport, (IUnknown**)&m_assemblyReader);
	if(FAILED(hRes) || m_assemblyReader == NULL)
	{
		m_outDlg->AppendOutputString(CString(_T("Failed to open assembly scope on metadata memory!")));
		return;
	}

	m_outDlg->AppendOutputString(CString(_T("Ready to parse metadata...")));
}

CNetAnalyze::~CNetAnalyze()
{
	if(m_dispenser)
		m_dispenser->Release();
	if(m_importer)
		m_importer->Release();
	if(m_assemblyReader)
		m_assemblyReader->Release();
}

void CNetAnalyze::LoadMetaData()
{
	WCHAR module[MAX_PATH];
	ULONG nameLen;
	m_importer->GetScopeProps(module, MAX_PATH, &nameLen, NULL);
	m_outDlg->AppendOutputString(CString(_T("Loading module '")) + module + _T("'..."));
	LoadTypes();
	LoadTypeReferences();
	LoadAssemblyReferences();
}

void CNetAnalyze::LoadTypes()
{
	HCORENUM corEnum = 0;
	mdTypeDef typeDefs[10];
	ULONG numTypeDefs = 0;
	while(SUCCEEDED(m_importer->EnumTypeDefs(&corEnum, typeDefs, 10, &numTypeDefs)))
	{
		if(numTypeDefs == 0)
			break;

		for(ULONG i = 0; i < numTypeDefs; ++i)
			ParseTypeDef(typeDefs[i]);
	}
	m_importer->CloseEnum(corEnum);
}

void CNetAnalyze::ParseTypeDef(mdTypeDef& def)
{
	WCHAR typeDefName[MAX_PATH];
	ULONG nameLen;
	DWORD flags;
	mdToken extend;
	HRESULT hRes = m_importer->GetTypeDefProps(def, typeDefName, MAX_PATH, &nameLen, &flags, &extend);
	if(FAILED(hRes))
		return;
	m_outDlg->AppendOutputString(CString(typeDefName));
	LoadMethods(def);
	// TODO:
	// Implement fields, properties, ...
}

void CNetAnalyze::LoadMethods(mdTypeDef& def)
{
	HCORENUM corEnum = 0;
	mdMethodDef typeDefs[10];
	ULONG numTypeDefs = 0;
	while(SUCCEEDED(m_importer->EnumMethods(&corEnum, def, typeDefs, 10, &numTypeDefs)))
	{
		if(numTypeDefs == 0)
			break;

		for(ULONG i = 0; i < numTypeDefs; ++i)
			LoadMethodInfo(typeDefs[i], def);
	}
	m_importer->CloseEnum(corEnum);
}

void CNetAnalyze::LoadMethodInfo(mdMethodDef& def, mdTypeDef& type)
{
	WCHAR methodName[MAX_PATH];
    ULONG nameLen;
    DWORD flags;
	PCCOR_SIGNATURE sig;
	/// TODO:
	/// Implement PCCOR_SIGNATURE and the last (yet unused) parameters of GetMethodProps
	HRESULT hRes = m_importer->GetMethodProps(def, &type, methodName, MAX_PATH, &nameLen, &flags, &sig, &nameLen, &nameLen, &nameLen);
	if(FAILED(hRes))
		return;

	m_outDlg->AppendOutputString(CString(methodName));
}

void CNetAnalyze::LoadTypeReferences()
{
	HCORENUM corEnum = NULL;
	mdTypeRef refs[10];
	ULONG numRefs = 0;
	while(SUCCEEDED(m_importer->EnumTypeRefs(&corEnum, refs, 10, &numRefs)))
	{
		if(numRefs == 0)
			break;
		for(ULONG i = 0; i < numRefs; ++i)
			ParseTypeReference(refs[i]);
	}
}

void CNetAnalyze::ParseTypeReference(mdTypeRef& ref)
{
	mdToken refToken;
	WCHAR refName[MAX_PATH];
	ULONG nameLen;
	HRESULT hRes = m_importer->GetTypeRefProps(ref, &refToken, refName, MAX_PATH, &nameLen);
	if(FAILED(hRes))
		return;

	m_outDlg->AppendOutputString(CString(refName));
}

void CNetAnalyze::LoadAssemblyReferences()
{
	HCORENUM corEnum = NULL;
	mdAssemblyRef refs[10];
	ULONG numRefs = 0;
	while(SUCCEEDED(m_assemblyReader->EnumAssemblyRefs(&corEnum, refs, 10, &numRefs)))
	{
		if(numRefs == 0)
			return;
		for(ULONG i = 0; i < numRefs; ++i)
			ParseAssemblyReference(refs[i]);
	}
}

void CNetAnalyze::ParseAssemblyReference(mdAssemblyRef& ref)
{
	WCHAR refName[MAX_PATH];
	ULONG nameLen;
	HRESULT hRes = m_assemblyReader->GetAssemblyRefProps(ref, NULL, NULL, refName, MAX_PATH, &nameLen, NULL, NULL, NULL, NULL);
	if(FAILED(hRes))
		return;
	m_outDlg->AppendOutputString(CString(refName));
}


// CNetAnalyze member functions
 
Zuletzt bearbeitet: