programing tip

Visual Studio에서 특정 줄 번호로 파일 열기

itbloger 2021. 1. 8. 07:55
반응형

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

직접 명령 줄 옵션으로이 작업을 수행하는 방법을 알아낼 수 없습니다. 매크로를 작성해야 할 것 같습니다. 아마도 그렇게 호출 할 수 있습니다.

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

따라서 파일 이름과 줄 번호를 사용하는 매크로를 만든 다음 파일을 열고 적절한 위치로 이동할 수 있습니다. 하지만 어딘가에 동일한 인스턴스 플래그를 지정할 수 있는지 여부는 모르겠습니다.


VS2008 SP1 에서는 다음 명령 줄을 사용하여 기존 인스턴스의 특정 줄에서 파일을 열 수 있습니다.

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

출처


Harold 질문과 답변에 대해 자세히 설명하면서 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.

도움이 될 수 있기를 바랍니다!


reder 답변을 기반으로 소스와 함께 저장소를 게시했습니다 . 여기는 binary (.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%

꽤 오래된 스레드이지만 시작하게되었으므로 여기에 또 다른 예가 있습니다. 오토 핫키 기능은 파일을 열고 커서를 특정 행과 열에 놓습니다.

; 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 솔루션의 VBS 변형입니다. link to .vbs script .

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

Windows는 기본적으로 VBScript를 지원하므로 컴파일이나 추가 인터프리터가 필요하지 않습니다.


다음은 Harold 솔루션의 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)

지정된 행 + 열로 이동하는 방법을 보여줍니다.


참고로 여기에 C #으로 작성된 ENVDE가 있습니다 ( 실시간 DTE 개체에 대한 참조를 얻기 위해 VisualStudio 내부의 O2 플랫폼 사용 ).

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 줄이 선택된 작은 애니메이션을 수행합니다 (100ms 간격).


a를 강제 wingrep실행 하고 줄 번호로 이동하는 올바른 명령 줄 은 다음과 같습니다.syntaxnew instance

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

studio version number설치에 맞는 올바른 버전 으로을 교체하십시오 .


프로젝트 참조에 대한 이러한 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 });
}

단순한 어?


웹 응용 프로그램을 디버깅 할 때 "노란색 화면"이 표시되면 스택 추적에서 제공하는 파일과 줄로 빠르게 이동하기를 원하기 때문에이 질문을하려고했습니다. 예 :

[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

그 앞에 다음 "유틸리티 함수"를 붙여 넣는 것이 좋습니다.

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"/ edit "ABSOLUTEFILEPATH_FILENAME.CPP"/ command "Edit.GoTo 164"

If it is already open, then sometimes it works and goes to the right line, but then it just stops working and I have never figured out why. Looks like Microsoft is aware of the issue but have said they "Will Not Fix" it, unless more people complain. So if it's still an issue I'd suggest commenting here: https://connect.microsoft.com/VisualStudio/Feedback/Details/1128717


This is my working C# solution for Visual Studio 2017 (15.9.7)

For other versions of VS just change the version number (i.e. "VisualStudio.DTE.14.0")

todo: Add Reference->Search 'envdte'->Check Checkbox for envdte->Click 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());
}

ReferenceURL : https://stackoverflow.com/questions/350323/open-a-file-in-visual-studio-at-a-specific-line-number

반응형