Write-FunctionCallToHost: a simple cross-platform PowerShell function wrapper

Summary

Since PowerShell Core was released in January (which means it's supported officially), it is now possible to run PowerShell on Windows, macOS and Linux. This means it has become a realistic scripting language to use in a lot more environments.

Not only that, submitting a module to the PowerShell Gallery is a lot easier than you might expect.

In this article we're going to submit a simple module to the PowerShell gallery and then install (and run) it on Windows, macOS and Linux machines. As usual, the code (what little there is) can be found in GitHub, although you don't need to download it from there as you can install it through PowerShell.

And, of course, I intend to use the specific function I've published (Write-FunctionCallToHost) in some other scripts in the future.

And don't forget, it's all open source so, if you want to learn more, the main PowerShell GitHub repository is worth checking out.

Background

Ever since writing my first production PowerShell script in 20111, I've thought it was pretty cool. In my current contract role, I'm working as a DevOps engineer and my main work machine is a MacBook Pro (I know). Since this is the first time I've ever used a Mac in anger2, I thought it was also the perfect time to have a look at PowerShell Core and see if it really is cross-platform.

Write-FunctionCallToHost

As part of a separate PowerShell script I'm going to release in a few days, I thought it would be handy to have a way to wrap function calls and to write them to the screen. The function itself is nice and short and this article is more about the process than the specific function.

Here is part of the script in question (with the full version being available at https://github.com/TomChantler/Write-FunctionCallToHost/blob/master/src/Write-FunctionCallToHost.psm1):

I have omitted the long, comment-based help which appears when you use the Get-Help command (but it's in the linked file on GitHub). It's outside the scope of this article, but you can read (a lot) more about it here and you can use my script as a starting point to create your own.

The last line is quite important. Export-ModuleMember is used to denote which functions are to be exported by the module. It's a good habit to specify these explicitly.

What does it do?

Write-FunctionCallToHost wraps a function call and emits a bit of text before and after making the call (and optionally suppresses any output generated by the called command). And that's it.

The best way to see what it does is to run PS> Get-Help Write-FunctionCallToHost -Help, but let's not get ahead of ourselves.

How to publish a PowerShell Module to the PowerShell Gallery

It's really simple. Before you start, you need to make sure you've got the latest version of PowerShellGet (which is linked from the homepage of https://powershellgallery.com). You want version 1.6.0 (or later) and you can check your version by running:

PS> Get-Module PowerShellGet  

Once you've created your .psm1 module file similar to the above (which is very similar to an ordinary .ps1 file, with the addition of a call to Export-ModuleMember), you should create a .psd1 module manifest, which you can do automatically like this:

PS> New-ModuleManifest -Path 'C:\GitHub\Write-FunctionCallToHost\src\Write-FunctionCallToHost.psd1' -Author 'Tom Chantler' -CompanyName 'TomSSL' -RootModule '.\Write-FunctionCallToHost.psm1' -Description 'Write-FunctionCallToHost wraps an existing PowerShell function (or simple block of script) to give a more user-friendly output.'  

You can edit the .psd1 file afterwards, so don't worry too much about getting it all right first time.

Now you need to choose where to publish it. I chose to publish mine to the PowerShell Gallery which required me to sign up and then to grab my API key.

You can publish it like this:

PS> Publish-Module -Name .\Write-FunctionCallToHost.psd1 -NuGetApiKey '<your api key taken from powershellgallery.com>'  

Publish PowerShell Module

You can find it in the PowerShell Gallery at https://www.powershellgallery.com/packages/Write-FunctionCallToHost/

Installing Write-FunctionCallToHost

You can install Write-FunctionCallToHost by running the following command:

PS> Install-Module -Name Write-FunctionCallToHost  

When you try to install a module from the PowerShell Gallery, it will warn you that the repository is untrusted and prompt you to decide whether or not to proceed. This makes perfect sense when you consider the fact that anybody can upload anything to the PSGallery without it being reviewed by Microsoft and thus it's possible that people might put malicious stuff in there, or just stuff that doesn't work properly. If you like, you can tell PowerShell to trust this repository, but based on what I've just written, that doesn't feel like a very good idea.

PowerShell prompting for installation of untrusted module

There are a couple of ways around this issue.

You can either allow the user interaction and just say Yes when prompted to install the module, or you can add the -Force flag like this:

PS> Install-Module -Name Write-FunctionCallToHost -Force  

Here is a cool animated gif I made which shows the installation on Windows.
Install Write-FunctionCallToHost animated gif

If you want to fund out how to use the function, you can use the interactive help.

PS> Get-Help Write-FunctionCallToHost  
PS> Get-Help Write-FunctionCallToHost -Example  
PS> Get-Help Write-FunctionCallToHost -Online  

Pay particular attention to the last one (with the -Online flag). That will bring you here (to this blog post, which also links you to the GitHub repository).

As usual, the code is in GitHub: https://github.com/TomChantler/Write-FunctionCallToHost

And, just for a more complete view, here is what it looks like on MacOS (installation and then showing the interactive help):

Installing Write-FunctionCallToHost on MacOS and displaying help

Testing the function

Let's test the function by using it to wrap a simple call to my blog and then optionally suppressing the output. The following command is fairly self-explanatory:

Write-FunctionCallToHost -FunctionToCall { (iwr https://tomssl.com).Links.Count } -InitialMessage "I'm going to load Tom's blog and count the links" -FinalMessage "I've loaded it and counted them" -SuppressOutput $false  

This is what it looks like on Windows 10:
Testing on Windows This is what it looks like on MacOS (I had to recapture this image a day later than the others, hence the number of links being 63):
Testing on MacOS This is what it looks like on Linux:

Testing on Linux

Success.

IMPORTANT NOTE: Right now, the installation process doesn't seem to work properly on Ubuntu 16.04. In the end it appears to be related to a problem whereby the -ExcludeVersion flag doesn't work in PowerShellGet.

In brief, instead of being able to install my module via PS> Install-Module -Name WriteFunctionCallToHost (which failed silently), I had to do the following:

How I installed Write-FunctionCallToHost on Ubuntu 16.04 LTS

PS> Install-Package -Provider NuGet -Source https://www.powershellgallery.com/api/v2 -Name Write-FunctionCallToHost -Destination '/tmp/' -Verbose -Debug  
PS> Test-ModuleManifest -Path /tmp/Write-FunctionCallToHost.1.0.0/Write-FunctionCallToHost -Verbose  
PS> Import-Module /tmp/Write-FunctionCallToHost.1.0.0/Write-FunctionCallToHost -Verbose

You can read more about this bug here and here.

Conclusion

As we have seen, submitting a PowerShell module to the PowerShell Gallery (or, indeed, any other PowerShell repository) is very easy to do. And having done so, installing it on either Windows, macOS or Linux3 is also simple. If you're targeting various different types of environments and haven't already tried PowerShell, it might be time to take a look.

You can find Write-FunctionCallToHost in GitHub and also in the PowerShell Gallery and you can install it via PS> Install-Module -Name Write-FunctionCallToHost


  1. It ran a SQL script, produced a CSV and then emailed it to a bunch of people and was a replacement for a load of VBScript inside a SQL DTS module.

  2. Not as much anger as you might think; I'm super-chilled since reading the stoics.

  3. With the exception of Linux, it would seem. Or maybe just Ubuntu 16.04. It's still possible, mind you.