Using Alternate Credentials with WMI and PowerShell [Hyper-V]

Using Alternate Credentials with WMI and PowerShell [Hyper-V]

  • Comments 6


The other day I was reading a post on Tore Lervik’s site and noticed that he had written some PowerShell scripts that would allow you to connect to a remote server using different user credentials than the ones you are logged in with.  This is something that I need to do quite often – and I have been doing it by just starting PowerShell using “runas” – but this approach is a heck of a lot more elegant.

It works by using a new command that was introduced in PowerShell 2.0: Get-Credential.  When you issue this command you will see a Windows credential dialog, like this:

image

You can then take the object returned by Get-Credential and pass it into Get-WMIObject using the –Credential parameter.

While this is quite useful – I have found that it has a couple of limitations to be aware of:

  1. You need to pass the credential object every time you use Get-WMIObject.  If you have a simple script that only calls Get-WMIObject once or twice this is not a big deal; but it can get really annoying really fast if you are getting a lot of WMI objects.
  2. PowerShell will object if you try to use alternative credentials and you are connecting to the local computer (as opposed to connecting over the network to a remote computer).  This means that you have to wrap every Get-WMIObject call in some logic to check if you are connecting to the local computer or not (at this point refer to my first issue – this becomes a real pain if you are having to do it a lot).

To try this out I decided to take my virtual machine inventory script from last week and modify it to take alternative credentials.  In order to handle the issue of alternate credentials not working for the local computer – I put in a prompt that asks if you want to use alternate credentials or not:

# Prompt for the Hyper-V Server to use
$HyperVServer = Read-Host "Specify the Hyper-V Server to use (enter '.' for the local computer)"
 
# Setup parameters for prompt to ask if the user wants to use alternative credentials
$message = "Do you want to use alternative user credentials?"
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Use alternative user credentials."
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Use your current user credentials."
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
 
# Ask the user if they want to use alternative credentials
$result = $host.ui.PromptForChoice($null, $message, $options, 0) 
 
switch ($result)
    {
        0 {# Prompt for the user credentials to use
           $wmiCredentials = Get-Credential -credential $null
 
           # Get all guest KVP data objects on the server in question, using the credentials provided
           $Kvps = gwmi -namespace root\virtualization Msvm_KvpExchangeComponent -computername $HyperVServer -Credential $wmiCredentials}
           
        1 {# Get all guest KVP data objects on the server in question
           $Kvps = gwmi -namespace root\virtualization Msvm_KvpExchangeComponent -computername $HyperVServer}
    }
 
# Create an empty hashtable
$table = @{}
 
# Go over each of the guest KVP data objects
foreach ($Kvp in [array] $Kvps) 
  {
   # Get the OSName value out of the guest KVP data
   $xml = [xml]($Kvp.GuestIntrinsicExchangeItems | ? {$_ -match "OSName"})
   $entry = $xml.Instance.Property | ?{$_.Name -eq "Data"}
 
   # Filter out unknown operating systems
   if ($entry.Value) {$value = $entry.Value} else {$value = "Unknown"}
 
   # Count up the values and store it in a hashtable
   if ($table.ContainsKey($value)) 
      {$table[$value] = $table[$value] + 1 }
   else
      {$table[$value] = 1}
   }
 
# Display the results in a nicely formated and sorted manner
$table.GetEnumerator() | Sort-Object Name | Format-Table -Autosize

 

I have also attached a copy of this script.

Cheers,
Ben

Attachment: WhatIsRunning.zip
Leave a Comment
  • Please add 2 and 7 and type the answer here:
  • Post
  • Hi Ben,

    The easiest way to use Get-Credential is either just "Get-Credential" or "Get-Credential <username>", the last one will fill your username box in the login prompt with the given text.

    Apparently there are some ways to store credentials in a script, but I have not looked into it yet. :)

  • Hi Ben,

    I ran into the same issue last month but my powershell code runs in a non-interactive service so I just check if $env:computername is a substring of $HyperVServer rooted at index 0 (in my case $HyperVServer is a FQDN). Also, my substring search is case-insensitive, just in case.

    Oh yeah, if $env:computername is empty (length zero) then I just log that and assume $HyperVServer is remote.

    Anyhow, please let me know if there are any problems with my approach.

    thanks,

    Marc

  • > This means that you have to wrap every Get-WMIObject call in some logic to check if you are connecting to the local computer or not

    This is easy to avoid with a splat parameter:

    $extraParams = {}

    if using credentials {

     $extraParams[credential] = result of get-credentials

    }

    Then pass (without quotes) "@extraParams" to each relevant cmdlet. Spat parameters are very useful where the set of parameters you want to pass is determined programmatically.

  • And if you don't want the GUI popup, you can get the username and password from the console:

    http://blogs.msdn.com/powershell/archive/2008/06/20/getting-credentials-from-the-command-line.aspx

  • Thanks for all the extra information!  I have posted an updated script that uses some of this here: http://blogs.msdn.com/virtual_pc_guy/archive/2010/04/26/using-alternate-credentials-with-wmi-and-powershell-take-2-hyper-v.aspx

    Cheers,

    Ben

  • What I was really looking for is, is there a way to have Windows Virtual PC remember part of your credentials.  I have Windows 7, and I have Virtual PC setup with WinXP.  My Virtual WinXP has joined the same domain as my Win7 host.  I login to my WinXP using my domain username/password.

    Well, my password changes from time to time.  But Virtual PC remembers my credentials, and keeps supplying my old password.  Too many bad password attempts, and my account locks.

    I want Virtual PC to remember my username, my domain, but not my password.  I want to fill in my password.  Once the login fails, I get the login screen back with my username and domain still filled in, but no password.  That's what I want when I fire up Virtual PC.

    Can this be done?  If so, How?

Page 1 of 1 (6 items)