在Visual Studio中打开一个特定行号的文件

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

emacs +140 filename.c 

我没有发现这样的Visual Studio(devenv)。 我发现的最接近的是:

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

但是,这会为每个这样的文件创build一个单独的devenv实例。 我宁愿有一些使用现有的实例。

这些变化重新使用现有的devenv,但不要去指定的行:

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

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

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

有任何想法吗?


好吧,似乎没有办法像我想的那样去做。 由于看起来我需要专用的代码来启动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; } 

我想不出用直接的命令行选项来做到这一点的方法。 它看起来像你将不得不写一个macros。 据说,你可以像这样调用它们。

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

所以,你可能会创build一个macros,它需要一个文件名和一个行号,然后打开文件并跳转到适当的位置。 但是,我不知道你可以指定一个相同的实例标志的地方,或不。

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

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

资源

在Harold的问答中,我将C ++解决scheme(我最初采用的方法)改编为C#。 这是更简单的(这是我的第一个C#程序!)。 只需要创build一个项目,添加对“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

希望可以帮助!

基于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% 

很老的线程,但它让我开始,所以这里是另一个例子。 此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。

下面是Harold解决scheme的VBS变体: 链接到.vbs脚本 。

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

Windows本机支持VBScript – 不需要编译或任何额外的解释器。

这里的参考是用C#编写的ENVDE(使用VisualStudio中的O2 Platform来获得对现场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; 

这段代码做了一些animation,其中20行被选中(间隔100ms)

下面是Harold解决scheme的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) 

它显示如何去指定的行+列。

正确的wingrep命令行syntax强制一个new instance并跳转到一个行号是:

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

用您的设置的正确版本replacestudio version number

我正要问这个问题,因为当debugging一个Web应用程序时,当你看到“死亡的黄色屏幕”时,你想要快速的到达它在堆栈跟踪中的文件和行,例如:

 [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 

假设我想要到第41行的ServiceUserController.cs。通常我会打开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 

您需要在它之前粘贴以下“实用function”:

 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 Files(x86)\ Microsoft Visual Studio 14.0 \ Common7 \ IDE \ devenv.exe”/编辑“ABSOLUTEFILEPATH_FILENAME.CPP”/命令“Edit.GoTo 164”

如果它已经打开了,那么有时候它会工作并且走向正确的路线,但是它只是停止工作,我从来没有想过为什么。 看起来像微软意识到这个问题,但已经表示,他们“不会修复”它,除非有更多的人抱怨。 所以,如果这仍然是一个问题,我build议在这里评论: https : //connect.microsoft.com/VisualStudio/Feedback/Details/1128717