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

Visual studio 如何以编程方式找出解决方案中每个启动项目的操作?,visual-studio,vsx,envdte,visual-studio-sdk,Visual Studio,Vsx,Envdte,Visual Studio Sdk,在解决方案->属性下,我可以设置多个启动项目: 我知道我可以获得标有“开始”的项目列表(通过使用EnvDTE:solution.SolutionBuild.StartupProjects),但如何获得其操作为“开始而不调试”的项目列表?它们没有出现在列表中。我认为这没有正式记录和提供,但以下是一些信息: 这由Visual Studio内置包存储在中。SUO文件具有OLE复合存储格式。您可以使用以下工具浏览它(它有一个资源管理器示例)。在该文件中,您将看到一个名为“SolutionConfig

在解决方案->属性下,我可以设置多个启动项目:


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

我认为这没有正式记录和提供,但以下是一些信息:

  • 这由Visual Studio内置包存储在中。SUO文件具有OLE复合存储格式。您可以使用以下工具浏览它(它有一个资源管理器示例)。在该文件中,您将看到一个名为“
    SolutionConfiguration
    ”的流,其中包含一个dwStartupOpt令牌,后跟您要查找的信息。流本身具有自定义的二进制格式

  • 同样的信息也可以从VS内部通过获得。您需要从加载的包之一获取指向它的指针(例如,使用枚举包列表)。一个包将支持带有'
    SolutionConfiguration
    '流的IVsPersistSolutionProps接口

但是,无论您选择什么方法,我相信您最终都会手动解析“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;
    }
}
以及显示与启动选项关联的项目GUID的示例:

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");
        }
    }
}

你的语言是什么?你是在开发一个VS软件包?一个VS插件?还是一些VS工具的外部工具?@SimonMourier用C编写一个VS软件包?我创建了一个感谢!我尝试将它作为一个外部应用程序运行,它起了作用,但如果我更改设置并再次运行它,我仍然会得到旧的值-直到我关闭解决方案,此时看起来VS writes到SUO,然后重新运行它会给我新的值。使用IVsPersistSolutionProps会解决这个问题吗?如果不会,您是否知道有什么方法可以强制Visual Studio写入.SUO?您需要保存解决方案以确保SUO更改提交此解决方案对于完整框架非常有效,但对于紧凑框架似乎不起作用.
BitConverter.ToInt32(bytes,i+tokenBytes.Length+2)
对于所有guid都是0。有什么解决方法可以让compact framework工作吗?@user678229-您应该询问另一个question@SimonMourier我已经在这里发布了答案,它是基于您的解决方案的,没有什么变化。谢谢您的指导。。
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");
        }
    }
}