public static void ShowIDE( string solutionFile )
        {
            EnvDTE.DTE ide = Msdev.GetIDEInstance( solutionFile );
            if (ide != null)
            {
                ShowIDE( ide );
            }
            else
            {
                // To create a new instance of the IDE, opened to the selected solution we
                // could try:
                // 
                //   Type dteType = Type.GetTypeFromProgID("VisualStudio.DTE.7.1");
                //   EnvDTE.DTE dte = Activator.CreateInstance(dteType) as EnvDTE.DTE;
                //   dte.MainWindow.WindowState = EnvDTE.vsWindowState.vsWindowStateMaximize;
                //   dte.MainWindow.Visible = true;
                //   dte.Solution.Open( solutionFile.Filename );
                //
                // This works but the new devenv.exe process does not exit when you close the
                // IDE.  You could then just reattach as described and the closed IDE would 
                // quickly redisplay (possibly useful as a feature).
                //
                // Instead we lookup the path to the IDE executable in the registry and
                // just start another process.

                RegistryKey devKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\VisualStudio\\7.1\\Setup\\VS");
                string idePath = (string) devKey.GetValue( "EnvironmentPath" );

                System.Diagnostics.Process p = new System.Diagnostics.Process();
                p.StartInfo.RedirectStandardOutput =false;
                p.StartInfo.Arguments = solutionFile;
                p.StartInfo.FileName = idePath;
                p.StartInfo.UseShellExecute = true;
                p.Start();
            }
        }
        private void ThreadMain()
        {
            // Take a snapshot of the currently running instances of Visual Studio
            // We'll also separately keep track of the solution files that each
            // instance has open at this time.  We'll use it to detect when an 
            // IDE has loaded or unloaded a solution.

            Dictionary<string, _DTE> snapshotInstances = Msdev.GetIDEInstances(m_openSolutionsOnly);
            Hashtable snapshotSolutions = new Hashtable();
            foreach( string snapshotKey in snapshotInstances.Keys )
            {
                string solutionFile = String.Empty;
                try
                {
                    EnvDTE.DTE ide = (EnvDTE.DTE) snapshotInstances[ snapshotKey ];
                    solutionFile = ide.Solution.FullName;
                }
                catch{}

                snapshotSolutions[ snapshotKey ] = solutionFile;
            }

            // We'll just keep looping in this thread, periodically checking the
            // currently running list of IDE's.  If there is any change we'll 
            // raise a Changed event.

            while (m_isRunning)
            {
                System.Threading.Thread.Sleep( m_period );
                if (Changed != null)
                {
                    Dictionary<string, _DTE> currentInstances = Msdev.GetIDEInstances(m_openSolutionsOnly);
                    bool changed = Msdev.CompareInstances( snapshotInstances, currentInstances );
                    if (changed)
                    {
                        m_invokeObject.BeginInvoke( Changed, null);
                        snapshotInstances = currentInstances;
                    }
                    else
                    {
                        foreach ( string currentKey in currentInstances.Keys )
                        {
                            string prevSolutionFile = (string) snapshotSolutions[ currentKey ];
                            string currentSolutionFile = String.Empty;
                            try
                            {
                                EnvDTE.DTE ide = (EnvDTE.DTE) currentInstances[ currentKey ];
                                currentSolutionFile = ide.Solution.FullName;
                            }
                            catch {}
                            if (prevSolutionFile != currentSolutionFile)
                            {
                                m_invokeObject.BeginInvoke( Changed, null );
                                snapshotInstances = currentInstances;
                                snapshotSolutions[ currentKey ] = currentSolutionFile;
                                break;
                            }
                        }
                    }
                }
            }
        }