You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Expose C# API for hosted scenarios + allow AST to be passed directly #1056
A fairly large ask, but I would be very happy doing the work. Just want to discuss it with everyone.
In PowerShell EditorServices, we have a hosted PowerShell environment and do a lot of parsing and AST analysis separately from PSScriptAnalyzer. And we are often generating a new AST with every document change. This means PSScriptAnalyzer is doing a fair amount of duplicate work when we call it, since it only accepts input as a string or a filepath.
Our ideal would be to be able to embed PSScriptAnalyzer with a C# API call, pass in our own hosted PowerShell session as its engine in the constructor, and then send pre-parsed ASTs to PSScriptAnalyzer for analysis. The cmdlets would then wrap or be an alternative entry point for this API.
James Truher (@JamesWTruher) and I have discussed something like this before, but I just want to document the desire. He and I also discussed being able to only use rules that use the parser, rather than the whole engine.
Anyway, to summarise:
We'd like to pass AST objects directly to PSSA, rather than having to reparse strings
Ideally we could do this in C# (no ps.AddCommand("Invoke-ScriptAnalyzer").Invoke())
Even more ideally we could pass in our own hosted PowerShell runtime for the analyzer to use, rather than have it spin up its own.
The public API already exists and was used in the past. Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer has a AnalyzeSyntaxTree method that does everything we need.
If I remember correctly the switch was due to some static helper clean up that wasn't happening, resulting in a large amount of memory usage.
Yes I had that suspicion. I had a very brief play with the code in PowerShell and didn't see hook-in points, but I'm guessing there's some singleton dance (shudder) to get at the script analyzer object.
Well in that case I suppose we should make some attempt to use that and if it doesn't work, this issue can track making that usable...?
Rob Holt (@rjmholt) it does have a static property Instance so I'd agree that it's probably intended to be a singleton. However, the constructor is public. Not sure if that's intended, seems to work though.
usingnamespaceSystem.Management.AutomationusingnamespaceMicrosoft.Windows.PowerShell.ScriptAnalyzerclassNullOutputWriter : IOutputWriter {
[void] WriteError([ErrorRecord] $errorRecord) { }
[void] WriteWarning([string] $message) { }
[void] WriteVerbose([string] $message) { }
[void] WriteDebug([string] $message) { }
[void] ThrowTerminatingError([ErrorRecord] $errorRecord) { throw$errorRecord }
}
$rs= [runspacefactory]::CreateRunspace($Host, [initialsessionstate]::CreateDefault())
try {
$rs.Open()
$analyzer= [ScriptAnalyzer]::new()
$analyzer.Initialize(
<# runspace: #>$rs,<# outputWriter: #> [NullOutputWriter]::new(),<# customizedRulePath: #>@(),<# includeRuleNames: #>@(),<# excludeRuleNames: #>@(),<# severity: #>@(),<# includeDefaultRules: #>$true,<# suppressedOnly: #>$false,<# profile: #> [string]::Empty)
$completionData= [CommandCompletion]::MapStringInputToParsedInput('gci',3)
$analyzer.AnalyzeSyntaxTree($completionData.Item1,$completionData.Item2, [string]::Empty)
# returns:# RuleName Severity ScriptName Line Message# -------- -------- ---------- ---- -------# PSAvoidUsingCmdletAliases Warning 1 'gci' is an alias of 'Get-ChildItem'. Alias can# introduce possible problems and make scripts hard to# maintain. Please consider changing alias to its full# content.
} finally {
if ($analyzer) {
$analyzer.CleanUp()
}
$rs.Dispose()
}
Patrick Meinecke (@SeeminglyScience) is right, the API is already there but there were memory problems in the past due to static members not being disposed in the Helper class (leading to big memory consumption) in Helper.cs
Christoph Bergmeister (@bergmeister) thanks for confirming. I do wonder though, was the memory issue due to our failure to invoke a cleanup method? I'd think the same problem would still be occurring otherwise. Right now we invoke PSSA as a cmdlet in it's own runspace pool, but since the singleton instances would be app domain wide, to me that means we just weren't doing something that the cmdlets do themselves.
Patrick Meinecke (@SeeminglyScience)
Sorry, I forgot to respond. This is the original memory issue of PSSA that was never followed up PowerShell/PowerShellEditorServices#269
Now that we have the preview, we could try experimenting with calling the API and see if the memory issue still applies and if so try fixing it.
Rob Holt (@rjmholt) I will close this since we agreed that PSSA already exposes an API (and given that it was used in the past, it seems that the available API is suitable for PSES). Should problems show up because of a bug or memory issues, then we will of course fix it in PSSA but given that PSSA has changed quite a lot it is possible that it is already fixed. If you think the available APIs are not sufficient for PSES, please re-open with details of what kind of API you'd need to be added.
Activity
SeeminglyScience commentedon Aug 19, 2018
The public API already exists and was used in the past.
Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzerhas aAnalyzeSyntaxTreemethod that does everything we need.If I remember correctly the switch was due to some static helper clean up that wasn't happening, resulting in a large amount of memory usage.
rjmholt commentedon Aug 19, 2018
Yes I had that suspicion. I had a very brief play with the code in PowerShell and didn't see hook-in points, but I'm guessing there's some singleton dance (shudder) to get at the script analyzer object.
Well in that case I suppose we should make some attempt to use that and if it doesn't work, this issue can track making that usable...?
SeeminglyScience commentedon Aug 19, 2018
Rob Holt (@rjmholt) it does have a static property
Instanceso I'd agree that it's probably intended to be a singleton. However, the constructor is public. Not sure if that's intended, seems to work though.bergmeister commentedon Aug 19, 2018
Patrick Meinecke (@SeeminglyScience) is right, the API is already there but there were memory problems in the past due to static members not being disposed in the Helper class (leading to big memory consumption) in Helper.cs
SeeminglyScience commentedon Aug 19, 2018
Christoph Bergmeister (@bergmeister) thanks for confirming. I do wonder though, was the memory issue due to our failure to invoke a cleanup method? I'd think the same problem would still be occurring otherwise. Right now we invoke PSSA as a cmdlet in it's own runspace pool, but since the singleton instances would be app domain wide, to me that means we just weren't doing something that the cmdlets do themselves.
bergmeister commentedon Feb 3, 2019
Patrick Meinecke (@SeeminglyScience)
Sorry, I forgot to respond. This is the original memory issue of PSSA that was never followed up
PowerShell/PowerShellEditorServices#269
Now that we have the preview, we could try experimenting with calling the API and see if the memory issue still applies and if so try fixing it.
bergmeister commentedon Feb 14, 2019
Rob Holt (@rjmholt) I will close this since we agreed that PSSA already exposes an API (and given that it was used in the past, it seems that the available API is suitable for PSES). Should problems show up because of a bug or memory issues, then we will of course fix it in PSSA but given that PSSA has changed quite a lot it is possible that it is already fixed. If you think the available APIs are not sufficient for PSES, please re-open with details of what kind of API you'd need to be added.