Open a file in Visual Studio at a specific line number

Visual StudioCommand Line

Visual Studio Problem Overview


I have a utility (grep) that gives me a list of filenames and a line numbers. After I have determined that devenv is the correct program to open a file, I would like to ensure that it is opened at the indicated line number. In emacs, this would be:

emacs +140 filename.c

I have found nothing like this for Visual Studio (devenv). The closest I have found is:

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

However, this makes a separate instance of devenv for each such file. I would rather have something that uses an existing instance.

These variations re-use an existing devenv, but don't go to the indicated line:

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

I thought that using multiple "/Command" arguments might do it, but I probably don't have the right one because I either get errors or no response at all (other than opening an empty devenv).

I could write a special macro for devenv, but I would like this utility to be used by others that don't have that macro. And I'm not clear on how to invoke that macro with the "/Command" option.

Any ideas?


Well, it doesn't appear that there is a way to do this as I wanted. Since it looks like I'll need to have dedicated code to start up Visual Studio, I've decided to use EnvDTE as shown below. Hopefully this will help somebody else.

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

Visual Studio Solutions


Solution 1 - Visual Studio

With VS2008 SP1, you can use the following command line to open a file at a specific line in an existing instance :

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

Source

Solution 2 - Visual Studio

Elaborating on Harold question and answer, I adapted the C++ solution (that I first adopted) to C#. It is much simpler (that is my first C# program!). One just need to create a project, add references to "envDTE" and "envDTE80" and drop the following 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);      
            }
        }
    }
}

One then just calls openStudioFileLine path_to_file numberOfLine.

Hope that may help !

Solution 3 - Visual Studio

Based on reder answer I have published repository with source, here is binary(.net2.0)

I also add support for multiple VS versions

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 

Example using from GrepWin:

VisualStudioFileOpenTool.exe 12 %path% %line%

Solution 4 - Visual Studio

Pretty old thread, but it got me started so here's another example. This AutoHotkey function opens a file, and puts the cursor on a particular rowand column.

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

Call with:

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

You could translate it pretty much line by line to VBScript or JScript.

Solution 5 - Visual Studio

Here is Python variation of Harold's solution:

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)

It shows how to go to specified line + column.

Solution 6 - Visual Studio

Here is VBS variation of Harold's solution: link to .vbs script.

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

Windows supports VBScript natively - no need for compilation or any additional interpreters.

Solution 7 - Visual Studio

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

Solution 8 - Visual Studio

For reference here is the ENVDE written in C# (using O2 Platform inside VisualStudio to get a reference to the live DTE object)

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;

This code does a little animation where 20 lines are selected (with a 100ms interval)

Solution 9 - Visual Studio

The correct wingrep command line syntax to force a new instance and jump to a line number is:

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

Replace the studio version number with the correct version for your setup.

Solution 10 - Visual Studio

These C# dependencies on project references are completely unecessary. Indeed much of the code here is overly verbose. All you need is this.

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

Simples eh?

Solution 11 - Visual Studio

The version posted by @Mungo64 worked for me, but of course the version number is always changing, so I made a version that automatically searches until we find it.

Add Reference->Search 'envdte'->Check Checkbox for envdte->Click OK

//using EnvDTE; //I didn't use the using directive as it causes ambiguity in another module I'm using.

private static void OpenFileAtLine(string file, int line)
{
    //The number needs to be rolled to the next version each time a new version of visual studio is used... 
    EnvDTE.DTE dte = null;


    for (int i = 25; i > 8; i--) {
        try
        {
            dte = (EnvDTE.DTE)Marshal.GetActiveObject("VisualStudio.DTE." + i.ToString() + ".0");
        }
        catch (Exception ex)
        {
            //don't care... just keep bashing head against wall until success
        }
    }

    //the following line works fine for visual studio 2019:
    //EnvDTE.DTE dte = (EnvDTE.DTE)Marshal.GetActiveObject("VisualStudio.DTE.16.0");
    dte.MainWindow.Visible = true;
    dte.ExecuteCommand("File.OpenFile", file);
    dte.ExecuteCommand("Edit.GoTo", line.ToString());
}

Solution 12 - Visual Studio

I can't figure out a way to do this with straight command-line options. It looks like you will have to write a macro for it. Supposedly, you can invoke them like so.

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

So, you can probably create a macro that takes a filename and a line number, then opens the file and jumps to the proper place. But, I don't know that you can specify a same-instance flag somewhere, or not.

Solution 13 - Visual Studio

I was about to ask this question because when you get the "yellow screen of death" when debugging a web application, you want to quickly go to the file and line that it gives you in the stacktrace e.g:

[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

Say I want to go to ServiceUserController.cs at line 41. Usually I would open Visual Studio and do it manually but then I wrote a little Autohotkey script which does it.

To open it, you will highlight the filename and line number e.g. ServiceUserController.cs:41 and thereafter press your shortcut Alt + v. Here is the code for it:

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

You will want to paste the following "utility functions" before it:

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
}

Solution 14 - Visual Studio

Using this command works for me, as long as Visual Studio is NOT open already. "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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHarold BamfordView Question on Stackoverflow
Solution 1 - Visual StudioFouré OlivierView Answer on Stackoverflow
Solution 2 - Visual StudiorederView Answer on Stackoverflow
Solution 3 - Visual StudiodiimdeepView Answer on Stackoverflow
Solution 4 - Visual StudioWade HatlerView Answer on Stackoverflow
Solution 5 - Visual StudioEvgeny PanasyukView Answer on Stackoverflow
Solution 6 - Visual StudioEvgeny PanasyukView Answer on Stackoverflow
Solution 7 - Visual StudioMungo64View Answer on Stackoverflow
Solution 8 - Visual StudioDinis CruzView Answer on Stackoverflow
Solution 9 - Visual StudioRichard MillsView Answer on Stackoverflow
Solution 10 - Visual StudioOnceUponATimeInTheWestView Answer on Stackoverflow
Solution 11 - Visual StudioJoeView Answer on Stackoverflow
Solution 12 - Visual StudioEndangeredMassaView Answer on Stackoverflow
Solution 13 - Visual StudioTahir HassanView Answer on Stackoverflow
Solution 14 - Visual StudioCraigw1701View Answer on Stackoverflow