visual-studio 在 Visual Studio 中以特定行号打开文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/350323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 09:59:15  来源:igfitidea点击:

Open a file in Visual Studio at a specific line number

visual-studiocommand-line

提问by Harold Bamford

I have a utility (grep) that gives me a list of filenames and a line numbers. After I have determined that devenv is the correct program to open a file, I would like to ensure that it is opened at the indicated line number. In emacs, this would be:

我有一个实用程序 (grep),它为我提供了一个文件名列表和一个行号。在确定 devenv 是打开文件的正确程序之后,我想确保它在指定的行号处打开。在 emacs 中,这将是:

emacs +140 filename.c

I have found nothing like this for Visual Studio (devenv). The closest I have found is:

我在 Visual Studio (devenv) 中没有发现任何类似的东西。我找到的最接近的是:

devenv /Command "Edit.Goto 140" filename.c

However, this makes a separate instance of devenv for each such file. I would rather have something that uses an existing instance.

但是,这会为每个此类文件创建一个单独的 devenv 实例。我宁愿拥有使用现有实例的东西。

These variations re-use an existing devenv, but don't go to the indicated line:

这些变体重新使用现有的 devenv,但不要转到指示的行:

devenv /Command "Edit.Goto 140" /Edit filename.c
devenv /Command  /Edit filename.c "Edit.Goto 140"

I thought that using multiple "/Command" arguments might do it, but I probably don't have the right one because I either get errors or no response at all (other than opening an empty devenv).

我认为使用多个“/Command”参数可能会做到这一点,但我可能没有正确的参数,因为我要么收到错误要么根本没有响应(除了打开一个空的 devenv)。

I could write a special macro for devenv, but I would like this utility to be used by others that don't have that macro. And I'm not clear on how to invoke that macro with the "/Command" option.

我可以为 devenv 编写一个特殊的宏,但我希望没有该宏的其他人使用此实用程序。而且我不清楚如何使用“/Command”选项调用该宏。

Any ideas?

有任何想法吗?



Well, it doesn't appear that there is a way to do this as I wanted. Since it looks like I'll need to have dedicated code to start up Visual Studio, I've decided to use EnvDTE as shown below. Hopefully this will help somebody else.

好吧,似乎没有办法按照我的意愿做到这一点。由于看起来我需要专门的代码来启动 Visual Studio,我决定使用 EnvDTE,如下所示。希望这会对其他人有所帮助。

#include "stdafx.h"

//-----------------------------------------------------------------------
// This code is blatently stolen from http://benbuck.com/archives/13
//
// This is from the blog of somebody called "BenBuck" for which there
// seems to be no information.
//-----------------------------------------------------------------------

// import EnvDTE
#pragma warning(disable : 4278)
#pragma warning(disable : 4146)
#import "libid:80cc9f66-e7d8-4ddd-85b6-d9e6cd0e93e2" version("8.0") lcid("0") raw_interfaces_only named_guids
#pragma warning(default : 4146)
#pragma warning(default : 4278)

bool visual_studio_open_file(char const *filename, unsigned int line)
{
    HRESULT result;
    CLSID clsid;
    result = ::CLSIDFromProgID(L"VisualStudio.DTE", &clsid);
    if (FAILED(result))
        return false;

    CComPtr<IUnknown> punk;
    result = ::GetActiveObject(clsid, NULL, &punk);
    if (FAILED(result))
        return false;

    CComPtr<EnvDTE::_DTE> DTE;
    DTE = punk;

    CComPtr<EnvDTE::ItemOperations> item_ops;
    result = DTE->get_ItemOperations(&item_ops);
    if (FAILED(result))
        return false;

    CComBSTR bstrFileName(filename);
    CComBSTR bstrKind(EnvDTE::vsViewKindTextView);
    CComPtr<EnvDTE::Window> window;
    result = item_ops->OpenFile(bstrFileName, bstrKind, &window);
    if (FAILED(result))
        return false;

    CComPtr<EnvDTE::Document> doc;
    result = DTE->get_ActiveDocument(&doc);
    if (FAILED(result))
        return false;

    CComPtr<IDispatch> selection_dispatch;
    result = doc->get_Selection(&selection_dispatch);
    if (FAILED(result))
        return false;

    CComPtr<EnvDTE::TextSelection> selection;
    result = selection_dispatch->QueryInterface(&selection);
    if (FAILED(result))
        return false;

    result = selection->GotoLine(line, TRUE);
    if (FAILED(result))
        return false;

    return true;
}

采纳答案by EndangeredMassa

I can't figure out a way to do this with straight command-line options. It looks like you will have to write a macro for it. Supposedly, you can invoke them like so.

我想不出用直接命令行选项来做到这一点的方法。看起来您必须为它编写一个宏。据说,您可以像这样调用它们。

devenv /command "Macros.MyMacros.Module1.OpenFavoriteFiles"

So, you can probably create a macro that takes a filename and a line number, then opens the file and jumps to the proper place. But, I don't know that you can specify a same-instance flag somewhere, or not.

因此,您可以创建一个带有文件名和行号的宏,然后打开文件并跳转到正确的位置。但是,我不知道您是否可以在某处指定相同实例标志。

回答by Fouré Olivier

With VS2008 SP1, you can use the following command line to open a file at a specific line in an existing instance :

使用 VS2008 SP1,您可以使用以下命令行在现有实例中的特定行打开文件:

devenv /edit FILE_PATH /command "edit.goto FILE_LINE"

Source

来源

回答by reder

Elaborating on Harold question and answer, I adapted the C++ solution (that I first adopted) to C#. It is much simpler (that is my first C# program!). One just need to create a project, add references to "envDTE" and "envDTE80" and drop the following code:

在详细阐述 Harold 问答时,我将 C++ 解决方案(我首先采用的)改编为 C#。它要简单得多(这是我的第一个 C# 程序!)。只需要创建一个项目,添加对“envDTE”和“envDTE80”的引用并删除以下代码:

using System;
using System.Collections.Generic;
using System.Text;

namespace openStudioFileLine
{
    class Program    
    {
        [STAThread]
        static void Main(string[] args)     
        {
            try          
            {
                String filename = args[0];
                int fileline;
                int.TryParse(args[1], out fileline);
                EnvDTE80.DTE2 dte2;
                dte2 = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE");
                dte2.MainWindow.Activate();
                EnvDTE.Window w = dte2.ItemOperations.OpenFile(filename, EnvDTE.Constants.vsViewKindTextView);
                ((EnvDTE.TextSelection)dte2.ActiveDocument.Selection).GotoLine(fileline, true);
            }
            catch (Exception e)          
            {          
                Console.Write(e.Message);      
            }
        }
    }
}

One then just calls openStudioFileLine path_to_file numberOfLine.

一个然后只是调用openStudioFileLine path_to_file numberOfLine

Hope that may help !

希望能有所帮助!

回答by diimdeep

Based on rederanswer I have published repository with source, here is binary(.net2.0)

基于reder 的答案,我发布了带有 source 的存储库这里是 binary(.net2.0)

I also add support for multiple VS versions

我还添加了对多个 VS 版本的支持

usage: <version> <file path> <line number> 

Visual Studio version                 value 
VisualStudio 2002                     2 
VisualStudio 2003                     3 
VisualStudio 2005                     5 
VisualStudio 2008                     8 
VisualStudio 2010                    10 
VisualStudio 2012                    12 
VisualStudio 2013                    13 

Example using from GrepWin:

使用来自 GrepWin 的示例:

VisualStudioFileOpenTool.exe 12 %path% %line%

回答by Wade Hatler

Pretty old thread, but it got me started so here's another example. This AutoHotkeyfunction opens a file, and puts the cursor on a particular rowand column.

很旧的线程,但它让我开始了所以这是另一个例子。这个AutoHotkey函数打开一个文件,并将光标放在特定的行和列上。

; http://msdn.microsoft.com/en-us/library/envdte.textselection.aspx
; http://msdn.microsoft.com/en-us/library/envdte.textselection.movetodisplaycolumn.aspx
VST_Goto(Filename, Row:=1, Col:=1) {
    DTE := ComObjActive("VisualStudio.DTE.12.0")
    DTE.ExecuteCommand("File.OpenFile", Filename)
    DTE.ActiveDocument.Selection.MoveToDisplayColumn(Row, Col)
}

Call with:

致电:

VST_Goto("C:\Palabra\.NET\Addin\EscDoc\EscDoc.cs", 328, 40)

You could translate it pretty much line by line to VBScript or JScript.

您几乎可以将其逐行翻译成 VBScript 或 JScript。

回答by Evgeny Panasyuk

Here is Python variation of Harold's solution:

这是 Harold 解决方案的 Python 变体:

import sys
import win32com.client

filename = sys.argv[1]
line = int(sys.argv[2])
column = int(sys.argv[3])

dte = win32com.client.GetActiveObject("VisualStudio.DTE")

dte.MainWindow.Activate
dte.ItemOperations.OpenFile(filename)
dte.ActiveDocument.Selection.MoveToLineAndOffset(line, column+1)

It shows how to go to specified line + column.

它显示了如何转到指定的行 + 列。

回答by Evgeny Panasyuk

Here is VBS variation of Harold's solution: link to .vbs script.

这是 Harold 解决方案的 VBS 变体:链接到 .vbs 脚本

open-in-msvs.vbs full-path-to-file line column

Windows supports VBScript natively - no need for compilation or any additional interpreters.

Windows 本身支持 VBScript - 无需编译或任何额外的解释器。

回答by OnceUponATimeInTheWest

These C# dependencies on project references are completely unecessary. Indeed much of the code here is overly verbose. All you need is this.

这些对项目引用的 C# 依赖是完全没有必要的。事实上,这里的大部分代码都过于冗长。你只需要这个。

using System.Reflection;
using System.Runtime.InteropServices;

private static void OpenFileAtLine(string file, int line) {
    object vs = Marshal.GetActiveObject("VisualStudio.DTE");
    object ops = vs.GetType().InvokeMember("ItemOperations", BindingFlags.GetProperty, null, vs, null);
    object window = ops.GetType().InvokeMember("OpenFile", BindingFlags.InvokeMethod, null, ops, new object[] { file });
    object selection = window.GetType().InvokeMember("Selection", BindingFlags.GetProperty, null, window, null);
    selection.GetType().InvokeMember("GotoLine", BindingFlags.InvokeMethod, null, selection, new object[] { line, true });
}

Simples eh?

简单吧?

回答by Mungo64

This is my working C# solution for Visual Studio 2017 (15.9.7)

这是我为 Visual Studio 2017 (15.9.7) 工作的 C# 解决方案

For other versions of VS just change the version number (i.e. "VisualStudio.DTE.14.0")

对于其他版本的 VS,只需更改版本号(即“VisualStudio.DTE.14.0”)

todo: Add Reference->Search 'envdte'->Check Checkbox for envdte->Click OK

待办事项: 添加引用->搜索'envdte'->选中envdte的复选框->单击确定

using EnvDTE;        

private static void OpenFileAtLine(string file, int line)
{
    DTE dte = (DTE)  Marshal.GetActiveObject("VisualStudio.DTE.15.0");
    dte.MainWindow.Visible = true;
    dte.ExecuteCommand("File.OpenFile", file);
    dte.ExecuteCommand("Edit.GoTo", line.ToString());
}

回答by Richard Mills

The correct wingrepcommand line syntaxto force a new instanceand jump to a line number is:

强制 a并跳转到行号的正确wingrep命令行是:syntaxnew instance

"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe" $F /command "edit.goto $L"

Replace the studio version numberwith the correct version for your setup.

将 替换studio version number为适合您的设置的正确版本。

回答by Dinis Cruz

For reference here is the ENVDE written in C# (using O2 Platforminside VisualStudio to get a reference to the live DTE object)

作为参考,这里是用 C# 编写的 ENVDE(在 VisualStudio 中使用O2 平台获取对实时 DTE 对象的引用)

var visualStudio = new API_VisualStudio_2010();

var vsDTE = visualStudio.VsAddIn.VS_Dte;
//var document = (Document)vsDTE.ActiveDocument;
//var window =  (Window)document.Windows.first();           
var textSelection  = (TextSelection)vsDTE.ActiveDocument.Selection;
var selectedLine = 1;
20.loop(100,()=>{
                    textSelection.GotoLine(selectedLine++);
                    textSelection.SelectLine();
                });
return textSelection;

This code does a little animation where 20 lines are selected (with a 100ms interval)

这段代码做了一个小动画,其中选择了 20 行(间隔 100 毫秒)