-1

WMI commands can either receive explicit credentials as an argument (the -Credential flag), or run in the security context of the user running the script if no credentials are provided.

Right now, my script looks like this:

if ($Creds) { # if the user provided credentials
    Invoke-WMIMethod -Credential $Creds <...something...>
    ... hundreds more lines of Invoke-WMIMethod code ...
else { # user did not supply credentials, use current security context
    Invoke-WMIMethod <...something...>
    ... same exact hundreds of lines of Invoke-WMIMethod code, without -Credential .... 
}

In other words, the only difference is the -Credential flag. Is there any way I can consolidate this huge if-else into one block of code?

AlwaysQuestioning
  • 1,464
  • 4
  • 24
  • 48

2 Answers2

2

Use splatting for dynamically passing arguments to a cmdlet, like this:

$params = @{
  'Class'        = 'Win32_Foo'
  'ComputerName' = 'bar'
  ...
}

if ($cred) {
  $params['Credential'] = $cred
}

Invoke-WmiMethod @params

or like this:

$optional_params = @{}
if ($cred) {
  $optional_params['Credential'] = $cred
}

Invoke-WmiMethod -Class Win32_Foo -Computer bar ... @optional_params

The technique should already be available in PowerShell v2.0.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • So, using the second example, if I add `@optional_params` to the end of every `Invoke-WMIMethod`, then it will only add `-Credential $Cred` if I assign it a value like you did? – AlwaysQuestioning Feb 06 '17 at 20:17
  • How about you just *try* it and see for yourself? – Ansgar Wiechers Feb 06 '17 at 20:26
  • The reason I ask is because of the performance implications. I imagine this adds more overhead than the other solution proposed. – AlwaysQuestioning Feb 06 '17 at 20:33
  • Run both kinds of statements a couple hundred or thousand times and measure execution time. Then compare the results and you'll know without any of us having to speculate about it. It really is as simple as that. – Ansgar Wiechers Feb 06 '17 at 20:51
  • I would argue that asking a question about performance is within scope of determining the best answer for a question. In most cases, performance is not a matter of speculation. – AlwaysQuestioning Feb 06 '17 at 21:58
  • Unfortunately, this solution does not seem to work, because it evaluates to "$null" when no username/password are given. – AlwaysQuestioning Feb 06 '17 at 22:27
  • 1
    @AnsgarWiechers's code should work fine if used properly. Put up a sample of your code if you think it's not. You don't want to set the Hashtable key/value entry at all if your credential isn't meant to be specified. Setting it with a `$null` value will be just like specifying `-Credential $null`. The performance implications will be negligible, but as Ansgar points out, the only way to evaluate it for your specific situation is for you to measure it in *your* specific situation... – Matthew Wetmore Feb 07 '17 at 00:12
  • @AlwaysQuestioning Please provide evidence. Update your question with the code that "evaluates to $null". Include all errors you're getting. – Ansgar Wiechers Feb 07 '17 at 09:06
  • @AnsgarWiechers I created an updated question addressing your splatting suggestion http://stackoverflow.com/questions/42301329/splatting-input-string-was-not-in-a-correct-format – AlwaysQuestioning Feb 17 '17 at 15:27
0

It doesn't look like the current security context is available to be passed in as a credential object (ref this question).

Fortunately, invoke-wmimethod's use of the credential attribute appears to behave as if it wasn't specified when provided a null value. So if $cred is empty then invoke-wmimethod -credential $cred <...something...> should behave the same as invoke-wmimethod <...something...>.

Now, even better might be just to keep the if else and remove any duplicate code. So, instead of:

if ($Creds) { # if the user provided credentials
    Invoke-WMIMethod -Credential $Creds <...something...>
    ... hundreds more lines of code ...
else { # user did not supply credentials, use current security context
    Invoke-WMIMethod <...something...>
    ... same exact hundreds of lines of code .... 
}

You would have:

if ($Creds) { # if the user provided credentials
    $myresults = Invoke-WMIMethod -Credential $Creds <...something...>
else { # user did not supply credentials, use current security context
    $myresults = Invoke-WMIMethod <...something...>
}


    ... hundreds more lines of code using $myresults...
Community
  • 1
  • 1
James Santiago
  • 2,883
  • 4
  • 22
  • 29
  • Well, it produces a pop-up prompt for credentials something like 50 times (one for each Invoke-WMIMethod command, I imagine). So this wont work. However, once I cancel out of all them it seems to produce the expected output. Is there a way I can disable the prompt, or (better yet) provide a value that wont produce a prompt? – AlwaysQuestioning Feb 06 '17 at 20:12
  • Maybe try setting the `$Cred` variable to `$null` if the user doesn't supply credentials. – James Santiago Feb 06 '17 at 21:50
  • Didn't work either. I'll keep looking for a solution. – AlwaysQuestioning Feb 06 '17 at 22:27