简体   繁体   中英

Powershell calling a function if script has mandatory parameters

I'm pretty new to PowerShell but loving it for automating loads of tasks on our Windows machines. I love that you can call functions from other scripts, however the scripts I have written all use parameters the user can provide (so it's easier for colleagues to use them).

There is one parameter in particular that is usually mandatory in my scripts. The problem I'm facing is calling functions from scripts with mandatory parameters.

Here's a simple example:

Param(

 [Parameter()]
 [ValidateNotNullOrEmpty()]
 [string]$VirtualMachine=$(throw "Machine name missing!"),

 [int]$Attempts = 150

 )

Function DoSomething($VirtualMachine, $Attempts){

    write("$VirtualMachine and $Attempts")

 }

Running this as a script you would provide -VirtualMachine "VMnameHere" -Attempts 123 . Running this would produce VMnameHere and 123 . Perfect! However.. If I try to call this as a function from another script..

Example here:

. ".\Manage-Machine.ps1"

DoSomething -VirtualMachine "nwb-thisisamachine" -Attempts 500

This produced an error:

Machine name missing!
At C:\Users\something\Desktop\Dump\play\Manage-Machine.ps1:33 char:28
+  [string]$VirtualMachine=$(throw "Machine name missing!"),
+                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Machine name missing!:String) [], RuntimeException
    + FullyQualifiedErrorId : Machine name missing!

Which is clearly because the field is mandatory. Am I doing something wrong in how I'm calling the function in this case? Is there an alternative way to calling the function if the script it belongs to has mandatory parameters, because if I remove the validation for the parameter, it all works.

Would love some input,

Thank you!

I would use [parameter(Mandatory = $true)] and remove =$(throw "Machine name missing!") .

You can then run powershell with the -NonInteractive flag ( documentation link ) and any missing mandatory parameters will cause an error and a non-zero exit code will be returned.

This return code should be picked up by your CI process and it itself will handle the error.

I'm not sure it's such a great idea to do this, but it sounds like the following would work:

Param(

  [ValidateNotNullOrEmpty()]
  # Do NOT use = $(Throw ...) or [Parameter(Mandatory)].
  [string]$VirtualMachine, 

  [int]$Attempts = 150

)

# Determine if the script is being "dot-sourced".
# Note: The `$MyInvocation.Line -eq ''` part detects being run from the
#       ISE or Visual Studio Code, which implicitly perform sourcing too.
$isDotSourced = $MyInvocation.InvocationName -eq '.' -or $MyInvocation.Line -eq ''

# NOT sourced? Enforce mandatory parameters.
if (-not $isDotSourced) {
  if (-not $VirtualMachine) { Throw "Machine name missing!" }
}

Function DoSomething($VirtualMachine, $Attempts) {
  "$VirtualMachine and $Attempts"
}


# NOT sourced? Call the default function or
# do whatever you want the script to do when invoked as a whole.
if (-not $isDotSourced) {
  DoSomething $VirtualMachine $Attempts
}
  • . .\\Manage-Machine.ps1 . .\\Manage-Machine.ps1 will then merely define the functions ( DoSomething in this case), for later invocation;
    since none of the script parameters are technically declared as mandatory, invocation without parameters will succeed (unlike in your attempt, where the throw statement invariably kicked in - whether directly invoked or dot-sourced).

  • .\\Manage-Machine.ps1 , by contrast, will enforce the presence of a $VirtualMachine parameter value and instantly call DoSomething , passing the parameter values through.

Note that, of course, your functions could benefit from typing your parameters and adding validation attributes, too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM