3

I'm going to start by saying I'm still pretty much a rookie at PowerShell and hoping there is a way to do this.

We have a utils.ps1 script that contains just functions that we dot source with in other scripts. One of the functions returns back a default value if a value is not passed in. I know I could check $args and such but what I wanted was to use the function for the default value in the parameters.

param(
    [string]$dbServer=$(Get-DefaultParam "dbServer"), 
    [string]$appServer=$(Get-DefaultParam "appServer")
)

This doesn't work since the Util script hasn't been sourced yet. I can't put the dot source first because then params doesn't work as it's not the top line. The utils isn't a module and I can't use the #require.

What I got working was this

param(
    [ValidateScript({ return $false; })]
    [bool]$loadScript=$(. ./Utils.ps1; $true),
    [string]$dbServer=$(Get-DefaultParam "dbServer"), 
    [string]$appServer=$(Get-DefaultParam "appServer")
)

Create a parameter that loads the script and prevent passing a value into that parameter. This will load the script in the correct scope, if I load it in the ValidateScript it's not in the correct scope. Then the rest of the parameters have access to the functions in the Utils.ps1. This probably is not a supported side effect, aka hack, as if I move the loadScript below the other parameters fail since the script hasn't been loaded.

  1. PowerShell guarantee parameters will always load sequential?
  2. Instead should we put all the functions in Utils.ps1 in global scope? this would need to run Utils.ps1 before the other scripts - which seems ok in scripting but less than ideal when running the scripts by hand
  3. Is there a more supported way of doing this besides modules and #require?
  4. Better to not use default value of params and just code all the checks after sourcing and check $args if we need to run the function?
2
  • The only negative implication I see with your above solution is that if someone uses the -LoadScript parameter, it won't dot-source your script. That said, this is a pretty clever solution to your problem, although it requires you to lug your Utils.ps1 around everywhere. Commented Jan 8, 2020 at 15:15
  • @BendertheGreatest They can't use the loadScript as the ValidationScript only runs if the value is passed in and then it returns false saying whatever value the pass is invalid. I do feel it's a hack. I tired to use the psm1 in the same directory but couldn't figure out how to make #require load it. I assume it would need to move to the standard module directory. Working on a dev team with lots of dev and didn't want to make it so they all had to add a module Commented Jan 8, 2020 at 15:21

1 Answer 1

3

It would be beneficial to instead turn that script into a PowerShell Module, despite your statement that you desire to avoid one. This way, your functions are always available for use as long as the module is installed. Also, despite not wanting to use it, the #Require directive is how you put execution constraints on your script, such as PowerShell version or modules that must be installed for the script to function.


If you really don't want to put this into a module, you can dot-source utils.ps1 from the executing user's $profile. As long as you don't run powershell.exe with the -NoProfile parameter, the profile loads with each session and your functions will be available for use.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.