Skip to content

Commit 6b47621

Browse files
committed
add new topic about launching VS through DTE
1 parent c0c463e commit 6b47621

File tree

2 files changed

+190
-5
lines changed

2 files changed

+190
-5
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
---
2+
title: Launch Visual Studio using DTE
3+
ms.date: 04/26/2019
4+
ms.topic: conceptual
5+
author: gewarren
6+
ms.author:
7+
manager: jillfra
8+
ms.workload:
9+
- "vssdk"
10+
---
11+
# Launch Visual Studio using DTE
12+
13+
Starting with Visual Studio 2017, the mechanism to launch Visual Studio using DTE is different to launching previous versions of Visual Studio. This change is necessary because Visual Studio 2017 and later supports side-by-side installations of major releases (for example, you can have a preview and a release version installed side-by-side).
14+
15+
The remainder of this article shows the code you can use to launch Visual Studio 2019 using DTE.
16+
17+
## Set up the project
18+
19+
To see the launching code in action, create a project by following these steps.
20+
21+
1. Create a new **Console App** project for the .NET Framework.
22+
23+
2. Install the [Microsoft.VisualStudio.Setup.Configuration.Interop](https://www.nuget.org/packages/Microsoft.VisualStudio.Setup.Configuration.Interop/) NuGet package and add a reference to the assembly.
24+
25+
3. Add a reference to EnvDTE.
26+
27+
4. Paste the [example code](#example-code) that follows into the *Program.cs* file.
28+
29+
5. Press **F5** to run the program. You should see Visual Studio 2019 open before the program exits.
30+
31+
## Example code
32+
33+
```csharp
34+
using Microsoft.VisualStudio.Setup.Configuration;
35+
using System;
36+
using System.Collections.Generic;
37+
using System.Diagnostics;
38+
using System.IO;
39+
using System.Linq;
40+
using System.Runtime.InteropServices;
41+
using System.Runtime.InteropServices.ComTypes;
42+
using System.Threading;
43+
44+
namespace ConsoleLauncherApp
45+
{
46+
class Program
47+
{
48+
static void Main(string[] args)
49+
{
50+
EnvDTE.DTE dte = LaunchVsDte(isPreRelease: false);
51+
52+
dte.MainWindow.WindowState = EnvDTE.vsWindowState.vsWindowStateMaximize;
53+
dte.MainWindow.WindowState = EnvDTE.vsWindowState.vsWindowStateMinimize;
54+
dte.MainWindow.WindowState = EnvDTE.vsWindowState.vsWindowStateNormal;
55+
dte.Quit();
56+
}
57+
58+
private static EnvDTE.DTE LaunchVsDte(bool isPreRelease)
59+
{
60+
ISetupInstance setupInstance = GetSetupInstance(isPreRelease);
61+
string installationPath = setupInstance.GetInstallationPath();
62+
string executablePath = Path.Combine(installationPath, @"Common7\IDE\devenv.exe");
63+
Process vsProcess = Process.Start(executablePath);
64+
string runningObjectDisplayName = $"VisualStudio.DTE.16.0:{vsProcess.Id}";
65+
66+
IEnumerable<string> runningObjectDisplayNames = null;
67+
object runningObject;
68+
for (int i = 0; i < 60; i++)
69+
{
70+
try
71+
{
72+
runningObject = GetRunningObject(runningObjectDisplayName, out runningObjectDisplayNames);
73+
}
74+
catch
75+
{
76+
runningObject = null;
77+
}
78+
79+
if (runningObject != null)
80+
{
81+
return (EnvDTE.DTE)runningObject;
82+
}
83+
84+
Thread.Sleep(millisecondsTimeout: 1000);
85+
}
86+
87+
throw new TimeoutException($"Failed to retrieve DTE object. Current running objects: {string.Join(";", runningObjectDisplayNames)}");
88+
}
89+
90+
private static object GetRunningObject(string displayName, out IEnumerable<string> runningObjectDisplayNames)
91+
{
92+
IBindCtx bindContext = null;
93+
NativeMethods.CreateBindCtx(0, out bindContext);
94+
95+
IRunningObjectTable runningObjectTable = null;
96+
bindContext.GetRunningObjectTable(out runningObjectTable);
97+
98+
IEnumMoniker monikerEnumerator = null;
99+
runningObjectTable.EnumRunning(out monikerEnumerator);
100+
101+
object runningObject = null;
102+
List<string> runningObjectDisplayNameList = new List<string>();
103+
IMoniker[] monikers = new IMoniker[1];
104+
IntPtr numberFetched = IntPtr.Zero;
105+
while (monikerEnumerator.Next(1, monikers, numberFetched) == 0)
106+
{
107+
IMoniker moniker = monikers[0];
108+
109+
string objectDisplayName = null;
110+
try
111+
{
112+
moniker.GetDisplayName(bindContext, null, out objectDisplayName);
113+
}
114+
catch (UnauthorizedAccessException)
115+
{
116+
// Some ROT objects require elevated permissions.
117+
}
118+
119+
if (!string.IsNullOrWhiteSpace(objectDisplayName))
120+
{
121+
runningObjectDisplayNameList.Add(objectDisplayName);
122+
if (objectDisplayName.EndsWith(displayName, StringComparison.Ordinal))
123+
{
124+
runningObjectTable.GetObject(moniker, out runningObject);
125+
if (runningObject == null)
126+
{
127+
throw new InvalidOperationException($"Failed to get running object with display name {displayName}");
128+
}
129+
}
130+
}
131+
}
132+
133+
runningObjectDisplayNames = runningObjectDisplayNameList;
134+
return runningObject;
135+
}
136+
137+
private static ISetupInstance GetSetupInstance(bool isPreRelease)
138+
{
139+
return GetSetupInstances().First(i => IsPreRelease(i) == isPreRelease);
140+
}
141+
142+
private static IEnumerable<ISetupInstance> GetSetupInstances()
143+
{
144+
ISetupConfiguration setupConfiguration = new SetupConfiguration();
145+
IEnumSetupInstances enumerator = setupConfiguration.EnumInstances();
146+
147+
int count;
148+
do
149+
{
150+
ISetupInstance[] setupInstances = new ISetupInstance[1];
151+
enumerator.Next(1, setupInstances, out count);
152+
if (count == 1 &&
153+
setupInstances != null &&
154+
setupInstances.Length == 1 &&
155+
setupInstances[0] != null)
156+
{
157+
yield return setupInstances[0];
158+
}
159+
}
160+
while (count == 1);
161+
}
162+
163+
private static bool IsPreRelease(ISetupInstance setupInstance)
164+
{
165+
ISetupInstanceCatalog setupInstanceCatalog = (ISetupInstanceCatalog)setupInstance;
166+
return setupInstanceCatalog.IsPrerelease();
167+
}
168+
169+
private static class NativeMethods
170+
{
171+
[DllImport("ole32.dll")]
172+
public static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);
173+
174+
[DllImport("ole32.dll")]
175+
public static extern void GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
176+
}
177+
}
178+
}
179+
```
180+
181+
## See also
182+
183+
- [Walkthrough: Access the DTE object from an editor extension](walkthrough-accessing-the-dte-object-from-an-editor-extension.md)

docs/extensibility/toc.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -489,16 +489,16 @@
489489
href: the-structure-of-the-content-types-dot-xml-file.md
490490
- name: VSIX Manifest Designer
491491
href: vsix-manifest-designer.md
492-
- name: Localizing VSIX Packages
492+
- name: Localize VSIX Packages
493493
href: localizing-vsix-packages.md
494494
items:
495495
- name: VSIX Language Pack Schema 2.0 Reference
496496
href: vsix-language-pack-schema-2-0-reference.md
497497
- name: Update a Visual Studio Extension
498498
href: how-to-update-a-visual-studio-extension.md
499-
- name: Preparing Extensions for Windows Installer Deployment
499+
- name: Prepare Extensions for Windows Installer Deployment
500500
href: preparing-extensions-for-windows-installer-deployment.md
501-
- name: Signing VSIX Packages
501+
- name: Sign VSIX Packages
502502
href: signing-vsix-packages.md
503503
- name: Private Galleries
504504
href: private-galleries.md
@@ -507,7 +507,7 @@
507507
href: how-to-create-an-atom-feed-for-a-private-gallery.md
508508
- name: Manage a Private Gallery By Using Registry Settings
509509
href: how-to-manage-a-private-gallery-by-using-registry-settings.md
510-
- name: Supporting Multiple Versions of Visual Studio
510+
- name: Support Multiple Versions of Visual Studio
511511
href: supporting-multiple-versions-of-visual-studio.md
512512
items:
513513
- name: Choosing Between Shared and Versioned VSPackages
@@ -523,8 +523,10 @@
523523
href: registering-verbs-for-file-name-extensions.md
524524
- name: Managing Side-by-Side File Associations
525525
href: managing-side-by-side-file-associations.md
526-
- name: Locating Visual Studio
526+
- name: Locate Visual Studio
527527
href: locating-visual-studio.md
528+
- name: Launch Visual Studio using DTE
529+
href: launch-visual-studio-dte.md
528530
- name: Inside the Visual Studio SDK
529531
href: internals/toc.yml
530532
- name: Support for the Visual Studio SDK

0 commit comments

Comments
 (0)