How to use interfaces in Powershell defined via Add-Type?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



How to use interfaces in Powershell defined via Add-Type?



I developed a PowerShell module that relied on a .NET Assembly for some operations.

I refactored this module to not need that Assembly and noticed some strange behavior, which blocks me from removing the class at last:


Add-Type -TypeDefinition "public interface ICanTalk string talk(); " -Language CSharp

class Talker : ICanTalk
[string] talk() return "Well hello there";



If you run this commands interactively, it will succeed.
But as soon as I run it "en-bloque" in ISE or from a psm1 file, it will throw an error, stating it cannot find the interface defined in the Add-Type call.


Add-Type



I can reproduce the problem in both Windows-PowerShell and PowerShell Core (6.0.2)



What is the reason for the different behaviour and how can I tackle it?





Don't trust the ISE.
– TheIncorrigible1
Aug 10 at 21:58





Probably you are right, but the sample is a minimal reproduction of the problem and it also applies to psm1 files loaded via ipmo.
– TGlatzer
Aug 10 at 22:00





Thanks for the clarification. I can say your test case occurred for me as well in 6.0.3. It feels like the Add-Type command isn't being executed.
– TheIncorrigible1
Aug 10 at 22:06


Add-Type





Perhaps classes are parsed before anything else has the chance to execute?
– TGlatzer
Aug 10 at 22:09





Possible duplicate of Using .Net Objects within a Powershell (V5) Class
– PetSerAl
Aug 11 at 1:56




2 Answers
2



Apparently PowerShell will read the file and handle class-definitions before executing the code.



To solve this problem, the Add-Type needs to be put into an own script file, which is run before the module loads (or in ISE, just run the code before running the class definitions).


Add-Type



This can be accomplished by using ScriptsToProcess from the PSD1 file.



Kudos to @TheIncorrigible1 for putting me on the track.



To complement your own answer:



PowerShell class and enum definitions are parsed before execution begins and any types referenced in such definitions must either be:


class


enum



loaded into the current the session beforehand.



[only partially implemented as of Windows PowerShell v5.1 / PowerShell Core 6.1.0]
loaded via a using module / using assembly statement at the very
top of the file.


using module


using assembly



using module already works, but only if the referenced types are themselves class / enum definitions.


using module


class


enum



Currently, types loaded from assemblies - whether via a module containing assemblies imported with using module or using assembly to directly load an assembly - aren't yet detected.


using module


using assembly


using module


using assembly



The workaround in the meantime is to load the referenced types via a separate script beforehand, by using the module manifest's NestedModules entry.


NestedModules


ScriptsToProcess


Add-Type


NestedModules






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard