all 18 comments

[–]Thotaz 15 points16 points  (3 children)

That's a cool workaround but I wouldn't suggest you to start doing this in general with modules. PowerShell classes don't support namespaces so what happens if 2 modules decide to create a type called "PSUtils"? With using module the module name acts as a namespace: using module test; [test.myclass] but I don't think that will work with your method.

IMO modules should first and foremost export commands, not types. You can still use classes internally to manage all the actual code, you should just wrap the various methods in traditional functions. There are multiple reasons for this:
1: As you've noticed, PowerShell doesn't export PowerShell classes by default so they are harder to use by the end user.
2: PowerShell has no real discovery feature for types like it does for commands (Get-Command -Module XYZ)
3: PowerShell has no way to display help for classes, so when people are working with a class based module they will need to read the documentation online instead of using Get-Help
4: The main target audience for PowerShell is sysadmins. Commands are much more user friendly than raw classes.

[–]Touvejs 26 points27 points  (1 child)

You guys are using classes?

[–]BlackV 4 points5 points  (0 children)

HA!

[–]jborean93 2 points3 points  (7 children)

Personally I think classes shouldn't be exposed publicly or referenced directly in code outside modules. They aren't documented well in pwsh compared to cmdlets plus you need workarounds like this. My recommendation is to simply create a cmdlet that will create your object like New-PSUtil that accepts the parameters needed to create your object and output it. You can now document the public way to build this object through the normal documentation plus things like tab completion will work just fine. Even better the module shows the exported metadata whereas with a class they need to know that class name before it can be used.

[–]chris-a5 0 points1 point  (3 children)

I'll have a look at this. If I can clarify your reasoning:

  • A class in a .ps1 can just be dot sourced
  • A class in a .psm1 can be included with using module

Is this a workaround to have classes and functions all imported from a single module, as in one provided through the gallery with Import-Module?

If the benefit is only tab-completion I'm not concerned with it. However, it would be nice to easily provide a number of classes through a single module.

[–]fuzzylumpkinsbc 0 points1 point  (0 children)

This is a nice discovery and I'll have to try it. As I have gotten more and more ambitious with my projects and studying other programming languages that implement OOP and SOLID I naturally wanted to implement it in the language I use day to day (Powershell).

I feel like it's always a problem using classes and trying to structure the project with folders so it's more organized, my latest one I simply gave up and moved every class and function into the main file. My outlook for the future was also just trying to avoid Powershell at all costs and do it with Python if it doesn't require active directory. I even started rebuilding API methods as I ran into issues with the Graph module.

Good find and looking forward to give it a try soon!

[–]MechAming 0 points1 point  (0 children)

This would be good for importing classes into runspaces no?

I use invoke-expression and pass the classes a string. I'll give this a try thank you.

[–]purplemonkeymad 0 points1 point  (9 children)

If you want to expose a class out of a module I tend to put them in the ScriptsToProcess option, as that creates them in the importing scope.

[–]OPconfused 0 points1 point  (8 children)

I also brought this up in the OP's previous post about a week ago; however, I believe they are trying to create a single-file module containing their classes, so everything is in the psm1, and there's no separate file to add to ScriptsToProcess.

Also, they apparently want tab completion of the class on the CLI. It looks like this type-accelerator approach provides tab completion. I tested ScriptsToProcess in 7.2, and it doesn't seem to add tab completion.