2011-07-28 20 views
18

Quiero escribir un perfilador CLR para enganchar nuestra función de aplicación con GetILFunctionBody/SetILFunctionBody.Analizador CLR: problema al usar DefineAssemblyRef

Quiero usar DefineAssemblyRef para importar nuestro C# dll (para usar en el código IL) en este código DefineAssemblyRef siempre devuelve True? ¿Mi dll tiene que estar firmado? ¿Necesita ser instalado en el caché de ensamblaje global (GAC)?

 HRESULT CProfilerCallback::JITCompilationStarted 
     (
     UINT functionId, 
     BOOL fIsSafeToBlock 
     ) 
    { 
     ClassID classID; 
     ModuleID moduleID; 
     mdToken token; 
     wchar_t wszClass[512]; 
     wchar_t wszMethod[512]; 
     HRESULT result = S_OK; 
     ClassID classId = 0; 
     ModuleID moduleId = 0; 
     mdToken tkMethod = 0; 

     // Get the moduleID and tkMethod  
     m_pICorProfilerInfo->GetFunctionInfo(functionId, &classId, &moduleId, &tkMethod); 

     if(!GetMethodNameFromFunctionId(functionId,wszClass,wszMethod)) 
     {return S_FALSE;} 


     if(wcscmp(wszMethod,L"FunctionName") == 0) 
     { 
      // Get the metadata import 
      IMetaDataImport* pMetaDataImport = NULL; 
      DebugBreak(); 
      result = m_pICorProfilerInfo->GetModuleMetaData 
       (
       moduleId, 
       ofRead, 
       IID_IMetaDataImport, 
       (IUnknown**)&pMetaDataImport 
       ); 


      if (FAILED(result)) 
      { return S_FALSE;} 
     // 
     // Metadata modification 
     // 
     IMetaDataEmit* pMetaDataEmit = NULL;  
     IMetaDataAssemblyEmit* pMetaDataAssemblyEmit = NULL; 
     mdAssemblyRef tkLoggerLib; 
     HRESULT res; 
     res = m_pICorProfilerInfo->GetModuleMetaData 
      (
      moduleId,   /// The ID of the module to which the interface instance will be mapped 
      ofRead | ofWrite, 
      IID_IMetaDataEmit, 
      (IUnknown**)&pMetaDataEmit 
      ); 

     if (FAILED(res)) {DebugBreak(); return S_FALSE;} /// DebugBreak for debug 

     res = pMetaDataEmit->QueryInterface 
      (
      IID_IMetaDataAssemblyEmit, 
      (void**)&pMetaDataAssemblyEmit 
      ); 

     if (FAILED(res)) { return S_FALSE;} 

     // Get the token for the Logger class and its Log method 
     mdTypeDef tkLogger = 0; 
     mdMethodDef tkLog = 0; 

     // Create a token for the Log.dll assembly 
     ASSEMBLYMETADATA amd; 
     ZeroMemory(&amd, sizeof(amd)); 
     amd.usMajorVersion = 0; 
     amd.usMinorVersion = 0; 
     amd.usBuildNumber = 0; 
     amd.usRevisionNumber = 0; 

     res= pMetaDataAssemblyEmit->DefineAssemblyRef 
      (
      NULL, 0, // No public key token 
      L"Dllname", ///dll name 
      &amd, NULL, 0, 0, 
      &tkLoggerLib 
      ); 

     if (FAILED(res)) {return S_FALSE; } 

       ...... 
+1

No he incursionado en los profilers de .NET durante años, así que podría estar fuera de base aquí, pero ¿por qué esperarías que fallara DefineAssemblyRef? Simplemente está declarando una referencia: el ensamblaje real no se resuelve hasta que se utiliza la referencia. Su ensamblaje no debería tener que estar firmado o en el GAC, pero el ensamblado que realiza la llamada necesita poder encontrarlo, por lo tanto, si no está en el GAC, debe estar en un directorio que en la ruta de búsqueda, IIRC. –

+0

Para la posteridad [este enlace] (http://www.dupuis.me/node/18) se publicó como una respuesta que parece que se puede eliminar. La descripción en el enlace parece ser muy relevante para la pregunta, aunque no tengo el conocimiento seguro. – Ben

Respuesta

1

De acuerdo con este blog de MSDN http://blogs.msdn.com/b/davbr/archive/2006/02/27/540280.aspx:

IMetaDataAssemblyEmit :: DefineAssemblyRef() le da una mdAssemblyRef a su montaje. Es necesario un poco de trabajo para hacerlo bien. Una forma confiable de hacer referencia a su ensamblaje es firmar su ensamblaje, agregarlo al GAC y usar la clave pública que se imprime "gacutil/l"

También puede encontrar útil este proyecto - Gancho dinámico CLR inyección http://www.dupuis.me/node/18 que demuestra lo que estás tratando de hacer.

Cuestiones relacionadas