2008-12-08 5 views
50

Ich habe ein Dienstprogramm (Grep), die mir eine Liste von Dateinamen und Zeilennummern gibt. Nachdem ich festgestellt habe, dass devenv das richtige Programm zum Öffnen einer Datei ist, möchte ich sicherstellen, dass es unter der angegebenen Zeilennummer geöffnet ist. In emacs wäre dies:Öffnen Sie eine Datei in Visual Studio unter einer bestimmten Zeilennummer

Ich habe nichts dergleichen für Visual Studio (Devenv) gefunden. Die nächstgelegene ich gefunden habe, ist:

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

Dies macht jedoch eine separate Instanz von devenv für jede solche Datei. Ich hätte lieber etwas, das eine existierende Instanz benutzt.

Diese Variationen wiederverwenden eine bestehende devenv, aber gehen Sie nicht auf die angegebene Zeile:

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

Ich dachte, dass mehrere „/ Command“ Argumenten es tun könnte, aber ich wahrscheinlich nicht habe den richtigen, weil ich entweder Fehler oder gar keine Antwort bekomme (außer das Öffnen eines leeren Devenv).

Ich könnte ein spezielles Makro für Devenv schreiben, aber ich möchte dieses Dienstprogramm von anderen verwendet werden, die dieses Makro nicht haben. Und ich bin nicht klar, wie man dieses Makro mit der Option "/ Command" aufrufen kann.

Irgendwelche Ideen?


Nun, es scheint nicht, dass es einen Weg gibt, dies zu tun, wie ich wollte. Da es so aussieht, dass ich zum Starten von Visual Studio dedizierten Code benötigen muss, habe ich beschlossen, EnvDTE wie unten gezeigt zu verwenden. Hoffentlich hilft das jemand anderem.

#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; 
} 
+0

Ehrfürchtig. Also, rufen Sie dies mit "devenv/command Macros.MyMacros.visual_studio_open_file myFile someLineNumber" auf? – EndangeredMassa

+0

Nein, dies ist nur Code, um eine Datei mit einer vorhandenen Devenv-Instanz zu öffnen. Die Idee ist, dass, wenn ich spezialisierten Code haben muss, um die Datei zu öffnen, das ist dieser Code. Entschuldigung, ich habe mich vorher nicht bei Ihnen gemeldet, ich habe gerade Ihren Kommentar bemerkt. –

+3

Ich frage mich, ob jemand eine sauberere Möglichkeit hat, dies ab VS 2010 zu tun? –

Antwort

0

Ich kann keinen Weg finden, dies mit geraden Befehlszeilenoptionen zu tun. Es sieht so aus, als müssten Sie ein Makro dafür schreiben. Angeblich können Sie sie so aufrufen.

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

So können Sie wahrscheinlich ein Makro erstellen, die einen Dateinamen und eine Zeilennummer nimmt, öffnet dann die Datei und springt an die richtige Stelle. Aber ich weiß nicht, dass Sie ein Flag für dieselbe Instanz irgendwo angeben können oder nicht.

+5

Dies löst das Problem nicht wirklich, weil devenv/command eine neue Instanz startet. –

+0

Gar nicht die Lösung. Siehe die richtige Antwort unten, mit einem Beitrag von reder !! –

29

Mit VS2008 SP1, können Sie die folgende Befehlszeile verwenden, um eine Datei zu einer bestimmten Zeile in einer vorhandenen Instanz zu öffnen:

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

Source

+2

Dies funktioniert auch mit VS2010. –

+7

Ich versuchte dies mit keiner laufenden Instanz und es funktionierte - VS2008 startete, öffnete die Datei und ging zur angegebenen Zeile. Ich versuchte es dann auf einer anderen Datei (mit VS2008 läuft noch) und es öffnete die Datei, blieb aber in Zeile 1. Was denken Sie, ist unterschiedlich zwischen unseren Setups? –

+0

Ich habe dies in Vim eingerichtet, und es funktioniert eins zu zehn Mal. VS2010 –

1

Als Referenz ist hier der ENVDE geschrieben in C# (mit O2 Platform innerhalb Visual Studio einen Verweis auf das Live-DTE-Objekt zu erhalten)

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; 

Dieser Code macht eine kleine Animation, wo 20 Zeilen ausgewählt sind (mit einem 100ms Intervall)

24

Auf Harold Frage und Antwort ausarbeitend, passte ich die C++ Lösung (die ich zuerst annahm) an C# an. Es ist viel einfacher (das ist mein erstes C# -Programm!).Man braucht nur ein Projekt zu erstellen, fügen Sie Verweise auf „EnvDTE“ und „EnvDTE80“ und legen Sie den folgenden Code:

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

man dann openStudioFileLine path_to_file numberOfLine gerade anruft.

Hoffe, dass kann helfen!

+0

Wunderbar! Ich musste "VisualStudio.DTE.9.0" einstellen, um es zum Laufen zu bringen (es wirft mir eine COMException mit Nachricht MK_E_UNAVAILABLE andernfalls) –

+0

Vielleicht passen Sie Ihren Code an, um Datei ohne Pfadnamen zu öffnen, der Teil eines geöffneten Projektes ist (Pfad sollte sein von Projektdaten abgezogen)? Und durch folgende Eingabe: FILENAME: LINE_NUM. Dieses Format ist in der Unix-Welt weit verbreitet. Idealerweise sollte es einen interaktiven Befehl geben, wie Strg + G, der zu LINE_NUM springt, aber es sollte auch zu einer anderen Datei springen, wenn der "FILENAME:" Teil geliefert wird – midenok

12

Basierend auf reder Antwort, die ich repository with source veröffentlicht haben, here is binary(.net2.0)

ich auch

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 

Beispiel für die Verwendung von grepWin Unterstützung für mehrere VS-Versionen hinzuzufügen:

VisualStudioFileOpenTool.exe 12 %path% %line% 
+0

Schöner Schritt, der es auf vielen Versionen funktioniert und auf github gehostet wird. Seltsamerweise funktioniert es aber nicht in den interessanten Fällen. Es funktioniert, wenn es vom Debugger ausgeführt wird, nicht von der Befehlszeile oder FxCop. VS2010, Win7. –

+0

Sie sind herzlich eingeladen, es besser zu machen! :) – diimdeep

+1

Vielen Dank. In meinen Qt-Anwendungen habe ich einen Logger, der die Quelldatei/Zeilennummer jedes Log-Eintrags aufzeichnet. Mit diesem Code kann ich jetzt eine Schaltfläche auf dem Logger-Widget hinzufügen, um zu der Zeile in Visual Studio zu springen. – drescherjm

0

Ich wollte gerade fragen, Diese Frage, weil, wenn Sie den "gelben Bildschirm des Todes" beim Debuggen einer Webanwendung erhalten, möchten Sie quickl geht y auf die Datei und Zeile, gibt es Ihnen in der Stacktrace zB:

[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 

sagen, dass ich 41 bis ServiceUserController.cs in Zeile gehen will Normalerweise würde ich Visual Studio öffnen und manuell tut es aber dann schrieb ich ein kleines Autohotkey-Skript, das es tut.

Um es zu öffnen, markieren Sie den Dateinamen und die Zeilennummer z. ServiceUserController.cs:41 und danach drücken Sie die Tastenkombination Alt + v. Hier ist der Code für sie:

$!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 

Sie möchten die folgenden „Utility-Funktionen“, bevor es einzufügen:

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 
} 
3

recht alten Thread, aber es hat mich ein weiteres Beispiel hier ist also gestartet. Diese AutoHotkey Funktion öffnet eine Datei und setzt den Cursor auf eine bestimmte Zeile und Spalte.

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

Anruf mit:

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

Sie es ziemlich Zeile für Zeile zu VBScript oder JScript übersetzen könnte.

2

Hier ist Python Variation von Harold Lösung:

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) 

Es zeigt, wie auf bestimmte Zeile + Spalte gehen.

1

Die richtige wingrep Befehlszeile syntax ein new instance und springt zu einer Zeilennummer zu zwingen:

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

für Ihr Setup der studio version number mit der richtigen Version ersetzen.

3

Hier ist VBS Variante der Harold-Lösung: link to .vbs script.

Windows unterstützt VBScript nativ - keine Kompilierung oder zusätzliche Interpreter erforderlich.

+0

Ich versuche, eine Datei zu öffnen und ein Schlüsselwort zu finden. 'dte.ExecuteCommand" Edit.Find "," ID = "" label1 "" "' funktioniert nicht, da VS "Der folgende angegebene Text als nicht gefunden: ID = label1" lautet. Es scheint, die Zitate werden geschluckt. Weißt du, warum? – Gqqnbig

+0

@LoveRight Ich bin mir nicht sicher, worauf Sie sich beziehen. Skript auf Link hat keinen "ExecuteCommand". –

0

Die Verwendung dieses Befehls funktioniert für mich, solange Visual Studio nicht bereits geöffnet ist. "C: \ Program Files (x86) \ Microsoft Visual Studio 14.0 \ Common7 \ IDE \ devenv.exe"/edit "ABSOLUTEFILEPATH_FILENAME.CPP"/command "Edit.GoTo 164"

Wenn es bereits geöffnet ist, dann manchmal funktioniert es und geht zur richtigen Linie, aber dann hört es einfach auf zu arbeiten und ich habe nie herausgefunden warum. Es sieht so aus, als wäre Microsoft sich des Problems bewusst, aber sie haben gesagt, dass sie es nicht reparieren werden, es sei denn, mehr Leute beschweren sich. Also, wenn es immer noch ein Problem ist, würde ich empfehlen, hier zu kommentieren: https://connect.microsoft.com/VisualStudio/Feedback/Details/1128717

Verwandte Themen