PowerShell / PowerShellEditorServices

A common platform for PowerShell development support in any editor or application!
MIT License
623 stars 214 forks source link

Can't import PSScriptAnalyzer because assembly has already been loaded #1956

Closed simonsabin closed 1 year ago

simonsabin commented 1 year ago

Prerequisites

Steps to reproduce

trying to import PSScriptAnalyser when using the Integrated Terminal fails as the powershell extension has already loaded the PSScriptAnalyzer assemblies. However the PSScriptAnalyzer module isn't loaded

This means you can't then use PSScriptAnalyzer commands

Expected behavior

Import-module PSScriptAnalyzer works

Actual behavior

import-module PSScriptAnalyzer 
Import-Module: Assembly with same name is already loaded

### Error details

```console
Type        : System.Management.Automation.ActionPreferenceStopException
ErrorRecord : 
    Exception             : 
        Type       : System.IO.FileLoadException
        Message    : Assembly with same name is already loaded
        TargetSite : 
            Name          : LoadBinaryModule
            DeclaringType : Microsoft.PowerShell.Commands.ModuleCmdletBase
            MemberType    : Method
            Module        : System.Management.Automation.dll
        Source     : System.Management.Automation
        HResult    : -2146232799
        StackTrace : 
   at Microsoft.PowerShell.Commands.ModuleCmdletBase.LoadBinaryModule(PSModuleInfo parentModule, String moduleName, String fileName, Assembly assemblyToLoad, String moduleBase, SessionState ss, ImportModuleOptions options,
ManifestProcessingFlags manifestProcessingFlags, String prefix, Boolean loadTypes, Boolean loadFormats, Boolean& found, String shortModuleName, Boolean disableFormatUpdates)
   at Microsoft.PowerShell.Commands.ModuleCmdletBase.LoadModule(PSModuleInfo parentModule, String fileName, String moduleBase, String prefix, SessionState ss, Object privateData, ImportModuleOptions& options, ManifestProcessingFlags
manifestProcessingFlags, Boolean& found, Boolean& moduleFileFound)
   at Microsoft.PowerShell.Commands.ImportModuleCommand.ImportModule_LocallyViaName(ImportModuleOptions importModuleOptions, String name)
   at Microsoft.PowerShell.Commands.ImportModuleCommand.ProcessRecord()
   at System.Management.Automation.CommandProcessor.ProcessRecord()
    CategoryInfo          : NotSpecified: (:) [Import-Module], FileLoadException
    FullyQualifiedErrorId : System.IO.FileLoadException,Microsoft.PowerShell.Commands.ImportModuleCommand
    InvocationInfo        : 
        MyCommand        : Import-Module
        ScriptLineNumber : 34
        OffsetInLine     : 17
        HistoryId        : 4
        ScriptName       : C:\Users\SimonSabin\Documents\PowerShell\Modules\PSScriptAnalyzer\1.20.0\PSScriptAnalyzer.psm1
        Line             : $binaryModule = Import-Module -Name $binaryModulePath -PassThru

        PositionMessage  : At C:\Users\SimonSabin\Documents\PowerShell\Modules\PSScriptAnalyzer\1.20.0\PSScriptAnalyzer.psm1:34 char:17
                           + $binaryModule = Import-Module -Name $binaryModulePath -PassThru
                           +                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        PSScriptRoot     : C:\Users\SimonSabin\Documents\PowerShell\Modules\PSScriptAnalyzer\1.20.0
        PSCommandPath    : C:\Users\SimonSabin\Documents\PowerShell\Modules\PSScriptAnalyzer\1.20.0\PSScriptAnalyzer.psm1
        InvocationName   : Import-Module
        CommandOrigin    : Internal
    ScriptStackTrace      : at <ScriptBlock>, C:\Users\SimonSabin\Documents\PowerShell\Modules\PSScriptAnalyzer\1.20.0\PSScriptAnalyzer.psm1: line 34
                            at <ScriptBlock>, <No file>: line 1
    PipelineIterationInfo : 

TargetSite  : 
    Name          : Invoke
    DeclaringType : System.Management.Automation.Runspaces.PipelineBase, System.Management.Automation, Version=7.2.7.500, Culture=neutral, PublicKeyToken=31bf3856ad364e35
    MemberType    : Method
    Module        : System.Management.Automation.dll
Message     : The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: Assembly with same name is already loaded
Data        : System.Collections.ListDictionaryInternal
Source      : System.Management.Automation
HResult     : -2146233087
StackTrace  : 
   at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
   at System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace rs, Boolean performSyncInvoke)
   at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
   at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
   at System.Management.Automation.PowerShell.Invoke[T](IEnumerable input, PSInvocationSettings settings)
   at Microsoft.PowerShell.EditorServices.Services.PowerShell.Utility.PowerShellExtensions.InvokeAndClear[TResult](PowerShell pwsh, PSInvocationSettings invocationSettings) in
D:\a\_work\1\s\src\PowerShellEditorServices\Services\PowerShell\Utility\PowerShellExtensions.cs:line 76
   at Microsoft.PowerShell.EditorServices.Services.PowerShell.Utility.PowerShellExtensions.InvokeCommand[TResult](PowerShell pwsh, PSCommand psCommand, PSInvocationSettings invocationSettings) in
D:\a\_work\1\s\src\PowerShellEditorServices\Services\PowerShell\Utility\PowerShellExtensions.cs:line 99
   at Microsoft.PowerShell.EditorServices.Services.PowerShell.Execution.SynchronousPowerShellTask`1.ExecuteNormally(CancellationToken cancellationToken) in
