Sending Text To BMC (iDRAC, XClarity, iLO, Etc) Remote Consoles

I wasn’t planning on writing a post on this but after spending far too long looking for a simple solution I figured it was worth sharing. Plus I haven’t blogged in a while so this is what you get 😀.

The problem

You’re connected to the remote console using Dell iDRAC, Lenovo XClarity, HP iLO, or whatever flavour of BMC you happen to use. A login prompt is on the screen that doesn’t allow text to be pasted and the BMC doesn’t have a Paste as keystrokes function.

The password you need to enter is 30+ random characters. This is fine if you only need to do it once but often there are multiple servers or multiple reboots and logins required.

Frustrated person

Let’s get the TL;DR out of the way as there’s a bit more to unpack towards the end.

Sending keys into iDRAC, XClarity, or iLO with PowerShell

PowerShell combined with WScript can target a specific window and send key presses into that Window. Cool. Here’s the code.

function Send-KeysToBMC {
    [CmdletBinding()]

    Param (
        [Parameter(Mandatory=$false)]
        [SecureString]$Text,

        [Parameter(Mandatory)]
        [ValidateSet("iDRAC","XClarity","IMM","iLO")]
        [string]$BMCType
    )

    $WindowTitle = switch ($BMCType) {
        "iDRAC"  {"FPS"; break}      
        "XClarity" {"XClarity"; break} 
        "IMM" {"HTML5"; break}
        "iLO" {"iLO"; break}
    }

    $Window = Get-Process | Select -ExpandProperty MainWindowTitle | ? {$_ -match $WindowTitle}
    if ($null -eq $WindowTitle) {Write-Error "Unable to locate window"}

    if ($null -eq $Text) {$Text = Read-Host -AsSecureString -Prompt "Enter Text"}
    
    $WShell = New-Object -ComObject wscript.shell
    $Result = $WShell.AppActivate($Window)
    if ($Result -eq $True) {
        Sleep 1
        $WShell.SendKeys((New-Object PSCredential "user",$Text).GetNetworkCredential().Password)
    } else {
        Write-Host "Unable to find target window - keys not sent"
    }
}

Let’s skim over what this does. The user provides the BMCType during invocation and we use that to assign a string to the $WindowTitle variable. Our code needs to know the title of the window that contains the remote console. Some are obvious, others like IMM title the remote console window “HTML5 Viewer”.

These could change with different versions so you may need to update the code to suit your needs. Just look at the window title and pick an appropriate string for matching.

IMM Remote Console Title

We then create the WSHell object, change the focus to the remote console window, and finally use the SendKeys method to send the keystrokes.

The MainWindowTitle property can be a little iffy with Chrome (the only browser I tested with). For consistent results it helps to make sure that the remote console is the last window you had selected prior to switching to the PowerShell prompt.

Here’s an example how the code works with Dell iDRAC and a baremetal Windows server.

iDRAC Key Injection with PowerShell

A note on security

The function offers a parameter for the user to supply the text as a SecureString or via Read-Host where again the input is treated as a SecureString. The default PSReadLine module saves text typed into the terminal in the ConsoleHost_history.txt file so we want to avoid pasting in anything sensitive as it could end up being stored in plaintext in the history file.

Lenovo XClarity bug

Lenovo XClarity has a bug that causes the Shift key to get stuck down when Shift and Caps Lock are pressed together. Now I don’t know how exactly the SendKeys method works under the hood, but whatever it does it seems to trigger the bug consistently.

Here is the Lenovo KB: Shift and CapsLock keys not functioning as expected when using XCC remote console on ThinkSystems - Lenovo ThinkAgile and Lenovo ThinkSystem

It was meant to be fixed in Q3 2020 but it looks like it never got done or wasn’t implemented well.

This is what it looks like when we try to inject text into the XClarity console. We’re going to be using the string abc123Xabc123. Notice what happens after the X.

iDRAC Key Injection with PowerShell

The issue persists if manually typing into the console after the injection. You need to either refresh the page or use the fix in the Lenovo support article.

Sadly I began this whole exercise testing with XClarity and didn’t find out about the bug until well after most of my hair had been ripped out.

Can we use JavaScript instead?

JavaScript gives us one advantage in that we don’t need to leave the browser to run PowerShell. Our code could be created as an extension and would make the workflow that much smoother.

The best option I found for using Javascript is to dispatch a KeyboardEvent.

We can send a single key with the following code:

window.dispatchEvent(new KeyboardEvent('keydown', {keyCode: 65}));

Let’s see it in action.

JavaScript KeyboardEvent

What is the keyCode? It’s the JavaScript representation of the character we want to send, but it’s deprecated and not particularly recommended for our use case as it doesn’t work well for characters requiring Shift (uppercase, symbols, etc).

There’s also a keypress event, but this is also deprecated and I could not make it work.

Lastly, I could only make the KeyboardEvent method work in XClarity, I could not get it to trigger in iDRAC.

Can we use the existing BMC JavaScript?

This is another avenue I very briefly explored - remote consoles usually have a virtual keyboard available and there could be existing code we could tap into, maybe a function used by an EventListener or something similar.

The main issue is that we would need to write code per BMC implementation and keep up with any code changes on the vendor side.

Oh, and the Lenovo Virtual Keyboard code is ~9000 lines of this:

Lenovo Virtual Keyboard JS

So while a JavaScript solution would be a cleaner option I’m going to leave it for now - I may revisit it in the future if I ever get that bored.

The PowerShell method works well and I can stick it in my sync’d profile to ensure I have it available wherever I need it.


If you enjoyed this post consider sharing it on , , , or , and .