Откройте файл в Visual Studio по определенному номеру строки - PullRequest
52 голосов
/ 08 декабря 2008

У меня есть утилита (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;
}

Ответы [ 12 ]

29 голосов
/ 09 сентября 2010

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

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

Источник

26 голосов
/ 23 мая 2012

Разрабатывая вопрос и ответ Гарольда, я адаптировал решение 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);      
            }
        }
    }
}

Один просто звонит openStudioFileLine path_to_file numberOfLine.

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

13 голосов
/ 05 июля 2013

На основе 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%
3 голосов
/ 26 сентября 2016

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

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

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

3 голосов
/ 22 ноября 2014

Довольно старая ветка, но я начал, так что вот еще один пример. Эта функция 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)
}

Позвонить по номеру:

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

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

2 голосов
/ 20 октября 2015

Вот вариант 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)

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

1 голос
/ 28 января 2016

Правильная 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 верной версией для вашей настройки.

1 голос
/ 15 мая 2012

Для справки здесь ENVDE, написанный на C # (с использованием O2 Platform внутри 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 мс)

0 голосов
/ 25 февраля 2019

Эти зависимости 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, а?

0 голосов
/ 24 июля 2017

Использование этой команды работает для меня, если 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

...