自動化を実行できるように、Visual Studioの実行中のすべてのインスタンスを取得するにはどうすればよいですか?
(これは閉じられたので、この質問を追加しました)
自動化を実行できるように、Visual Studioの実行中のすべてのインスタンスを取得するにはどうすればよいですか?
(これは閉じられたので、この質問を追加しました)
実行中のオブジェクトテーブルを使用してすべてのインスタンスを取得し、必要なインスタンスを選択します。
これ以上のことはできないと思います。これは、デバッガーをVSインスタンスに接続する方法に似ています。リストから1つを選択する必要があります。
IEnumerable<DTE> GetInstances()
{
IRunningObjectTable rot;
IEnumMoniker enumMoniker;
int retVal = GetRunningObjectTable(0, out rot);
if (retVal == 0)
{
rot.EnumRunning(out enumMoniker);
IntPtr fetched = IntPtr.Zero;
IMoniker[] moniker = new IMoniker[1];
while (enumMoniker.Next(1, moniker, fetched) == 0)
{
IBindCtx bindCtx;
CreateBindCtx(0, out bindCtx);
string displayName;
moniker[0].GetDisplayName(bindCtx, null, out displayName);
Console.WriteLine("Display Name: {0}", displayName);
bool isVisualStudio = displayName.StartsWith("!VisualStudio");
if (isVisualStudio)
{
object obj;
rot.GetObject(moniker[0], out obj);
var dte = obj as DTE;
yield return dte;
}
}
}
}
[DllImport("ole32.dll")]
private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc);
[DllImport("ole32.dll")]
private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
以下は、VB.Netが現在のVisualStudioインスタンスを取得するためのソリューションです。
私がしているのは、現在のアセンブリ名でデバッグしているプロセスとの単純な文字列比較です。VSの複数のインスタンスが開いている場合は、期待どおりに機能するようです。VisualStudio 2013で、デバッグモードとリリースモードで試してみました。
輸入:
Imports System
Imports System.Diagnostics.CodeAnalysis
Imports System.Runtime.InteropServices
Imports System.Runtime.InteropServices.ComTypes
Imports EnvDTE80
P /呼び出し:
(NativeMethods.dll)
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Returns a pointer to an implementation of <see cref="IBindCtx"/> (a bind context object).
''' <para></para>
''' This object stores information about a particular moniker-binding operation.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms678542%28v=vs.85%29.aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <param name="reserved">
''' This parameter is reserved and must be 0.
''' </param>
'''
''' <param name="ppbc">
''' Address of an <see cref="IBindCtx"/> pointer variable that receives the
''' interface pointer to the new bind context object.
''' <para></para>
''' When the function is successful, the caller is responsible for calling Release on the bind context.
''' <para></para>
''' A value of <see langword="Nothing"/> for the <paramref name="ppbc"/> value indicates that an error occurred.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' This function can return the standard return values <c>E_OUTOFMEMORY</c> and <c>S_OK</c>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible", justification:="Assembly Reference")>
<DllImport("ole32.dll")>
Public Shared Function CreateBindCtx(ByVal reserved As Integer,
ByRef ppbc As IBindCtx
) As Integer
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Returns a pointer to the <see cref="IRunningObjectTable"/> interface on the local running object table (ROT).
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' <see href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684004%28v=vs.85%29.aspx"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <param name="reserved">
''' This parameter is reserved and must be 0.
''' </param>
'''
''' <param name="pprot">
''' The address of an <see cref="IRunningObjectTable"/> pointer variable that receives the
''' interface pointer to the local ROT.
''' <para></para>
''' When the function is successful, the caller is responsible for calling Release on the interface pointer.
''' <para></para>
''' A value of <see langword="Nothing"/> for the <paramref name="pprot"/> value indicates that an error occurred.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' This function can return the standard return values <c>E_UNEXPECTED</c> and <c>S_OK</c>.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible", justification:="Assembly Reference")>
<DllImport("ole32.dll")>
Public Shared Function GetRunningObjectTable(ByVal reserved As Integer,
ByRef pprot As IRunningObjectTable
) As Integer
End Function
残りのコード:
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets a collection of the Visual Studio instances that are running on this PC.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' An <see cref="IEnumerable(Of DTE2)"/> that contains the running Visual Studio instances, if any.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Shared Iterator Function GetVisualStudioInstances() As IEnumerable(Of DTE2)
Dim rot As IRunningObjectTable = Nothing
Dim enumMoniker As IEnumMoniker = Nothing
Dim retVal As Integer = NativeMethods.GetRunningObjectTable(0, rot)
If (retVal = 0) Then
rot.EnumRunning(enumMoniker)
Dim fetched As IntPtr = IntPtr.Zero
Dim moniker As IMoniker() = New IMoniker(0) {}
While (enumMoniker.Next(1, moniker, fetched) = 0)
Dim bindCtx As IBindCtx = Nothing
NativeMethods.CreateBindCtx(0, bindCtx)
Dim displayName As String = ""
moniker(0).GetDisplayName(bindCtx, Nothing, displayName)
If (displayName.StartsWith("!VisualStudio")) Then
Dim obj As New Object
rot.GetObject(moniker(0), obj)
Yield DirectCast(obj, DTE2)
End If
End While
End If
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Gets a <see cref="DTE2"/> object that represents the current Visual Studio instance that is running this project.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="DTE2"/> object that represents the current Visual Studio instance that is running this project.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Shared Function GetCurrentVisualStudioInstance() As DTE2
Dim currentInstance As DTE2 = Nothing
Dim processName As String = Process.GetCurrentProcess.MainModule.FileName
Dim instances As IEnumerable(Of DTE2) = GetVisualStudioInstances
For Each instance As DTE2 In instances
For Each p As EnvDTE.Process In instance.Debugger.DebuggedProcesses
If (p.Name = processName) Then
currentInstance = instance
Exit For
End If
Next p
Next instance
Return currentInstance
End Function
Powershell 5.1の例、Visual Studio 2019以外は何もインストールされていない、インポートはないなど。
https://github.com/jefflomax/visual-studio-dte-utilities/blob/main/getDteBySolutionName.ps1