簡體   English   中英

如何找到裝配體的項目目錄?

[英]How to find out the project directory of an assembly?

為了啟用詳盡的調試方案,我需要我的程序集來確定源文件在運行時的位置。

Assembly對象不知道此信息,也可能不知道。 .pdb文件顯然知道,但是我不知道如何解析它。 所以我想也許可以在構建時用屬性標記我的程序集,從而達到以下效果:

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

我無法使用當前目錄,因為在調試過程中IIS將其設置為某個臨時目錄。 我也不想對目錄進行硬編碼。

到目前為止,我解決這個問題最接近的方法是使用Assembly.CodeBase屬性。 它指向構建IIS解決方案的目錄( Solution/IISProject/bin/Debug/ ,而不是/Solution/source/MyLibrary/ ),而不是我的項目目錄。 一個駭人聽聞的解決方案從那里上升了幾層,然后下降了幾層回到項目文件夾。 如果可能的話,我非常想避免這種黑客攻擊。

通常,要啟用這些類型的方案,最佳實踐是將這些目錄放在web.config中的設置中。 因此,您可以根據特定情況說,使用此目錄而不是此目錄。 人們經常使用if(IsDebugging)使用此目錄,否則使用此目錄。

經過大量的靈魂搜索,我設法收集了足夠的靈感來編寫以下代碼段。 這個想法是使用.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();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM