Подтвердить что ты не робот

Откройте файл в Visual Studio с определенным номером строки

У меня есть утилита (grep), которая дает мне список имен файлов и номеров строк. После того, как я определил, что devenv является правильной программой для открытия файла, я хотел бы убедиться, что он открыт с указанным номером строки. В emacs это будет:

emacs +140 filename.c

Я не нашел ничего подобного для Visual Studio (devenv). Самое близкое, что я нашел:

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

Однако это делает отдельный экземпляр devenv для каждого такого файла. Я бы предпочел что-то, что использует существующий экземпляр.

Эти варианты повторного использования существующего devenv, но не идут в указанную строку:

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

Я думал, что использование нескольких аргументов "/Command" может это сделать, но у меня, вероятно, нет правильного, потому что я либо получаю ошибки, либо вообще не отвечаю (кроме открытия пустого devenv).

Я могу написать специальный макрос для devenv, но я бы хотел, чтобы эта утилита использовалась другими, у которых нет этого макроса. И я не понимаю, как вызвать этот макрос с параметром "/Command".

Любые идеи?


Ну, похоже, что есть способ сделать это, как я хотел. Поскольку мне кажется, что мне нужно иметь выделенный код для запуска 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;
}
4b9b3361

Ответ 1

Я не могу найти способ сделать это с помощью прямых параметров командной строки. Похоже, вам придется написать макрос для него. Предположительно, вы можете вызвать их так.

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

Итак, вы можете создать макрос, который принимает имя файла и номер строки, затем открывает файл и переходит в нужное место. Но я не знаю, что вы можете указать флаг одного и того же экземпляра, или нет.

Ответ 2

С VS2008 SP1 вы можете использовать следующую командную строку, чтобы открыть файл в определенной строке в существующем экземпляре:

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

Источник

Ответ 3

Разрабатывая вопрос Гарольда и ответ, я адаптировал решение С++ (которое я впервые принял) к С#. Это намного проще (это моя первая программа на С#!). Нужно просто создать проект, добавить ссылки на "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);      
            }
        }
    }
}

Затем вызывается только openStudioFileLine path_to_file numberOfLine.

Надеюсь, что это поможет!

Ответ 4

На основе ответа reder я опубликовал репозиторий с источником, здесь является двоичным (.net2.0)

Я также добавляю поддержку нескольких версий 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 

Пример использования GrepWin:

VisualStudioFileOpenTool.exe 12 %path% %line%

Ответ 5

Довольно старая нить, но это заставило меня начать, вот и еще один пример. Эта функция AutoHotkey открывает файл и помещает курсор в конкретный столбец rowand.

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

Позвонить с помощью:

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

Вы могли бы перевести его довольно много строк за строкой на VBScript или JScript.

Ответ 6

Ниже приведен вариант VBS решения Гарольда: ссылка на .vbs script.

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

Windows поддерживает VBScript изначально - нет необходимости в компиляции или каких-либо дополнительных интерпретаторах.

Ответ 7

Здесь 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)

Показывает, как перейти к указанной строке строки +.

Ответ 8

Для справки: ENVDE, написанный на С# (используя Платформа O2 в VisualStudio, чтобы получить ссылку на живой объект 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;

Этот код немного анимации, где выбрано 20 строк (с интервалом 100 мс)

Ответ 9

Правильная командная строка wingrep syntax, чтобы заставить new instance и перейти к номеру строки:

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

Замените studio version number на правильную версию для вашей установки.

Ответ 10

Эти зависимости С# от ссылок на проекты совершенно не нужны. Действительно, большая часть кода здесь слишком многословна. Все, что вам нужно, это.

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

Просто, а?

Ответ 11

Я собирался задать этот вопрос, потому что когда вы получаете "желтый экран смерти" при отладке веб-приложения, вы хотите быстро перейти к файлу и строке, которые он дает вам в стеке, например:

[ContractException: Precondition failed: session != null]
   System.Diagnostics.Contracts.__ContractsRuntime.TriggerFailure(ContractFailureKind kind, String msg, String userMessage, String conditionTxt, Exception inner) in C:\_svn\IntegratedAdaptationsSystem\Source\IntegratedAdaptationsSystem\IAS_UI\Controllers\CustomErrorsPageController.cs:0
   System.Diagnostics.Contracts.__ContractsRuntime.ReportFailure(ContractFailureKind kind, String msg, String conditionTxt, Exception inner) in C:\_svn\IntegratedAdaptationsSystem\Source\IntegratedAdaptationsSystem\IAS_UI\Controllers\CustomErrorsPageController.cs:0
   System.Diagnostics.Contracts.__ContractsRuntime.Requires(Boolean condition, String msg, String conditionTxt) in C:\_svn\IntegratedAdaptationsSystem\Source\IntegratedAdaptationsSystem\IAS_UI\Controllers\CustomErrorsPageController.cs:0
   IAS_UI.Web.IAS_Session..ctor(HttpSessionStateBase session) in C:\_svn\IntegratedAdaptationsSystem\Source\IntegratedAdaptationsSystem\IAS_UI\Web\IAS_Session.cs:15
   IAS_UI.Controllers.ServiceUserController..ctor() in C:\_svn\IntegratedAdaptationsSystem\Source\IntegratedAdaptationsSystem\IAS_UI\Controllers\ServiceUserController.cs:41

Скажем, я хочу перейти в ServiceUserController.cs в строке 41. Обычно я открываю Visual Studio и делаю это вручную, но потом я написал немного Autohotkey script, который делает это.

Чтобы открыть его, вы выделите имя файла и номер строки, например. ServiceUserController.cs:41, а затем нажмите кнопку быстрого доступа Alt + v. Вот код для него:

$!v::
if (NOT ProcessExists("devenv.exe"))
{
    MsgBox, % "Visual Studio is not loaded"
}
else
{
    IfWinExist, Microsoft Visual Studio
    {
        ToolTip, Opening Visual Studio...
        c := GetClip()

        if (NOT c) {
            MsgBox, % "No text selected"
        }
        else 
        {
            WinActivate ; now activate visual studio
            Sleep, 50
            ; for now assume that there is only one instance of visual studio - handling of multiple instances comes in later

            arr := StringSplitF(c, ":")

            if (arr.MaxIndex() <> 2) {
                MsgBox, % "Text: '" . c . "' is invalid."
            }
            else {
                fileName := arr[1]
                lineNumber := arr[2]

                ; give focus to the "Find" box
                SendInput, ^d 

                ; delete the contents of the "Find" box
                SendInput, {Home}
                SendInput, +{End}
                SendInput, {Delete}

                ; input *** >of FILENAME *** into the "Find" box
                SendInput, >of{Space}
                SendInput, % fileName

                ; select the first entry in the drop down list
                SendInput, {Down}
                SendInput, {Enter}

                ; lineNumber := 12 remove later

                ; open the go to line dialog
                SendInput, ^g
                Sleep, 20

                ; send the file number and press enter
                SendInput, % lineNumber
                SendInput {Enter}
            }
        }    
        ToolTip
    }
}
return

Перед этим вам нужно вставить следующие "служебные функции":

GetClip()
{
    ClipSaved := ClipboardAll
    Clipboard=
    Sleep, 30
    Send ^c
    ClipWait, 2
    Sleep, 30
    Gc := Clipboard
    Clipboard := ClipSaved
    ClipSaved=

    return Gc
}

ProcessExists(procName)
{
    Process, Exist, %procName%

    return (ErrorLevel != 0)
}

StringSplitF(str, delimeters)
{
    Arr := Object()

    Loop, parse, str, %delimeters%,
    {
        Arr.Insert(A_LoopField)
    }

    return Arr
}

Ответ 12

Использование этой команды работает для меня, если Visual Studio уже не открыта. "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe" /edit "ABSOLUTEFILEPATH_FILENAME.CPP" /команда "Edit.GoTo 164"

Если он уже открыт, то иногда он работает и идет в нужную строку, но затем он просто перестает работать, и я никогда не понял, почему. Похоже, Microsoft знает об этой проблеме, но заявила, что они "не исправит", если больше людей не пожалуются. Поэтому, если это еще проблема, я предлагаю комментировать здесь: https://connect.microsoft.com/VisualStudio/Feedback/Details/1128717

Ответ 13

Это мое рабочее решение С# для Visual Studio 2017 (15.9.7)

Для других версий VS просто измените номер версии (например, "VisualStudio.DTE.14.0")

сделать:   Добавьте Reference-> Поиск 'envdte' → Установите флажок для envdte-> Нажмите OK

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