60 Stimmen

Öffnen einer Datei in Visual Studio an einer bestimmten Zeilennummer

Ich habe ein Dienstprogramm (grep), das mir eine Liste von Dateinamen und Zeilennummern liefert. Nachdem ich festgestellt habe, dass devenv das richtige Programm zum Öffnen einer Datei ist, möchte ich sicherstellen, dass sie an der angegebenen Zeilennummer geöffnet wird. In emacs wäre dies der Fall:

emacs +140 filename.c

Ich habe nichts dergleichen für Visual Studio (devenv) gefunden. Das nächste, was ich gefunden habe, ist:

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

Dadurch wird jedoch für jede dieser Dateien eine eigene Instanz von devenv erzeugt. Ich würde lieber etwas haben, das eine bestehende Instanz verwendet.

Diese Varianten verwenden ein bestehendes devenv, gehen aber nicht bis zur angegebenen Zeile:

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

Ich dachte, dass die Verwendung mehrerer "/Command"-Argumente könnte es tun, aber ich habe wahrscheinlich nicht die richtige, weil ich entweder Fehler oder keine Antwort überhaupt (andere als das Öffnen eines leeren devenv) erhalten.

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

Irgendwelche Ideen?


Nun, es sieht nicht so aus, als gäbe es eine Möglichkeit, dies so zu tun, wie ich es wollte. Da es so aussieht, als bräuchte ich einen eigenen Code, um Visual Studio zu starten, habe ich mich entschieden, EnvDTE wie unten gezeigt zu verwenden. Ich hoffe, dass dies jemand anderem helfen wird.

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

3voto

Diese C#-Abhängigkeiten von Projektreferenzen sind völlig überflüssig. Ein Großteil des Codes hier ist in der Tat übermäßig langatmig. Alles, was Sie brauchen, ist dies.

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

Ganz einfach, oder?

3voto

Mungo64 Punkte 41

Dies ist meine funktionierende C#-Lösung für Visual Studio 2017 (15.9.7)

Für andere VS-Versionen ändern Sie einfach die Versionsnummer (z. B. "VisualStudio.DTE.14.0")

t Verweis hinzufügen->Suche 'envdte'->Kontrollkästchen für envdte ankreuzen->Klick 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());
}

2voto

Evgeny Panasyuk Punkte 8906

Hier ist die VBS-Variante von Harolds Lösung: Link zum .vbs-Skript .

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

Windows unterstützt VBScript von Haus aus - eine Kompilierung oder zusätzliche Interpreter sind nicht erforderlich.

1voto

Dinis Cruz Punkte 3991

Als Referenz finden Sie hier das in C# geschriebene ENVDE (mit O2-Plattform in VisualStudio, um 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 zeigt eine kleine Animation, bei der 20 Zeilen ausgewählt werden (mit einem Intervall von 100 ms)

1voto

Richard Mills Punkte 11

Die richtige wingrep Kommandozeile syntax um eine new instance und zu einer Zeilennummer zu springen, ist:

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

Ersetzen Sie die studio version number mit der richtigen Version für Ihre Einrichtung.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X