gpt4 book ai didi

visual-studio - 如何以编程方式找出解决方案中每个启动项目的操作?

转载 作者:行者123 更新时间:2023-12-04 12:12:05 24 4
gpt4 key购买 nike

在Solution->Properties下,我可以设置多个启动项目:
Solution Properties

我知道我可以获得标有“开始”的项目列表(通过使用 EnvDTE: solution.SolutionBuild.StartupProjects ),但是如何获得操作为“不调试就开始”的项目列表?它们不会出现在列表中。

最佳答案

我不认为这是正式记录和提供的,但这里有一些信息:

  • 这存储在 solution's .SUO file通过 Visual Studio 内置包。 SUO 文件具有 OLE 复合存储格式。您可以使用 OpenMCDF 等工具进行浏览。 (它有一个资源管理器示例)。在此文件中,您将看到一个名为“SolutionConfiguration”的流。 ' 包含一个 dwStartupOpt token ,后跟您要查找的信息。流本身具有自定义二进制格式。
  • 通过 IVsPersistSolutionProps Interface 可以从 VS 中获得相同的信息。 .您需要从一个已加载的包中获取指向它的指针(例如,使用 IVsShell.GetPackageEnum Method 枚举包列表。一个包将支持带有“SolutionConfiguration”流的 IVsPersistSolutionProps 接口(interface)。

  • 但是,无论您选择哪种方法,我相信您最终都会手动解析“SolutionConfiguration”流。我在这里提出了一种方法,它只需打开 SUO 文件并“手动”破解这些位,因此它可以在 VS 之外工作。

    这是解析“SolutionConfiguration”流的实用程序类:
    public sealed class StartupOptions
    {
    private StartupOptions()
    {
    }

    public static IDictionary<Guid, int> ReadStartupOptions(string filePath)
    {
    if (filePath == null)
    throw new ArgumentNullException("filePath");

    // look for this token in the file
    const string token = "dwStartupOpt\0=";
    byte[] tokenBytes = Encoding.Unicode.GetBytes(token);
    Dictionary<Guid, int> dic = new Dictionary<Guid, int>();
    byte[] bytes;
    using (MemoryStream stream = new MemoryStream())
    {
    CompoundFileUtilities.ExtractStream(filePath, "SolutionConfiguration", stream);
    bytes = stream.ToArray();
    }

    int i = 0;
    do
    {
    bool found = true;
    for (int j = 0; j < tokenBytes.Length; j++)
    {
    if (bytes[i + j] != tokenBytes[j])
    {
    found = false;
    break;
    }
    }
    if (found)
    {
    // back read the corresponding project guid
    // guid is formatted as {guid}
    // len to read is Guid length* 2 and there are two offset bytes between guid and startup options token
    byte[] guidBytes = new byte[38 * 2];
    Array.Copy(bytes, i - guidBytes.Length - 2, guidBytes, 0, guidBytes.Length);
    Guid guid = new Guid(Encoding.Unicode.GetString(guidBytes));

    // skip VT_I4
    int options = BitConverter.ToInt32(bytes, i + tokenBytes.Length + 2);
    dic[guid] = options;
    }
    i++;
    }
    while (i < bytes.Length);
    return dic;
    }
    }

    随后是一个小型复合流读取实用程序(不需要外部库):
    public static class CompoundFileUtilities
    {
    public static void ExtractStream(string filePath, string streamName, string streamPath)
    {
    if (filePath == null)
    throw new ArgumentNullException("filePath");

    if (streamName == null)
    throw new ArgumentNullException("streamName");

    if (streamPath == null)
    throw new ArgumentNullException("streamPath");

    using (FileStream output = new FileStream(streamPath, FileMode.Create))
    {
    ExtractStream(filePath, streamName, output);
    }
    }

    public static void ExtractStream(string filePath, string streamName, Stream output)
    {
    if (filePath == null)
    throw new ArgumentNullException("filePath");

    if (streamName == null)
    throw new ArgumentNullException("streamName");

    if (output == null)
    throw new ArgumentNullException("output");

    IStorage storage;
    int hr = StgOpenStorage(filePath, null, STGM.READ | STGM.SHARE_DENY_WRITE, IntPtr.Zero, 0, out storage);
    if (hr != 0)
    throw new Win32Exception(hr);

    try
    {
    IStream stream;
    hr = storage.OpenStream(streamName, IntPtr.Zero, STGM.READ | STGM.SHARE_EXCLUSIVE, 0, out stream);
    if (hr != 0)
    throw new Win32Exception(hr);

    int read = 0;
    IntPtr readPtr = Marshal.AllocHGlobal(Marshal.SizeOf(read));
    try
    {
    byte[] bytes = new byte[0x1000];
    do
    {
    stream.Read(bytes, bytes.Length, readPtr);
    read = Marshal.ReadInt32(readPtr);
    if (read == 0)
    break;

    output.Write(bytes, 0, read);
    }
    while(true);
    }
    finally
    {
    Marshal.FreeHGlobal(readPtr);
    Marshal.ReleaseComObject(stream);
    }
    }
    finally
    {
    Marshal.ReleaseComObject(storage);
    }
    }

    [ComImport, Guid("0000000b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    private interface IStorage
    {
    void Unimplemented0();

    [PreserveSig]
    int OpenStream([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, IntPtr reserved1, STGM grfMode, uint reserved2, out IStream ppstm);

    // other methods not declared for simplicity
    }

    [Flags]
    private enum STGM
    {
    READ = 0x00000000,
    SHARE_DENY_WRITE = 0x00000020,
    SHARE_EXCLUSIVE = 0x00000010,
    // other values not declared for simplicity
    }

    [DllImport("ole32.dll")]
    private static extern int StgOpenStorage([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, IStorage pstgPriority, STGM grfMode, IntPtr snbExclude, uint reserved, out IStorage ppstgOpen);
    }

    以及显示与启动选项相关的项目指南的示例:
    static void SafeMain(string[] args)
    {
    foreach (var kvp in StartupOptions.ReadStartupOptions("mySample.suo"))
    {
    if ((kvp.Value & 1) != 0)
    {
    Console.WriteLine("Project " + kvp.Key + " has option Start");
    }
    if ((kvp.Value & 2) != 0)
    {
    Console.WriteLine("Project " + kvp.Key + " has option Start with debugging");
    }
    }
    }

    关于visual-studio - 如何以编程方式找出解决方案中每个启动项目的操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8817693/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com