Vscode-powershell: Provide a way to restart VSC's internal powershell session that runs the Script Analyzer

Created on 4 Jan 2021  路  7Comments  路  Source: PowerShell/vscode-powershell

Summary of the new feature

This feature request is related to https://github.com/PowerShell/PowerShell/issues/14536

This is to help aleviate the problems of working with classes, particularly when developing modules. Currently, the problem we face is that once a class has been defined and is present in a session, it can't be modified. Obviously, the real underlying problem that should be fixed is this write once only nature of class definitions, but I guess if it was easy to fix, then you'd have done that already. Whilst this is not fixed, can we please have a mechanism for working around this issue.

We need a quick and easy way to restart the current session (the hidden session that runs the script analyzer inside VSC), without having to close down VSC and reopen it. Current, if the user make a change to a class definition then the script analyzer can't pick up the changes, unless its session is restarted. There is no ui element that allows the user the control the interal PS session. I am assuming that the internal session is different to the powershell session that the user can invoke in the interal terminal in VSC and these 2 sessions are not related to each other, but you can correct me if I'm wrong.

Working with classes in the current environment is more dfficult than it should be. Until we get a fix for the class issue, it would be nice for VSC to provide some helpers (like being able to restart the PSSA powershell session).

PowerShell-Bug Resolution-External

All 7 comments

The extension uses PowerShellEditorServices which creates the "PowerShell Integrated Console" and uses this session for script debugging and analysis. There is a command exposed for PowerShell: Restart Current Session, this should restart the PSIC session for you. Alternatively, you can also click the PowerShell version in the lower right which will bring up a menu where one of the options is to restart the current session.

@corbob thanks for your insight. So the terminal powershelll session is used for the analytics services, so re-starting that session will allow the internal PSSA to pick up new class changes. That's great, cheers.

PSSA does run in it's own runspace, but restarting that runspace wouldn't solve the issue as that runspace still won't have the class defined. The only way to get around this problem currently is to use using module ModuleWithTargetClass instead.

This error comes from PowerShell's parser itself. I'm not sure there's anything that PSES can really do to get around it. Ideally there would be support for some sort of #include ./other-classes.ps1 parser directive (purely for intellisense and suppressing this error in editor scenarios) but that would have to come from PowerShell.

Argh, its such a shame that PowerShell implemented classes the way they did. They have made a rod for their own back now. It seems like they must have rushed out the class implementation with serious deficiencies (for the sake of being able to say that you can program with classes in PS), instead of coming up with a proper robust design, that doesnt present all these issues. I'm hoping that in a future release they will come up with a new class system regardless of wether it breaks existing classes. The existing system is broken and should be fixed reagrdless of backward compatibility. If they don't do this, thn at least there should be proper documentation about powershell classes that explains all the issues. I never knew about the read onl;y nature of classes until I read some 3rd party blog on the subject, when I should have been able to find that info in Microsoft docs.

It seems like they must have rushed out the class implementation with serious deficiencies (for the sake of being able to say that you can program with classes in PS)

Classes were added mainly as a better way to write DSC resources. They work pretty well for that from what I've heard.

Really classes work mostly just fine up until the point you try to import them outside of the module. They're best used as module internal logic, keeping the actual public API as functions.

instead of coming up with a proper robust design, that doesnt present all these issues.

Assuming you mean making them more dynamic, I'm not really sure how that could be fixed without decoupling classes from .NET runtime classes completely. That would free up some design avenues, but would greatly limit the usability.

Personally I think classes would have been a lot easier to understand if they went a bit harder into static and made them actually read only.

Definitely not saying there is nothing to fix with classes, there are an absolute ton of fixable problems.

I never knew about the read onl;y nature of classes until I read some 3rd party blog on the subject, when I should have been able to find that info in Microsoft docs.

I should stress that they're not read only. Only when it comes to exported classes do they become functionally read only.

For example, you can do this interactively:

PS> class Test { static [int] GetInt() { return 10 } } [Test]::GetInt()
PS> class Test { static [int] GetInt() { return 20 } } [Test]::GetInt()

This is what makes them well suited for organizing internal only logic. If you only use the class in module code, then Import-Module x -Force will work just fine and the new class will be picked up without issue.

This isn't really documented much because it's considered to be an almost entirely authoring time issue.

Hi @SeeminglyScience, thanks for your insight. Don't get too hung up on me saying read only, I understood your original comment about this, but there were caveats. Read only, is just a succint way for me to express the limitation.

Using classes as internal only presents issues, that is why I have taken to defining a new module only with class defined in them to be consumed by client modules. The reason for this is that if I have a module Widget module that contains a class [bucket], then assuming the module is developed with a build stage that combines all its ps1 files into the psm1 file (which is a commonly used pattern), then accessing class types is a problem. Let's say inside Widget, we define a new class [ShinyBucket] that inherits from [bucket], then [ShinyBucket] won't be able to access type [bucket], because its in a different file and can't see the definition. Using a using module statment is not appropriate in this scenario, because it doesn't make sense for the Widget module to have a using module Widget statement.

So we can get around this by defining them in the same file. Ok so that works, but thats problematic also, you could end up having too much functionality combined into the same file for the sake of being able to access the types.

If we have the classes defined in a separate module, and a client module, lets say that's called WidgetClient which contains functionality that needs to access [ShinyBucket] or [bucket], in WidgetClient's psm file, we can have a using module Widget and all those class type become available easily.

I don't like this approach but I have not seen a satisfactory alternative.

You have expressed some points that I hadnt thought of particularly when it comes to .Net, but then if this is the case, then they should document EVERYTHING, rather than let users spin their wheels on incomprehensible error messages and extravagent work-aorunds.

Using classes as internal only presents issues (...)

Yeah at a certain level of complexity it becomes a lot less viable. That's part of why I wish it was a bit less dynamic, if you had to declare all the files that contain classes ahead of time then signatures could be built before actually trying to compile. The dynamicity is what bites us here, you have to compile immediately because you don't have a way of knowing what's gonna use it.

If we have the classes defined in a separate module, and a client module, lets say that's called WidgetClient which contains functionality that needs to access [ShinyBucket] or [bucket], in WidgetClient's psm file, we can have a using module Widget and all those class type become available easily.

Yeah, that approach falls apart with complexity pretty quickly as well though. Two files trying to reference each other, extra nested modules and incompatible types, and a lot of overhead. Pretty much every time I've hit that level of complexity with internal only PS classes, I've hit the same (or worse) problems trying to add using module.

Usually at that point I recommend just running with C# classes. Or mixed.

You have expressed some points that I hadnt thought of particularly when it comes to .Net, but then if this is the case, then they should document EVERYTHING, rather than let users spin their wheels on incomprehensible error messages and extravagent work-aorunds.

Can't really argue there, better docs would definitely be ideal. If you're feeling motivated, they're open sourced over at MicrosoftDocs/PowerShell-Docs.

Was this page helpful?
0 / 5 - 0 ratings