Skip to content

Returns the DTE object corresponding to the running VS instance where the given solution is open

License

Notifications You must be signed in to change notification settings

codewerfer/RunningVSInstanceFinder

 
 

Repository files navigation

Usage

Suppose you wish to automate from Powershell the Visual Studio instance where the given solution is open. This small tool makes it easy.

Build the tool and load the Ceridian.RunningVSInstanceFinder type into the Powershell memory:

PS C:\Dayforce\DevOps\RunningVSInstanceFinder> dotnet build -v:q -nologo

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.05
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> Add-Type -Path C:\dayforce\DevOps\RunningVSInstanceFinder\RunningVSInstanceFinder\bin\Debug\net472\RunningVSInstanceFinder.dll > $null
PS C:\Dayforce\DevOps\RunningVSInstanceFinder>

Obtain the DTE2 object:

PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res = [Ceridian.RunningVSInstanceFinder]::Find("C:\dayforce\CSTool\CSTool.sln")
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res

DTE                SolutionFullName              ErrorMessage
---                ----------------              ------------
System.__ComObject C:\dayforce\CSTool\CSTool.sln


PS C:\Dayforce\DevOps\RunningVSInstanceFinder>

Now let us build inside the respective VS instance and get back the build output pane text:

PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res.DTE.Solution.SolutionBuild.Build()
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $text = [Ceridian.RunningVSInstanceFinder]::GetOutputPaneText($res.DTE, "Build")
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $text.Length
6384
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $text -split "`r`n" | Select-Object -Last 2
========== Build: 0 succeeded, 0 failed, 3 up-to-date, 0 skipped ==========

PS C:\Dayforce\DevOps\RunningVSInstanceFinder>

Now let us check the Error List pane:

PS C:\Dayforce\DevOps\RunningVSInstanceFinder> [Ceridian.RunningVSInstanceFinder]::GetErrorList($res.DTE)
PS C:\Dayforce\DevOps\RunningVSInstanceFinder>

I am going to botch the code on purpose, build and get the build output and the error list again:

PS C:\Dayforce\DevOps\RunningVSInstanceFinder> echo "xyz" | Out-File -Encoding ascii -Append ..\..\CSTool\CSTool\ClassifyCmd.cs
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res.DTE.Solution.SolutionBuild.Build()
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> [Ceridian.RunningVSInstanceFinder]::GetOutputPaneText($res.DTE, "Build") -split "`r`n" | Select-Object -Last 2
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========

PS C:\Dayforce\DevOps\RunningVSInstanceFinder> [Ceridian.RunningVSInstanceFinder]::GetErrorList($res.DTE)


ErrorLevel  : High
Description : A namespace cannot directly contain members such as fields, methods or statements
FileName    : C:\dayforce\CSTool\CSTool\ClassifyCmd.cs
Line        : 394
Column      : 1
Project     : CSTool\CSTool.csproj



PS C:\Dayforce\DevOps\RunningVSInstanceFinder>

It is also possible to obtain the DTE2 object for a "vacant" VS instance that has no solution open. Just pass $null as the solution path:

PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res.DTE.Solution.Close()
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res2 = [Ceridian.RunningVSInstanceFinder]::Find($null)
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res2

DTE                SolutionFullName ErrorMessage
---                ---------------- ------------
System.__ComObject


PS C:\Dayforce\DevOps\RunningVSInstanceFinder> [Object]::ReferenceEquals($res2.DTE, $res.DTE)
True
PS C:\Dayforce\DevOps\RunningVSInstanceFinder>

Finally it is possible to obtain the DTE2 for multiple VS instances at once:

PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res.DTE.Solution.Open("C:\dayforce\CSTool\CSTool.sln")
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res2 = [Ceridian.RunningVSInstanceFinder]::FindMany([string[]]@("C:\dayforce\CSTool\CSTool.sln", "C:\dayforce\DevOps\RunningVSInstanceFinder\RunningVSInstanceFinder.sln"))
PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res2|Format-List


Found         : {[C:\dayforce\CSTool\CSTool.sln, System.Collections.Generic.List`1[Ceridian.RunningVSInstanceFinder+FindResult]],
                [C:\dayforce\DevOps\RunningVSInstanceFinder\RunningVSInstanceFinder.sln,
                System.Collections.Generic.List`1[Ceridian.RunningVSInstanceFinder+FindResult]]}
ErrorMessages : {}



PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res2.Found

Key                                                                    Value
---                                                                    -----
C:\dayforce\CSTool\CSTool.sln                                          {C:\dayforce\CSTool\CSTool.sln}
C:\dayforce\DevOps\RunningVSInstanceFinder\RunningVSInstanceFinder.sln {C:\dayforce\DevOps\RunningVSInstanceFinder\RunningVSInstanceFinder.sln}


PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res2.Found['C:\dayforce\CSTool\CSTool.sln']

DTE                SolutionFullName              ErrorMessage
---                ----------------              ------------
System.__ComObject C:\dayforce\CSTool\CSTool.sln


PS C:\Dayforce\DevOps\RunningVSInstanceFinder> $res2.Found['C:\dayforce\DevOps\RunningVSInstanceFinder\RunningVSInstanceFinder.sln']

DTE                SolutionFullName                                                       ErrorMessage
---                ----------------                                                       ------------
System.__ComObject C:\dayforce\DevOps\RunningVSInstanceFinder\RunningVSInstanceFinder.sln


PS C:\Dayforce\DevOps\RunningVSInstanceFinder>

Notes:

  • The code is current not available on NuGet, so to use it you need to clone the repo and build it with dotnet build.
  • Bear in mind that trying to automate a VS instance with an open modal dialog (there can be other busy scenarios) results in a COMException.
  • My original intention was to just implement the Find and FindMany methods. However, I failed to obtain the Error List and the Build Output Pane contents, because the DTE2.ToolWindows property is $null in Powershell. I have asked how to do it in this StackOverflow question.

About

Returns the DTE object corresponding to the running VS instance where the given solution is open

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%