D:\a\_work\1\s\src\PowerShellEditorServices\Services\PowerShell\Execution\SynchronousPowerShellTask.cs:line 125

Environment data

Name                           Value
----                           -----
PSVersion                      7.2.7
PSEdition                      Core
GitCommitId                    7.2.7
OS                             Microsoft Windows 10.0.22000
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Version

ms-vscode.powershell-2022.10.0

Visuals

No response

andyleejordan commented 1 year ago

I'm going to subsume this issue as the actual root problem: while the extension loads PSSA, the module's cmdlets aren't available in the extension terminal, and they should be. If they were, you wouldn't be trying to load PSSA manually.

simonsabin commented 1 year ago

Partly. Really I would like to own the version of PSSA that I load as with any dependency. At present, neither the cmdlets are loaded, nor the module is marked as loaded and thus one can't even tell if loaded. and I really don't want to be checking for loaded assemblies, thats awful.

Currently all our PS modules are failing the PSSA testing phase when run within VSCode, thus have to run outside of VSC.

andyleejordan commented 1 year ago

For owning the version of PSSA, I would recommend that you use powershell.developer.bundledModulesPath to override the bundled modules. For stability reasons, PSES is set to only load its dependent modules (PSSA, PSReadLine, etc.) from that path, but that path is configurable for advanced usage. Note that you'll need to run the extension in development mode for that setting to be utilized.

simonsabin commented 1 year ago

That looks like a load of faff and I can probably live with the version bump, can't live with it just not working because you don't get the cmdlets and can't load the module

andyleejordan commented 1 year ago

Definitely on my shortlist to get the cmdlets and module loaded in the main runspace so that this is usable.

SydneyhSmith commented 1 year ago

We realized this actually isn't possible due to our architecture, so script analyzer will need to be run in a non-extension terminal

ghost commented 1 year ago

This issue has been marked as answered and has not had any activity in a day. It has been automatically closed for housekeeping purposes.

simonsabin commented 1 year ago

Got to same I'm really disappointed in this. That means no pester testing using psscript analyzer. All our module development is now broken because of this. Why can't you import the module rather than just the assembly? at least that way it can be detected and handled using the normal mechanisms.

andyleejordan commented 1 year ago

So the problem is that the way PSSA is written prevents us from sharing it. It relies on a global singleton of shared state, once we've imported it and PSES is using it to analyze files and provide formatting, it cannot be used by a user in the Extension Terminal without clashing and then crashing 😢

simonsabin commented 1 year ago

Can we disable that behaviour so I can use PSSA

Simon Sabin

andyleejordan commented 1 year ago

Yes, I believe that if you disable script analysis via the setting powershell.scriptAnalysis.enable and disable formatting (editor settings editor.formatOnType, editor.formatOnPaste and editor.formatOnSave) then PSSA should never get initialized, which would be a viable workaround for you. I can imagine a reasonable ask for a powershell.codeFormatting.enable setting, but we don't currently have it.

simonsabin commented 1 year ago

Can’t you load it into an Assembly Load Context, or work with the PSSA module in order that they work together.

Simon Sabin