Managing dependencies of Powershell modules - powershell

I have my custom Powershell script module, let's call it PsHandyCmdlets. In its manifest the following line is found: RequiredModules = #('<Another module not necessarily installed yet>')
The RequiredModules property is supposed to guarantee that any module listed here is imported into global scope before importing the current module. This would fail if that module can't be located on the machine.
Does Powershell provide a mechanism for ensuring that these modules are installed when PsHandyCmdlets is installed? If there isn't, is there a best practice in place for handling this scenario?

This is a good write up by Rene Hernandez on his blog talking about this topic and offers up some solutions. He also provides links to a PowerShell module (PSDepend) that could be leveraged to address this challenge. (link gone, but provided link to example)
https://github.com/renehernandez/powershell-dependencies-example
The module PSDepend was authored by RamblingCookieMonster which I have admired their work as being innovative and solid.
https://github.com/RamblingCookieMonster/PSDepend

Related

Powershell Core and Powershell Modules

I have a need to create a Module that can Run in Powershell 7 and use commandlets from Powershell 5.
I want to save this module as an artifact and publish in AzureDevOps Artifacts.
The Module is for auditing cross platform system information. The problem is that some of the cmdlets are Windows platform specific such as Get-WindowsFeature. I also want to use PowerShell Core functions such as Azure Cosmos communication cmdlets.
How do I load functions only on certain platforms?
Do you need to write something in C# to achieve this, or nest a module for a specific platform in my main module?
The comments mention correctly you can wrap up a command with a version check.
That's a great option for a small use command.
I'd recommend as a better module design to just have two modules, one for each platform.
This would allow you to better seperate your work, and not rely on many embedded logic steps that conditionally run actions on different platforms. To me this is just cleaner.
As you get started on modules, I'd highly recommend you use a template to bootstrap your project. I've found that it saves a lot of time, and sets me up for best practices.
My personal favorite is PSModuleDevelopment which you can use like this:
Install-Module PSModuleDevelopment -Scope CurrentUser
Get-Help 'Invoke-PSMDTemplate'
This is very similar to the loading structure some very mature projects like dbatools and PSFramework use. If you use this, you benefit primarily from:
Being able to seperate all your functions into their own files and load them easily
Some nice enhancements to preload configurations in your module
Pester test template included
I stopped trying to write my own module structure and just leveraged a development module like this, and it's been very helpful for me.
Good luck!

How to know what silentArg to use when creating Chocolatey packages?

How do I find out what silentArg I need to use for creating a Chocolatey package?
I know that each installer will have different silentArgs but I just don't know where I can find which one has which. Also, I am using strictly .exe files (embedded too).
You'll have to work with the documentation/support provided by the software maintainer, but I'll provide some suggestions here.
Typically, MSI installers support the same silent installation parameters (many will simply work with /qn), but sometimes an installer might support additional variables or an input file you must provide.
EXE installers are a free-for-all, unfortunately. It depends on what parameters are coded into the setup program to support, even for the setup.exe installers that call another MSI. Depending on what built the EXE installer, you might be able to try some common options. The following techniques are suggestions to get you started on de-mystifying different common EXE installers:
A setup.exe that extracts and runs MSIs might be able to have the MSIs extracted and run on their own, but this is likely unsupported by the software maintainer. You will need to test this on your own per package to know if this approach will work.
Nullsoft Installers typically support a common array of options that can be used to deploy your application.
InstallShield Installers typically support the /S parameter along with an answer file, but you would still need to work with the software maintainer or read the software documentation to know what to put in the answer file.
As I've mentioned in other answers, the best thing you can do here is reach out to the vendor or software maintainer and ask for a deployment guide for that software, or at least documentation on how to silently install.

PowerShell Use third party module without installing it

I am sure this would be possible but can't find anything useful.
I have written a lan scanner script. To automate things as much as possible, I don't rely on any input from user. The script checks the local interface IP address and uses Indented Network Tools module to calculate the number of possible IP addresses and pings each one.
The problem is since I am using a third party tool, I have to install it on any machine that I want to use this script on. Is there a way I can include this third party module with my script like put them in the same folder and not have to install it separately?
That really depends on how you want to deploy your module to other machines. If you want to share it on a network share or distribute a zip package, then you can include these dependencies along with your module. Just put Indented.Common and Indented.NetworkTools in one directory with your script definition, like so:
MyModule/
└╴MyModule.psm1
└╴Indented.Common/
└╴IndentedNetworkTools/
Then, you can load these modules directly from MyModule.psm1 (without installing them to a global modules path):
import-module $psscriptroot\Indented.Common\Indented.Common.psm1
import-module $psscriptroot\Indented.NetworkTools\Indented.NetworkTools.psm1
And that's it. This will also work if you have a normal .ps1, not a .psm1 module.
Perhaps a more elegant way would be to use WMF5 PackageManagement. Declare Indented.NetworkTools as dependencies (NestedModules) in MyModule.psd1, then publish it on PSGallery. Then, you can just say Install-Module MyModule on other machines - this will install MyModule and it's dependencies.
The problem with this approach is that any declared dependencies have to be also available on PowershellGallery (which Indented.* modules are not).

