返回首页


{S0}简介
现代解决方案包含几十甚至远远超过上百个项目,每个项目数百个文件组成。东方自己是很难在这样的空间。这是正常的,如果你是从项目的开始 - 你知道的每一个历史的和你掌握的很大一部分包含的文件。但它是另一回事,如果你是一个具有10年历史的项目新手。由于某种原因,微软还没有提供facilty搜索解决方案资源管理器树。
有一些方法来处理这​​种情况。其一是使用工具/ Visual Studio的原始特征:根据"解决方案资源管理器中跟踪活动项"Options... /项目和解决方案/总,在CPP代码的类型,是这样的:#包括"file.cppquot ,然后点击鼠标右键并选择"打开quot; file.cppquot;文件"从上下文菜单中的项目。但做什么,如果你是NET开发人员,和VS汽车项目跟踪的嗡嗡声,有时(no! - 不幸的是,合适的字是"常"在巨大的解决方案与数万项的情况下)。
此包允许项目在解决方案资源管理器搜索。发现某个项目时,默认操作执行(相同的,如果你双击一个项目,在解决方案资源管理器窗口)。此外,包建立一个额外的菜单项,打开文件的上下文菜单(源文件),在各自的UI项目的位置,在解决方案资源管理器树。
Visual Studio SDK中提供了一个对象的数量扩展的基本功能。此文章是专门讨论如何创建一个Visual Studio集成包(C#/菜单命令)的方法。这不是一个演练和它的想法,你有一个关于VS包的基本知识。在这里,我只是提供了我的很多时间,要解决的事情短的注释工作代码(安装)。
你可以在MSDN找到很多文档和教程,使用的Visual Studio软件开发工具包(SDK)"搜索条款。背景
编译和运行所提供的代码,你必须有您的计算机安装了Visual Studio SDK(我用我的电脑VsSDKFebruary2007,它的工作原理VS2005和VS2008以及)。如果你只想得到描述的功能,您可以下载MS安装程序。
作为一个包的基础上,我使用Visual Studio SDK中提供的示例:Example.SolutionHierarchyTraversal。 (和许多其他样本)位于$(程序文件)\ Visual Studio SDK中\(版本)\ VisualStudioIntegration \ SAMPLES。解决方案
MSDN教程帮助创建VS包。很清楚,但我花了很多时间,知道在那里我可以得到菜单和子菜单中的常量的名称,更重要的是 - 在这里我可以得到菜单组中的常​​量的名称(所有命令都必须属于某个团体)。 VS存储菜单层次结构,在反恐委员会的文件。ShellCmdDef.ctcShellCmdPlace.ctcSharedCmdDef.ctc SharedCmdPlace.ctc
它们分别位于(程序文件)\ Visual Studio SDK中\(版本)\ VisualStudioIntegration \ COMMON \公司如果你想在某些地方在VS的命令,你应该找到这已经是在上述文件中有一个命令。然后,您创建的菜单组绑定到同一个组。要小心,出现的菜单命令坚实的字符串,但真正的文本代码包含一个"放大器";在中间的按钮标题,(但不强调)。

我遇到的第一混乱,存在着两种类型的解决方案层次:IVsHierarchy和UIHierarchy。首先是"自然"的层次结构,列举了解决方案对象。二是用户界面的层次结构,代表在解决方案资源管理器"窗口的树。好消息是,从微软的家伙优化的用户界面,如果你没有看到在解决方案资源管理器树(它是位于内倒塌的父节点)的节点,VS不为它分配内存)。例如,如果你有8K的文件,只有"选定"的UI层次结构中各自的项目。坏消息是,你不能旅行超过UIHierarchyItem,意图找到一个感兴趣的项目,因为,你有没有发现在UI层次结构中的项目的事实并不意味着它不存在的,这意味着,可能只是不会被加载到内存中。所以,你必须旅行过"真正的"解决方案层次结构中的对象,但没有一个方法来获得各自的UI项目使用真实的项目。要做到这一点,这是第一招。
我使用的方法,从上面的例子中,在分层次的项旅游:

private bool FindItemInHierarchy(ref List<string> clew, string match, 

        IVsHierarchy hierarchy, uint itemid, int recursionLevel, 

        bool hierIsSolution, bool visibleNodesOnly)

{

    Boolean isTermination;

    lock(workerManager)

    {

        isTermination = workerManager.IsTermination;

    }

    if (isTermination)

    {

        return false;

    }



    int hr;

    IntPtr nestedHierarchyObj;

    uint nestedItemId;

    Guid hierGuid = typeof(IVsHierarchy).GUID;



    hr = hierarchy.GetNestedHierarchy(itemid, ref hierGuid, 

                   out nestedHierarchyObj, out nestedItemId);

    if (VSConstants.S_OK == hr && IntPtr.Zero != nestedHierarchyObj)

    {

        IVsHierarchy nestedHierarchy = 

          Marshal.GetObjectForIUnknown(nestedHierarchyObj) 

          as IVsHierarchy;

        // we are responsible to release

        // the refcount on the out IntPtr parameter

        Marshal.Release(nestedHierarchyObj);

        if (nestedHierarchy != null)

        {

            // Display name and type of the node in the Output Window

            //if (

            FindItemInHierarchy(

                ref clew, match, nestedHierarchy, nestedItemId, 

                    recursionLevel, false, visibleNodesOnly);

            //)

            //{

                //return true;

            //}



            if (workerManager.IsTermination)

            {

                return false;

            }

        }

    }

    else

    {

        object pVar;



        //Get the name of the root node in question

        //here and push its value to clew

        hr = hierarchy.GetProperty(itemid, 

                (int)__VSHPROPID.VSHPROPID_Name, out pVar);



        clew.Add((string)pVar);



        if (match.Length > 0)

        {

            //If we find match, terminate node enumerating

            if (Regex.Match(match, clew[clew.Count - 1], 

                  RegexOptions.IgnoreCase).Value != String.Empty)

            {

                SelectUIHItemAndWait(clew);

                

                if (workerManager.IsTermination)

                {

                    return false;

                }

                

                //return true;

            }

        }

        else

        {

            // suppose this is just request for all items in solution

        }



        ++recursionLevel;



        hr = hierarchy.GetProperty(itemid,

            ((visibleNodesOnly || (hierIsSolution && recursionLevel == 1) ?

                (int)__VSHPROPID.VSHPROPID_FirstVisibleChild : 

                (int)__VSHPROPID.VSHPROPID_FirstChild)), out pVar);

        Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr);

        if (VSConstants.S_OK == hr)

        {

            //We are using Depth first search so at each level

            //we recurse to check if the node has any children

            //and then look for siblings.

            uint childId = GetItemId(pVar);

            while (childId != VSConstants.VSITEMID_NIL)

            {

                //if (

                FindItemInHierarchy(

                    ref clew, match, hierarchy, childId, 

                    recursionLevel, false, visibleNodesOnly);

                //)

                //{

                    //return true

                //}



                if (workerManager.IsTermination)

                {

                    return false;

                }



                hr = hierarchy.GetProperty(childId,

                    ((visibleNodesOnly || (hierIsSolution && recursionLevel == 1)) ?

                        (int)__VSHPROPID.VSHPROPID_NextVisibleSibling : 

                        (int)__VSHPROPID.VSHPROPID_NextSibling),

                    out pVar);

                if (VSConstants.S_OK == hr)

                {

                    childId = GetItemId(pVar);

                }

                else

                {

                    Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(hr);

                    break;

                }

            }

        }



        if (match.Length > 0)

        {

            clew.RemoveAt(clew.Count - 1);

        }

    }



    return false; //node is not found in current hierarchy

}

