title: Open a file in Visual Studio at a specific line number
body: <p>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:</p>
  
  <pre><code>emacs +140 filename.c
  </code></pre>
  
  <p>I have found nothing like this for Visual Studio (devenv). The closest I have found is:</p>
  
  <pre><code>devenv /Command "Edit.Goto 140" filename.c
  </code></pre>
  
  <p>However, this makes a separate instance of devenv for each such file. I would rather have something that uses an existing instance.</p>
  
  <p>These variations re-use an existing devenv, but don't go to the indicated line:</p>
  
  <pre><code>devenv /Command "Edit.Goto 140" /Edit filename.c
  devenv /Command  /Edit filename.c "Edit.Goto 140"
  </code></pre>
  
  <p>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).</p>
  
  <p>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.</p>
  
  <p>Any ideas?</p>
  
  <hr>
  
  <p>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.</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#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", &amp;clsid);
      if (FAILED(result))
          return false;
  
      CComPtr&lt;IUnknown&gt; punk;
      result = ::GetActiveObject(clsid, NULL, &amp;punk);
      if (FAILED(result))
          return false;
  
      CComPtr&lt;EnvDTE::_DTE&gt; DTE;
      DTE = punk;
  
      CComPtr&lt;EnvDTE::ItemOperations&gt; item_ops;
      result = DTE-&gt;get_ItemOperations(&amp;item_ops);
      if (FAILED(result))
          return false;
  
      CComBSTR bstrFileName(filename);
      CComBSTR bstrKind(EnvDTE::vsViewKindTextView);
      CComPtr&lt;EnvDTE::Window&gt; window;
      result = item_ops-&gt;OpenFile(bstrFileName, bstrKind, &amp;window);
      if (FAILED(result))
          return false;
  
      CComPtr&lt;EnvDTE::Document&gt; doc;
      result = DTE-&gt;get_ActiveDocument(&amp;doc);
      if (FAILED(result))
          return false;
  
      CComPtr&lt;IDispatch&gt; selection_dispatch;
      result = doc-&gt;get_Selection(&amp;selection_dispatch);
      if (FAILED(result))
          return false;
  
      CComPtr&lt;EnvDTE::TextSelection&gt; selection;
      result = selection_dispatch-&gt;QueryInterface(&amp;selection);
      if (FAILED(result))
          return false;
  
      result = selection-&gt;GotoLine(line, TRUE);
      if (FAILED(result))
          return false;
  
      return true;
  }
  </code></pre>