Откройте файл в 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;
}
11 ответов:
Я не могу найти способ сделать это с помощью прямых параметров командной строки. Похоже, вам придется написать макрос для этого. Предположительно, вы можете вызвать их так.
devenv /command "Macros.MyMacros.Module1.OpenFavoriteFiles"таким образом, вы, вероятно, можете создать макрос, который принимает имя файла и номер строки, а затем открывает файл и переходит в нужное место. Но, я не знаю, что вы можете указать флаг того же экземпляра где-то, или нет.
С VS2008 С пакетом обновления 1, вы можете использовать следующую командную строку, чтобы открыть файл в определенной строке в существующем экземпляре:
devenv /edit FILE_PATH /command "edit.goto FILE_LINE"
разрабатывая вопрос и ответ Гарольда, я адаптировал решение 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.надеюсь, что это может помочь !
на основе Редер ответ я опубликовал репозиторий с исходным,вот двоичный файл (. 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%
довольно старый поток, но это заставило меня начать так вот еще один пример. Это 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.
вот вариация VBS решения Гарольда:по ссылке .VBS скрипт.
open-in-msvs.vbs full-path-to-file line columnWindows поддерживает VBScript изначально - нет необходимости в компиляции или каких-либо дополнительных интерпретаторах.
вот вариант 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)он показывает, как перейти к указанной строке + столбец.
для справки вот ENVDE, написанный на C# (используя 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 мс)
правильный
wingrepкомандная строкаsyntaxзаставить anew instanceи перейти к номеру строки:"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe" $F /command "edit.goto $L"заменить
studio version numberС правильной версией для вашей установки.
я собирался задать этот вопрос, потому что когда вы получаете "желтый экран смерти" при отладке веб-приложения, вы хотите быстро перейти к файлу и строке, которую он дает вам в stacktrace, например:
[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, который это делает.
открыть его, вы выделите имя файла и номер строки, например,
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 }
использование этой команды работает для меня, пока Visual Studio еще не открыта. "C:\Program файлы (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.EXE-файл" / "правка" "ABSOLUTEFILEPATH_FILENAME.ЦПП" /команды "изменить.Гото 164"
Если он уже открыт, то иногда он работает и переходит на правильную линию, но потом он просто перестает работать, и я никогда не понимал, почему. Похоже, Microsoft знает об этой проблеме, но сказал, что они "не исправят" его, если больше людей не жалуются. Так если это все еще проблема, я бы предложил комментировать здесь:https://connect.microsoft.com/VisualStudio/Feedback/Details/1128717
Comments