views:

435

answers:

1

I'm using the EnvDTE COM objects to automate Visual Studio. I'm still looking through the documentation, however, I figured I'd drop the question here to see if someone already knows how to do this.

So, the problem is that when I get the DTE object and look at what Solution is open, I need to open another instance of Visual Studio if the solution is not the one I'm expecting. I don't necessarily want to load another solution over an existing instance of VS.

+1  A: 

So, I figured this out on my own. It turns out that the RunningObjectTable is the way to iterate over all VS instances and look for one with the solution open that I am expecting. If I don't find an instance that I can use, then I call CoCreateInstance() to launch a new VS IDE:

#define RETURN_ON_FAIL( expression ) \
result = ( expression ); \
if ( FAILED( result ) )  \
 return false;   \
else // To prevent danging else condition

...

HRESULT result;
CLSID clsid;
CComPtr<IUnknown> punk;
CComPtr<EnvDTE::_DTE> dte;

RETURN_ON_FAIL( ::CLSIDFromProgID(L"VisualStudio.DTE", &clsid) );

...

// Search through the Running Object Table for an instance of Visual Studio
 // to use that either has the correct solution already open or does not have 
 // any solution open.
 CComPtr<IRunningObjectTable> ROT;
 RETURN_ON_FAIL( GetRunningObjectTable( 0, &ROT ) );

 CComPtr<IBindCtx> bindCtx;
 RETURN_ON_FAIL( CreateBindCtx( 0, &bindCtx ) );

 CComPtr<IEnumMoniker> enumMoniker;
 RETURN_ON_FAIL( ROT->EnumRunning( &enumMoniker ) );

 CComPtr<IMoniker> dteMoniker;
 RETURN_ON_FAIL( CreateClassMoniker( clsid, &dteMoniker ) );

 CComBSTR bstrSolution( solutionPath );
 CComPtr<IMoniker> moniker;
 ULONG monikersFetched = 0;
 while ( enumMoniker->Next( 1, &moniker, &monikersFetched ) == S_OK)
 {
  if ( moniker->IsEqual( dteMoniker ) )
  {
   result = ROT->GetObject( moniker, &punk );
   if ( result == S_OK )
   {
    dte = punk;

    if ( dte )
    {
     CComPtr<EnvDTE::_Solution> solution;
     RETURN_ON_FAIL( dte->get_Solution( &solution ) );

     VARIANT_BOOL isOpen = FALSE;
     RETURN_ON_FAIL( solution->get_IsOpen( &isOpen ) );
     if ( !isOpen )
     {
      RETURN_ON_FAIL( solution->Open( bstrSolution ) );
      break;
     }
     else
     {
      CComBSTR fullName;
      RETURN_ON_FAIL( solution->get_FullName( &fullName ) );

      if ( fullName == bstrSolution )
       break;
     }
    }
   }

   punk = NULL;
  }

  moniker = NULL;
 }


if ( !dte )
{  
 RETURN_ON_FAIL( ::CoCreateInstance( clsid, NULL, CLSCTX_LOCAL_SERVER, EnvDTE::IID__DTE, (LPVOID*)&punk ) );
 dte = punk;

 if ( !dte )
  return false;

 if ( solutionPath )
 {
  CComPtr<EnvDTE::_Solution> solution;
  RETURN_ON_FAIL( dte->get_Solution( &solution ) );

  CComBSTR bstrSolution( solutionPath );
  RETURN_ON_FAIL( solution->Open( bstrSolution ) );
 }
}
Amir Ebrahimi