2013-03-23 53 views
0

要啓用精心製作的調試場景,我需要我的程序集來確定源文件在運行時的位置。如何找出程序集的項目目錄?

Assembly對象不知道這個信息,它可能不應該。 .pdb文件顯然知道,但我不知道如何解析它。所以我想也許我可以標記在構建時組裝與屬性,東西的效果:

[assembly: AssemblyMetadata("ProjectDirectory", $(ProjectDir))] 

我不能使用當前目錄,因爲它是由IIS中設置一些臨時目錄調試。我也不想對目錄進行硬編碼。

最近我到目前爲止解決這個問題,是使用Assembly.CodeBase屬性。它指向構建IIS解決方案的目錄(Solution/IISProject/bin/Debug/,而不是/Solution/source/MyLibrary/),但不是我的項目目錄。一個黑客解決方案從那裏上升幾個級別,然後再往下幾級返回到項目文件夾。如果可能的話,我非常想避免這種黑客攻擊。

+0

爲什麼你需要這個?如果你能告訴我們爲什麼這是有趣的信息存儲,那麼也許我們可以給你另外的解決方案。我不認爲有一種內置的方式來獲得你想要的。 – 2013-03-23 16:20:45

+0

@ LasseV.Karlsen我需要它能夠在調試運行時重新編譯部分解決方案(這些部分是特定領域的語言)。我確信有些事情可以做到。我的第一個想法是解析.pdb,它顯然具有這些信息,但顯然它不容易分析。 – Gleno 2013-03-23 16:28:07

回答

0

要啓用這些類型的場景,通常最好的做法是將這些目錄放置在web.config中的設置中。所以你可以說根據給定的情況,使用這個目錄代替這個目錄。通常人們使用if(IsDebugging)使用這個dir,否則使用這個dir。

0

經過大量的靈魂搜索,我設法收集了足夠的inspiration來撰寫以下代碼片段。這個想法是使用.pdb文件來發現源代碼的位置。您需要參考ISymWrapper.dll並以32位模式編譯。如果有更簡單的方法,我會很高興聽到它。

using System; 
using System.Diagnostics.SymbolStore; 
using System.IO; 
using System.Reflection; 
using System.Runtime.InteropServices; 
using System.Linq; 
public static class AssemblyDirectoryInfo 
{ 
    private const string 
     ImporterId = "7DAC8207-D3AE-4c75-9B67-92801A497D44", 
     DispenserId = "809c652e-7396-11d2-9771-00a0c9b4d50c", 
     DispenserClassId = "e5cb7a31-7512-11d2-89ce-0080c792e5d8"; 

    [Guid(ImporterId), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComVisible(true)] 
    public interface IMetaDataImport{} 

    [Guid(DispenserId), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), ComVisible(true)] 
    interface IMetaDataDispenser 
    { 
     void DefineScope(); 

     void OpenScope([In, MarshalAs(UnmanagedType.LPWStr)] String szScope, [In] Int32 dwOpenFlags, 
         [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.IUnknown)] out Object punk); 
    } 

    [DllImport("ole32.dll")] 
    private static extern int CoCreateInstance([In] ref Guid guid, 
     [In, MarshalAs(UnmanagedType.IUnknown)] Object pUnkOuter, 
     [In] uint dwClsContext, 
     [In] ref Guid riid, 
     [Out, MarshalAs(UnmanagedType.Interface)] out Object ppv); 

    public static DirectoryInfo GetAssemblyCodeBase(Assembly assembly) 
    { 
     var file = new FileInfo(assembly.Location); 

     Guid dispenserClassId = new Guid(DispenserClassId), 
      importerIid = new Guid(ImporterId), 
      dispenserIid = new Guid(DispenserId); 

     object dispenser, importer; 

     CoCreateInstance(ref dispenserClassId, null, 1, ref dispenserIid, out dispenser); 
     ((IMetaDataDispenser)dispenser).OpenScope(file.FullName, 0, ref importerIid, out importer); 

     var ptr = Marshal.GetComInterfaceForObject(importer, typeof(IMetaDataImport)); 
     var reader = new SymBinder().GetReader(ptr, file.FullName, file.DirectoryName); 
     return reader.GetDocuments() 
        .Select(d => d.URL) 
        .Where(v => !string.IsNullOrEmpty(v)) 
        .OrderBy(v => v.Length) 
        .Select(v => new FileInfo(v).Directory) 
        .First(); 
    } 
} 
相關問題