我改变了原生的工作方法,执行匹配:{C}
因此,我们可以键入任何正则​​表达式在解决方案资源管理器树中找到的东西。 "事"可能是一个项目,文件夹,源文件,或任何出现在解决方案资源管理器树中的项目。
真正的项目和UI项,将有一个名字和一个平等的祖先层次结构。而且,它是可以选择的UI项目,通过使用以下方法:
UIHierarchyItem GetItem (

    [InAttribute] string Names

)

名称包含为了从根,导致随后的子节点的名称。数组中的最后一个名字是作为一个UIHierarchyItem对象返回的节点。
再次,从微软的家伙为你一个惊喜。如果确定的路径节点UI层次结构中不存在通过优化,它不会。通过UI层次结构中的父节点扩展中,您必须强制它的存在。再有隐患,因为它首先看起来像一个简单的任务。
UIHierarchyItems.Expanded Property

正如MSDN说,设置或获取是否在层次结构中的节点是展开的。获取...也许,但不设置。编译和运行代码。但价值不会改变后,你必须分配一些值。它不扩大和所有。此外,它不改变它的值"真"。我花了很多时间来确定'为什么'。这似乎只是一个错误,MS不希望在VS版本修复版本。
解决方案是在每个路由节点有趣的节点来模拟用户点击。您可以执行此使用这对UIHierarchyItem.Select:(vsUISelectionType.vsUISelectionTypeSelect) - 选择节点,并UIHierarchy.DoDefaultAction() - 扩大在解决方案资源管理器窗口的层次结构中当前选中的节点。完整的代码如下:
private void SelectUIHItem(List<string> nodesTree)

{

    // Get an instance of the currently running Visual Studio IDE.

    DTE dte;

    DTE2 dte2;



    dte = (DTE)GetService(typeof(DTE));

    dte2 = dte as DTE2;



    if (null == dte2)

        return;



    UIHierarchy UIH = dte2.ToolWindows.SolutionExplorer;

    UIHierarchyItem UIHItem;// = UIH.GetItem(path);

    StringBuilder path = new StringBuilder();



    for (int i = 0; i < nodesTree.Count; ++i)

    {

        if (i > 0)

        {

            path.Append('\\');

        }

        path.Append(nodesTree[i]);



        UIHItem = UIH.GetItem(path.ToString());

        UIHItem.Select(vsUISelectionType.vsUISelectionTypeSelect);



        if (!UIHItem.UIHierarchyItems.Expanded)

        {

            UIH.DoDefaultAction();

        }



    }

}

这是一个小窍门。
在旅行节点中,我使用列表中的每一个跟踪的路径。当我来到下一层,我一个项目添加到列表。当我去一个级别,我从列表中删除最后一个项目。这是像穿越迷宫的线索。出于这个原因,Listlt; stringgt;被评为提示。
我们有匹配的节点,我们有充分的路径,所以我们可以选择"点击"的方法,我在上面描述。这是第一招。
在这一点上,我们有办法找到第一个匹配。在早期版本中,找到第二,第三,第四,等等,火柴,我只是一个整数参数,告诉多少场比赛,它是必要的跳过的方法调用相同的旅行。所以每次用户启动"查找下一个"任务,该系统已开始从一开始所有的工作。我这样做是因为我不知道如何恢复状态的递归调用(递归执行搜索,遍历当前节点的每个孩子,每个孩子,每个孩子,等等)。我不知道如何做到这一点,即使在C更托管的C#。
我得到了一个新的想法,当我解决了一个完全无关的任务。我使用的线程。所以我决定等待恢复交换。的思路是:在一个单独的线程中执行搜索,发现项目时,工作线程睡着了;如果用户继续搜索,在UI线程恢复工作线程。
下面的方法处理在解决方案资源管理器中的树中找到的东西:
private void MenuItemFindItemInSlnExplorer(object sender, EventArgs e)

{

    //Get the solution service so we can traverse 

    //each project hierarchy contained within.

    IVsSolution solution = 

       (IVsSolution)GetService(typeof(SVsSolution));

    if (null != solution)

    {

        IVsHierarchy solutionHierarchy = solution as IVsHierarchy;

        if (null != solutionHierarchy)

        {

            if (null == dlg)

            {

                dlg = new FormFindInSlnExplorer();



                ... //init dialog

            }

            //dead worker is the same as worker is absent

            if (null != workerManager.Worker && 

                 false == workerManager.Worker.IsAlive)

            {

                workerManager.Worker = null;

            }

            

            System.Windows.Forms.DialogResult findDlgResult = dlg.ShowDialog();

            if (System.Windows.Forms.DialogResult.OK == 

                 findDlgResult && dlg.ItemToFind.Length > 0)

            {

                if (null != workerManager.Worker)

                {

                    lock (workerManager)

                    {

                        workerManager.IsTermination = true;

                    }

                    //resume working thread

                    workerManager.Worker.Resume();

                    //wait until working thread terminated

                    workerManager.Worker.Join();

                }



                StartSearchThread();

            }

            else if (System.Windows.Forms.DialogResult.Retry == findDlgResult)

            {

                if (null != workerManager.Worker)

                {

                    workerManager.Worker.Resume();

                    //resume working thread

                }

                else

                {

                    //if there was no searching before 

                    //we consider that 'find' button was pushed

                    StartSearchThread();

                }

            }

        }

    }

}



/// Starts search thread

private void StartSearchThread()

{

    lock (workerManager)

    {

        workerManager.Worker = new Std.Thread(new Std.ThreadStart(DoSearch));

        workerManager.Worker.Start();

    }

}

下面的方法使用一个工作线程执行并开始搜索:
/// Search method

private void DoSearch()

{

    //Get objects again

    IVsSolution solution = (IVsSolution)GetService(typeof(SVsSolution));

    if (null == solution)

    {

        return;

    }

    IVsHierarchy solutionHierarchy = solution as IVsHierarchy;

    if (null == solutionHierarchy)

    {

        return;

    }



    //Search recursively

    List<string> clew = new List<string>();

    // used for path tracking



    if(!FindItemInHierarchy(

            ref clew, dlg.ItemToFind, solutionHierarchy, 

            VSConstants.VSITEMID_ROOT, 0, true, false)

        && !workerManager.IsTermination)

    {

        ShowMessageBox("Item not found");

        //see implementation in source codes

    }

    

    //terminate termination

    lock (workerManager)

    {

        workerManager.IsTermination = false;

    }

}

私人BOOL FindItemInHierarchy(REF Listlt; stringgt;提示,字符串匹配,IVsHierarchy层次结构,UINT ITEMID,recursionLevel INT,hierIsSolution BOOL,BOOL visibleNodesOnly)出现以上。
下面是执行的UI项目的选择和部队当前线程睡眠的方法:
private void SelectUIHItemAndWait(List<string> nodesTree)

{

    SelectUIHItem(nodesTree);

    Std.Thread.CurrentThread.Suspend();

}

要在一个单独的线程,而不是恢复状态,当找到一个匹配的搜索代码是第二招。其实,我利用一对:挂起/恢复,而不是其他一些微软推荐的方法,因为他们只说"糟糕的代码",或"过时",但没有提供任何可以理解的替代品。

接下来的任务是在解决方案资源管理器中选择当前打开的文档。正如我刚才说,你可以检查"追踪活动项目在解决方案资源管理器"选项nder工具/ Options... /项目和解决方案/总实现同样的效果。正如我早些时候说,它可能会导致一个时髦。
解决方案是未来的父从相对的ProjectItem,装配在全节点的路径的名称。然后,我们只是选择的节点,使用这个熟悉的函数:
private void MenuItemSyncItemWithSlnExplorer(object sender, EventArgs e)

{

    // Get an instance of the currently running Visual Studio IDE.

    DTE dte;

    DTE2 dte2;



    dte = (DTE)GetService(typeof(DTE));

    dte2 = dte as DTE2;



    if (null == dte2)

    {

        return;

    }



    Document activeDocument = dte2.ActiveDocument;

    if (null == activeDocument)

    {

        return;

    }



    dte.SuppressUI = false;



    List<string> clew = new List<string>();

    object item = activeDocument.ProjectItem; ;



    while (null != item)

    {

        clew.Insert(0, GetNameProperty(item));

        item = GetNextParent(item);

    }



    clew.Insert(0, 

     dte2.ToolWindows.SolutionExplorer.UIHierarchyItems.Item(1).Name);



    SelectUIHItem(clew);



    dte.SuppressUI = true;

}

这招是另一种形式的第一招。
的代码进行了测试,在XP和Vista与Visual Studio 2005和Visual Studio 2008。我希望微软添加此功能的VS版本十。
的源代码是3岁。事实上,为VS2005的插件,因为我开始在C#代码。因此,宽容有关的代码质量。通过这篇文章,我曾试图给读者带来思想。文章写于2009年12月24日。

回答

评论会员:会员3915525 时间:2012/01/25
这个软件包没有工作,2008年与VC

请勿下载
评论会员:会员3915525 时间:2012/01/25
这包不工作
评论会员:jake072 时间:2012/01/25
试图通过SETUP.EXE newSetup.msi安装。无论是在失败的结果。
"安装程序遇到意外的错误安装此软件包,这可能表明此软件包有问题。错误代码是2869。"
叶的目录结构,目录中的下列文件。
DevenvSetupCustomAction.InstallState
TBD27A8.tmp

VS 2008专业版的Windows 7 X86,

只是想知道,你为什么会后的解决方案,如果你到社会的发展,只要你说... ...我不想让你的安装。我想插件=)
评论会员:Roman_K 时间:2012/01/25
我已经发布链接到解决方案... ...其实不大,你发现这"文章错误"感谢 - 我删除链接到解决方案的来源,而不是"坏设置"先前{ S3}

此设置不会在Windows 7下(任何CPU)进行测试。我只是没有之一。它仅仅是一个计划安装。因此,尝试部署使用自己的手来源。觉得免费送我任何问题通过电子邮件

感谢收看
评论会员:jake072 时间:2012/01/25
任何机会,你可以分配一个固定的安装程序,或包括所需的项目?
我的VS 2008,并没有2005年或2005年的SDK,所以我不能建立或安装项目。


杰克
评论会员:jake072 时间:2012/01/25
我试图修改源VS2008的,并得到了它来编译... ...我尝试使用所产生的安装程序包,但似乎没有发生。它安装了,但是当我启动VS 2008中,有没有找到解决方案资源管理器=(...{ BR}
所以,我试图提供的安装在各种兼容模式运行,始终得到错误代码2869。
失败安装
我渴望得到这个功能,但我买不起像ReSharper的软件来实现这一功能。我认为这个问题是从MSI运行devenv的失败,因为运行devenv的不具有管理员权限。我已经试过所有安装此庄园;任何方式,你可以帮助呢?有什么我应该做的我转换后的代码得到它的工作吗?我没有看到一个像你描述的菜单项

非常感谢,

杰克
评论会员:Roman_K 时间:2012/01/25
喜杰克,

VS安装包实在是刺在矿方...我没有包,但也有很多头痛与安装。结果,我聘请一个人花了几十个小时创建VS2k5/XP和VS2k8/Vista的设置。
最大在这种情况下,我能做些什么,是给你​​他的联系。
我不知道为什么微软没有那么难。

罗马
评论会员:苏雷什suthar 时间:2012/01/25
嘿伙计!多数民众赞成我完全搜索....{ BR}*****从我... {S4}的
我无法安装的设置,它给我的打击显示错误:无法找到应用程序文件"newSetup.msi"。请参阅安装程序日志文件位于"C:\ DOCUME〜1 \ ADMINI〜1 \ LOCALS〜1 \ TEMP \ VSD28.tmp \ install.log"的更多信息。

鹰,天空是你的。上周五,12月25日,修改2009年1:03
评论会员:Roman_K 时间:2012/01/25
我有更新的setup.exe。再次尝试。如果错误叶片,请给我发送错误文本和/或电子邮件日志文件:(一)ceasor yandex.ru
感谢阅读,

修改上周五,12月25日,2009上午10:12