PowerShell / PowerShell/PSScriptAnalyzer
Migrate away from MEF for loading DLLs in Windows PowerShell
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- C#
- Sterne
- 2.2k
- Forks
- 414
- Ø Merge
- 13 Std. 1 Min.
- Gemergte PRs (30 T.)
- 2
Beschreibung
PSScriptAnalyzer's .NET Framework builds depend on a lesser known technology called the Managed Extensibility Framework (namespaced to System.ComponentModel.Composition) to do a kind of lazy loading of assemblies for rules, presumably for custom rule sets.
This seems to be a kind of inversion of control framework, although we use it in a less typical way than a web server might:
It also means that for rules to be discoverable they need to be decorated with attributes like here:
https://github.com/PowerShell/PSScriptAnalyzer/blob/cfeb7d5f510763ba33a9a4ec73259d7d6ea86fdb/Rules/AvoidGlobalFunctions.cs#L18-L20
All of that is fine, and it may be that PSScriptAnalyzer users are having success with it, but I'm not really sure if anyone is using it.
There are two problems:
- We aren't using (and don't seem to need) MEF in PowerShell Core (it apparently has been ported, but it's not clear to what extent).
- MEF loads assemblies differently to PowerShell
This problem raised itself in https://github.com/PowerShell/PSScriptAnalyzer/pull/1133, where a rule that depended on an external assembly, which in turn depended on a third assembly failed to load only in .NET Framework (and behaved differently across PowerShell versions).
The error looked like this:
System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
at System.Reflection.Assembly.GetTypes()
at System.ComponentModel.Composition.Hosting.AssemblyCatalog.get_InnerCatalog()
at System.ComponentModel.Composition.Hosting.AssemblyCatalog.GetEnumerator()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Microsoft.Windows.PowerShell.ScriptAnalyzer.SafeDirectoryCatalog..ctor(String folderLocation, IOutputWriter outputWriter)
System.ComponentModel.Composition.CompositionException: The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) Could not load file or assembly 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Resulting in: An exception occurred while trying to create an instance of type 'Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseCompatibleCommands'.
Resulting in: Cannot activate part 'Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseCompatibleCommands'.
Element: Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseCompatibleCommands --> Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseCompatibleCommands --> AssemblyCatalog (Assembly="Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules, Version=1.17.1.0, Culture=neutral, PublicKeyToken=null")
Resulting in: Cannot get export 'Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseCompatibleCommands (ContractName="Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.IScriptRule")' from part 'Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseCompatibleCommands'.
Element: Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseCompatibleCommands (ContractName="Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.IScriptRule") --> Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.UseCompatibleCommands --> AssemblyCatalog (Assembly="Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules, Version=1.17.1.0, Culture=neutral, PublicKeyToken=null")
Resulting in: Cannot set import 'Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer.ScriptRules (ContractName="Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.IScriptRule")' on part 'Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer'.
Element: Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer.ScriptRules (ContractName="Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.IScriptRule") --> Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer
at System.ComponentModel.Composition.CompositionResult.ThrowOnErrors(AtomicComposition atomicComposition)
at System.ComponentModel.Composition.Hosting.ComposablePartExportProvider.Compose(CompositionBatch batch)
at Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer.LoadRules(Dictionary`2 result, CommandInvocationIntrinsics invokeCommand, Boolean loadBuiltInRules)
At some point, the compatibility rule would depend on Microsoft.PowerShell.CrossCompatibility.dll, which in turn depended on Newtonsoft.Json.dll.
The first load would succeed, but the second would fail because it would only look for Newtonsoft.Json.dll in the directory of powershell.exe rather than in the same directory as Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules.dll.
This was resolved by adding Add-Type $newtonsoftDllPath to ScriptAnalyzer.psm1.
This may not actually be due to MEF, but is worth investigating in any case. The DLL loading differences between Windows PS and PS Core are here:
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne mit den DLL-Ladepfaden in Engine/ScriptAnalyzer.cs um die Zeilen 930-969, lies anschließend ScriptAnalyzer.psm1 und die Regelmetadaten in Rules/AvoidGlobalFunctions.cs. Vergleiche das im Issue beschriebene Verhalten von Windows PowerShell und PowerShell Core mit dem Fehler aus Pull Request 1133; als erledigt gilt ein dokumentierter, getesteter Ersatz oder eine klare Klärung, ob MEF entfernt werden sollte.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- csharp, powershell
- Bereich
- devtools
- Issue-Typ
- Refactoring
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Aktivitätsstatus
- Veraltet
- Klarheit
- Muss geklärt werden
- Anfängerfreundlichkeit
- 25/100