Freigeben über


why share-able functions shouldn't be in your PowerShell profile

<imho>

I cringe when I come across web sites or blog posts that start out with something like "shove this function into your $profile".  Your $profile should be a small, focused thing (this philosophy is a recurring theme) that's all about things like aliases and one-line functions (at times, effectively aliases) that make your typing or shell usage life easier, like when I have "vc" as a function that just does a set-location to take me to a particular spot in the source tree.

For anything that's not particular to you (so, things like your prompt function are still perfectly sane to have in your $profile, even if it's complicated), I would much rather see those functions as their own *.ps1 files.  That keeps you from having to clutter your $profile with more stuff, it makes it easier to version them separately (IMHO, good admins keep their scripts in a version control system, but I can save that rant for a different post), and it makes it easier to collaborate, as you can get updated/patched versions from other people more easily.

Another benefit of having it be its own file (no "function" declaration - first executable code is the param line) is not having to worry about function scope declaration - I also see multiple blog posts where they start preaching that everyone should be doing "function global:foo" everywhere because they had a function declaraction in a bar.ps1 file, ran bar.ps1 (not via dot-sourcing, just as a script), and the function didn't show up (this is by (imho, good) design, as function declarations default to script scope).  Get rid of that function global:foo line altogether and just make it foo.ps1 and you're all set.

This doesn't even get into the security benefits of signed scripts (also something worth tackling separately).

Now, admittedly, "we" kind of cause this line of thought, with such things as:

https://www.microsoft.com/technet/scriptcenter/resources/qanda/nov06/hey1121.mspx

Of course, this function will last only as long as your current Windows PowerShell session. If you’d like multiplynumbers to be a permanent addition to Windows PowerShell then add the function to your Windows PowerShell profile. To do that, type notepad $profile to bring up your default profile, add the function call, and then save the profile.

Please - when you have that function that's more than a line or two in your $profile, and could potentially be of use to someone else, move it out into a functionname.ps1 file and put it in your path (or put it in a new "scripts" dir and then put *that* into your path).  $env:path += ';d:\scripts' or something similar into your $profile should do the trick fine.

If I have lots of machines that I use the same scripts from, I can even put the scripts on a share and instead add ';\\server\share\scripts' to my $env:path during my $profile - now it's clearly better than a massive $profile as I can keep a central store of these scripts and not need to edit N different copies of $profile if I do an update to a given script.  Admittedly, some people have a 'network share' profile where $profile includes sourcing the \\server\share\profile.ps1, and that's fine, but I still think it's better off to keep the profile as simple as it can be (but no simpler).

It's a far more robust, maintainable, shareable, and supportable situation if I can just keep a few dozen different scripts in a scripts dir rather than having to see my $profile grow out of control into a huge file.  Please, think of the children.

</imho>