That whole nuget package manager console window, that is a powershell window, that gives you easy access to the visual studio automation model, is neat, very powerful, and, as I have discovered, a treasure trove of Visual Studio arcana.
EnvDTE.DTE is easy to get at when you are in the context of an add-in that you have written yourself. Exposing it in ready made powershell window, is a complex and involved trick. Writing that whole powershell console as an add-in inside of Visual Studio, after reading the source code at nuget.codeplex.com, appears to be an elegant work of coding art.
But.. back to $dte, my favorite powershell-nuget-visualstudio variable. Here is the code that worked the magic and populated the variable inside of powershell:
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"Microsoft.Reliability",
"CA2000:Dispose objects before losing scope",
Justification = "We can't dispose it if we want to return it.")]
private static Tuple CreateRunspace(IConsole console, string
hostName)
{
DTE dte = ServiceLocator.GetInstance();
"Microsoft.Reliability",
"CA2000:Dispose objects before losing scope",
Justification = "We can't dispose it if we want to return it.")]
private static Tuple
{
DTE dte = ServiceLocator.GetInstance
InitialSessionState initialSessionState
= InitialSessionState.CreateDefault();
initialSessionState.Variables.Add(
new SessionStateVariableEntry(
"DTE",
(DTE2)dte,
"Visual Studio DTE automation object",
ScopedItemOptions.AllScope | ScopedItemOptions.Constant)
);
initialSessionState.Variables.Add(
new SessionStateVariableEntry(
"DTE",
(DTE2)dte,
"Visual Studio DTE automation object",
ScopedItemOptions.AllScope | ScopedItemOptions.Constant)
);
// this is used by the functional tests
var packageManagerFactory = ServiceLocator.GetInstance();
var pmfTuple = Tuple.Create<string,
object>("packageManagerFactory", packageManagerFactory);
var packageManagerFactory = ServiceLocator.GetInstance
Tuple<string,
object>[] privateData = new Tuple<string, object>[]
{ pmfTuple };
var host = new NuGetPSHost(hostName,
privateData)
{
ActiveConsole = console
};
{
ActiveConsole = console
};
var runspace = RunspaceFactory.CreateRunspace(host,
initialSessionState);
runspace.ThreadOptions = PSThreadOptions.Default;
runspace.Open();
runspace.ThreadOptions = PSThreadOptions.Default;
runspace.Open();
//
// Set this runspace as DefaultRunspace so I can script DTE events.
//
// WARNING: MSDN says this is unsafe. The runspace must not be shared across
// threads. I need this to be able to use ScriptBlock for DTE events. The
// ScriptBlock event handlers execute on DefaultRunspace.
//
Runspace.DefaultRunspace = runspace;
// Set this runspace as DefaultRunspace so I can script DTE events.
//
// WARNING: MSDN says this is unsafe. The runspace must not be shared across
// threads. I need this to be able to use ScriptBlock for DTE events. The
// ScriptBlock event handlers execute on DefaultRunspace.
//
Runspace.DefaultRunspace = runspace;
return Tuple.Create(new
RunspaceDispatcher(runspace), host);
}
}
Pasted
from <http://nuget.codeplex.com/SourceControl/latest>
- They brute forced the whole console window. They didn't recycle any sort of existing powershell or command window. They wrote a new one and dealt with all the keypress by keypress nastiness that is involved therein.
- $dte is actually spelled $DTE, and just a variable passed into a Runspace through its InitialSessionState.
- OpenSource code is fun.
Also, and unrelated to codeplex and nuget, if you want to create a headless $dte object, or rather one connected to a new instance of visual studio 2012, that is simply:
$dte = New-Object -comobject VisualStudio.DTE.11.0
Getting the running obect is done like this:
$dte = [System.Runtime.InteropSrevices.Marshal]::GetActiveObject("VisualStudio.DTE.11.0")
No comments:
Post a Comment