When to choose development of a PowerShell Module over PowerShell Script

I am about to write a PowerShell Script for Windows administrators, in order to help them in certain tasks related to deployment of a web application.
Is there any reason I should favor or exclude the development of a PowerShell Module (.psm1) instead of doing a PowerShell script (.ps1)?
Arguments to develop a Script
simplicity: I think that using a script is a bit easier and more straightforward for Windows Administrators as it does not require the module to be installed (but I might be wrong as I am not a Windows Admin!).
faster development: developing a module requires more careful programming an exposure to internal methods. It is like designing an API an thus must be more rigorous.
Arguments to develop a Module:
reusability: this is the first thing that comes to mind: if the administrator wants to integrate our script in his own script, it might be easier for him to reuse a module exposing one (or several) cmdlet rather than invoke our script?
...
If you know the common use case of PS scripts vs PS modules, or the technical limitations of each choice, it might help.
To understand what modules can do for you, read this: https://learn.microsoft.com/en-us/powershell/scripting/developer/module/writing-a-windows-powershell-module?view=powershell-7.1
In a nutshell,
Windows PowerShell modules allow you to partition, organize, and abstract your Windows PowerShell code into self-contained, reusable units. With these reusable units, administrators, script developers, and cmdlet developers can easily share their modules directly with others. Script developers can also repackage third-party modules to create custom script-based applications. Modules, similar to modules in other scripting languages such as Perl and Python, enable production-ready scripting solutions that use reusable, redistributable components, with the added benefit of enabling you to repackage and abstract multiple components to create custom solutions.
If your script already has functions and is not just written to perform a single task, you can just rename it to .PSM1 to convert it to module. If you are not using functions, of course, there is no choice but to go for .ps1. In such a case, each .ps1 will be used to perform a single task. I always prefer modules when sharing the scripts I write with others.
I like modules for the ability to "hide" functions/variables and only export the ones that I want.

How do I create powershell 2.0 modules?

I've heard powershell 2.0 CTP has modules, but I can't find much example code or instructions. I've read what little help there seems to be online...
But I just keep getting "The term 'Add-Module' is not recognized as a cmdlet..." when I try and load a module.
Any help would be gratefully received!
Edit (July 2010)
Please note this question is based on powershell 2.0 CTP and is therefore a year and half out of date! Please see Samuel Jack's answer for help with the powershell 2.0 RTM.
With the Win7 build, Add-Module is gone. The new cmdlet is Import-Module. The easiest way to create a module is rename a PS1 file to a PSM1 file. From there you can do all sorts of things including the module manifest.
I'm no Powershell expert, but here's what I just figured out using PowerShell 2.0 RTM.
Suppose you want to create a module called MyModule:
Make sure that you have created the folder %My Documents%\WindowsPowershell\Modules
Create a folder inside Modules called MyModule
Put your code in a file inside MyModule and name the file MyModule.psm1
Remember to use the Export-ModuleMember command as the last thing in your script file. Export-ModuleMember -Function * -Alias * will export all functions and aliases
In scripts where you want to use the module, use the command Import-Module MyModule
By default Powershell is configured not to run any kinds of scripts from files, so you need to alter the security settings. Set-ExecutionPolicy Unrestricted will get you going if you're not concerned about scripts needing to be signed.
Here's a little bit of information.
http://huddledmasses.org/powershell-modules/
http://blogs.msdn.com/mediaandmicrocode/archive/2008/08/10/microcode-all-about-modules-windows-powershell-ctp2.aspx
Let's hope that the upcoming CTP3 has some useful documentation about modules.
Modules will hopefully solve a few problems. Right now, we can use dot sourcing to get functions, variables, and scripts into a PowerShell session's global scope.
The problem is that this can pollute your session with all kinds of global variables and helper functions that an end user may not want/need directly.
Modules will allow you as an author to build scripts and only make certain functions/variables avaiable to the end user of the module.
They also essentially replace the concept of a PSSnapin. You can use Add-Module Some.dll to add an assembly that has cmdlets in it.
What is really cool is what is called a Module Manifest. This is a hash table that basically specifies all kinds of dependcies as well as author, name, GUID Identifier, and version number. When a user loads a module that has a module manifest, it will check all the dependencies and run any scripts the module author deems necessary.
There should be some decent documentation on these when CTP3 ships.
Hope that helps a bit.
Andy
Windows PowerShell v2.0: TFM (sapienpress.com) has information and samples in one of the chapters. It's available as an ebook which is updated as new CTPs are released. I also blogged about them on ConcentratedTech.com, and there's been discussion on them at PowerShellCommunity.org in the forums.