最近在爆个插件,有个需求就是能够在Solution Explorer中右键点击某个文件然后做一些下流的操作,那么首先就要想办法得到用户选择的文件或者文件们。肿么搞呢。研究了一下WebEssential的代码,总结了一下:

首先,你需要获得DTE2对象,貌似指的是你当前的VS实例。为了方便使用定义成一个静态属性,放到package类里面:

也就是继承Package类的那个类,比如public sealed class ForeverAlonePackage : Package

private static DTE2 _dte;

internal static DTE2 DTE
{
    get
    {
        if (_dte == null)
            _dte = ServiceProvider.GlobalProvider.GetService(typeof(DTE)) as DTE2;

        return _dte;
    }
}

然后就可以写个助手类,用来获得当前选中的文件(们)了:

///<summary>Gets the full paths to the currently selected item(s) in the Solution Explorer.</summary>
public static IEnumerable<string> GetSelectedItemPaths(DTE2 dte = null)
{
    var items = (Array)(dte ?? 你的PACKAGE类.DTE).ToolWindows.SolutionExplorer.SelectedItems;
    foreach (UIHierarchyItem selItem in items)
    {
        var item = selItem.Object as ProjectItem;

        if (item != null && item.Properties != null)
            yield return item.Properties.Item("FullPath").Value.ToString();
    }
}

至于路径,稍微处理一下就行:

///<summary>Gets the paths to all files included in the selection, including files within selected folders.</summary>
public static IEnumerable<string> GetSelectedFilePaths()
{
    return GetSelectedItemPaths()
        .SelectMany(p => Directory.Exists(p)
                         ? Directory.EnumerateFiles(p, "*", SearchOption.AllDirectories)
                         : new[] { p }
                   );
}

另外,如果要获取选中的项目文件,可以这样:

///<summary>Gets the the currently selected project(s) in the Solution Explorer.</summary>
public static IEnumerable<Project> GetSelectedProjects()
{
    var items = (Array)你的PACKAGE类.DTE.ToolWindows.SolutionExplorer.SelectedItems;
    foreach (UIHierarchyItem selItem in items)
    {
        var item = selItem.Object as Project;

        if (item != null)
            yield return item;
    }
}

获取解决方案(sln)的根目录:

///<summary>Gets the directory containing the active solution file.</summary>
public static string GetSolutionFolderPath()
{
    EnvDTE.Solution solution = 你的PACKAGE类.DTE.Solution;

    if (solution == null)
        return null;

    if (string.IsNullOrEmpty(solution.FullName))
        return GetRootFolder();

    return Path.GetDirectoryName(solution.FullName);
}

这些代码在VS2010 SDK里也能用。