Description
Summary
When calling PSES programmatically (from C# but using the supported script) in a ConstrainedRunspace in ConstrainedLanguage mode, information about all cmdlets and the underlying filesystem is exposed via CodeCompletion.
Steps to Reproduce
StartLanguageServerViaScript()
{
InitialSessionState iss = InitialSessionState.Create();
iss.LanguageMode = PSLanguageMode.ConstrainedLanguage;
iss.ImportPSModule("Microsoft.Powershell.Utility", "Microsoft.Powershell.Core", "Microsoft.PowerShell.Security");
iss.Commands.Add(new SessionStateCmdletEntry("Get-Command", typeof(GetCommandCommand), null));
iss.Commands.Add(new SessionStateCmdletEntry("Where-Object", typeof(WhereObjectCommand), null));
iss.Commands.Add(new SessionStateCmdletEntry("Select-Object", typeof(SelectObjectCommand), null));
iss.Commands.Add(new SessionStateCmdletEntry("ForEach-Object", typeof(ForEachObjectCommand), null));
iss.Commands.Add(new SessionStateCmdletEntry("Format-List", typeof(FormatListCommand), null));
iss.Commands.Add(new SessionStateCmdletEntry("Format-Table", typeof(FormatTableCommand), null));
iss.Commands.Add(new SessionStateCmdletEntry("Set-ExecutionPolicy", typeof(SetExecutionPolicyCommand), null));
iss.Commands.Add(new SessionStateCmdletEntry("Format-Hex", typeof(FormatHex), null));
iss.Commands.Add(new SessionStateCmdletEntry("Out-Default", typeof(OutDefaultCommand), null));
iss.Commands.Add(new SessionStateCmdletEntry("Out-Host", typeof(OutHostCommand), null));
iss.Commands.Add(new SessionStateCmdletEntry("Import-Module", typeof(ImportModuleCommand), null));
iss.Commands.Add(new SessionStateCmdletEntry("Start-EditorServices", typeof(PSCommand), null));
iss.Commands.Add(new SessionStateFunctionEntry("TabExpansion2", PowershellCommands.TabExpansion));
iss.ImportPSModule(_modulePath);
Runspace myRunSpace = RunspaceFactory.CreateRunspace(_host, iss);
myRunSpace.Open();
PowerShell powershell = PowerShell.Create();
powershell.Runspace = myRunSpace;
powershell.AddCommand("Set-ExecutionPolicy")
.AddParameter("-ExecutionPolicy", "Bypass")
.AddParameter("-Scope", "Process")
.Invoke();
PSCommand[] profileCommands = PSHostUtilities.GetProfileCommands("Microsoft.PowerShell");
foreach (PSCommand command in profileCommands)
{
powershell.Commands = command;
powershell.Invoke();
}
powershell.AddScript(PowershellCommands.TabExpansion);
powershell.Runspace.SessionStateProxy.InvokeCommand.GetCommand("TabExpansion2", CommandTypes.Function);
var scriptInvocation = powershell.Runspace.SessionStateProxy.InvokeCommand
.GetCommand(_StartEditorServicesScriptPath, CommandTypes.ExternalScript);
powershell.AddCommand(scriptInvocation)
//"-FeatureFlags", "@()"
.AddParameter("HostName", "monaco")
.AddParameter("HostProfileId", "0")
.AddParameter("HostVersion", "1.0.0")
.AddParameter("LogPath", _logPath)
.AddParameter("LogLevel", "Diagnostic")
.AddParameter("BundledModulesPath", _bundledModulesPath)
.AddParameter("SessionDetailsPath", _sessionInfoFilePath)
.AddParameter("EnableConsoleRepl");
try
{
foreach (var command in powershell.Commands.Commands)
{
command.MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
command.MergeMyResults(PipelineResultTypes.Information, PipelineResultTypes.Output);
}
_psInvocationResult = powershell.BeginInvoke();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
Expected Behavior
CodeCompletion should only return information about the specific set of modules I loaded into my runspace via InitialSessionState
What actually happens
All available modules are available via CodeCompletion and my custom (and likely unnecessary) TabExpansion2 function never gets called.
Possible Fixes
Instead of always creating a new runspace in PowerShellContext.Create() use the existing one.
Create a new runspace but allow the user to specify a custom initialsessionstate. Perhaps do this instead of the recent change that simply passes in LanguageMode as this would give the user more granular control of the runspace. This would naturally require Start-EditorServices to be modified to accept an initiationsessionstate object.
I feel pretty confident I can implement the required changes, I’d like some feedback as to which option is most feasible or if there are perhaps intentional reasons a new runspace is being created.