Open Regedit and Connect to Remote Host





4.00/5 (1 vote)
Code to open regedit and connect to remote host
Introduction
This code accepts a hostname, opens REGEDIT.EXE and enters the keystrokes to connect to a remote registry.
Background
I couldn't find any way of programmatically opening regedit and connecting to a remote host. After watching REGMON (by Sysinternals) open regedit and automatically navigate to a specific registry key, I was inspired to write this.
Since I couldn't find any other way of doing it, I figured others might find this useful.
Using the Code
Sub ControlRegedit
Accepts a hostname As String
then opens regedit
, navigates to where you enter a hostname, enters the hostname into the box and presses enter.
Sub ActivateRegeditWindow
Activates any window titled "Registry Editor".
Sub Snooze
Accepts number of milliseconds As Long
. Pauses execution for number of milliseconds.
Sub KillRegedit
Kills process called "regedit
".
Imports System.Runtime.InteropServices
Imports System.Text.RegularExpressions
' Key sequence to connect to remote registry:
' With regedit.exe open type:
' 1) ALT+F Open file menu
' 2) C Select "Connect Remote Registry"
' 3) release ALT Let go of ALT key (obvious to us humans
' but the computer has to be told)
' 4) type hostname Type hostname of remote host
' 5) press enter Pressing enter clicks OK
Public Class RegeditConnector
Const VK_MENU = &H12 ' ALT
Const VK_F = &H46 ' F
Const VK_C = &H43 ' C
Const VK_Enter = &HD ' ENTER
Const VK_Left = &H25 ' LEFT arrow
Const VK_Right = &H27 ' RIGHT arrow
Const VK_Home = &H24 ' HOME
Const VK_ESCAPE = &H1B ' ESCAPE
<DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, _
CharSet:=CharSet.Unicode, EntryPoint:="keybd_event", _
ExactSpelling:=True, SetLastError:=True)> _
Public Shared Sub keybd_event(ByVal bVk As Byte, ByVal bScan As Byte, _
ByVal dwFlags As IntPtr, ByVal dwExtraInfo As IntPtr)
End Sub
' Function to terminate a process
Private Declare Function TerminateProcess Lib "kernel32" Alias "TerminateProcess" _
(ByVal hProcess As Long, ByVal uExitCode As Long) As Long
' btnOpenReg
Private Sub btnOpenReg_Click(ByVal sender As System.Object, ByVal e _
As System.EventArgs) Handles btnOpenReg.Click
' Oops, someone clicked the button too soon
If txtRegRemoteHost.Text = "enter hostname" Then Exit Sub
' Var to store hostname
Dim strHostname As String = Nothing
' Finds any alphanumeric string, underscore, hyphen and period
Dim reAlphaNumeric As New Regex("[a-zA-Z0-9_\-\.]")
' Assign txtRegRemoteHost to strHostname if there is something to add.
If txtRegRemoteHost.Text <> "" Then
strHostname = txtRegRemoteHost.Text
Else
Exit Sub
End If
' If \\<hostname> was entered then replace the \\ with nothing
If Mid(strHostname, 1, 2) = "\\" Then strHostname = _
Replace(strHostname, "\\", "")
' If all characters are valid then assume its a hostname and run regedit
If reAlphaNumeric.IsMatch(strHostname) = True Then ControlRegedit(strHostname)
End Sub
''' <summary>
''' Sub to send keystrokes to regedit
''' </summary>
''' <param name="strHostname">Hostname to connect regedit to As String</param>
''' <remarks></remarks>
Private Sub ControlRegedit(ByVal strHostname As String)
Dim intCharValue = Nothing
Dim hexCharValue = Nothing
Dim strCharToConvert As String = Nothing
Dim strSingleCharacter = Nothing
' If Reuse Regedit isn't checked then kill Regedit and sleep for a half second
If cbxReuseRegedit.Checked = False Then KillRegedit() : Snooze(500)
Process.Start("regedit.exe") ' Run regedit.exe
Snooze(500) ' Pause for .5 second for regedit to appear
ActivateRegeditWindow() ' Activate Regedit Window
' The following 3 lines are optional. They collapse the local registry
' tree down to "My Computer" so its easier to see the remote hosts registry.
keybd_event(VK_ESCAPE, 0, 0, 0) ' Hit escape twice to clear
' any existing regedit dialogs
keybd_event(VK_Home, 0, 0, 0) ' Go to top of Registry tree
' and by hitting HOME key
keybd_event(VK_Left, 0, 0, 0) ' Hit Left arror to collapse
' local registry tree
Snooze(25)
ActivateRegeditWindow() ' Activate Regedit Window again
' in case it lost focus
keybd_event(VK_MENU, 0, 0, 0) ' Press and hold ALT key
keybd_event(VK_F, 0, 0, 0) ' Press F
keybd_event(VK_MENU, 0, 2, 0) ' Release ALT key
keybd_event(VK_C, 0, 0, 0) ' Hit C to select "Connect Network Registry"
Snooze(100) ' Wait for "Select Computer"
' dialog to appear
ActivateRegeditWindow() ' Activate Regedit Window again
' in case it lost focus
' Convert each char in the hostname to HEX values and type the keystrokes
' into the object name field
For i As Integer = 1 To Len(strHostname) ' Loop once for each
' character entered
strSingleCharacter = Mid(strHostname, i, 1) ' Grab single character and
' assign to
' strSingleCharacter
intCharValue = Asc(strSingleCharacter.ToUpper) ' Get the decimal value of
' single character and
' assign to intCharValue
hexCharValue = "&H" & Hex(intCharValue) ' Convert intCharValue to
' Hex and prepend &H to make
' it look like real
' authentic Hex
keybd_event(hexCharValue, 0, 0, 0) ' Press key based on its
' hex value
Snooze(20) ' Pause briefly (this
' prevents missing letters)
ActivateRegeditWindow() ' Activate Regedit Window
' again in case it
' lost focus
Next
keybd_event(VK_Enter, 0, 0, 0) ' Press enter which clicks OK
If cbxExitWhenFinished.Checked = True Then End ' If "Exit When Finished"
' is checked then End
End Sub
''' <summary>
''' Sub to activate Registry Editor window
''' </summary>
''' <remarks></remarks>
Private Sub ActivateRegeditWindow()
Try
AppActivate("Registry Editor") ' Make Registry Editor the active window
Catch ex As Exception When ex.Message = _
"Process 'Registry Editor' was not found."
MsgBox("Error opening regedit")
End ' Can't find registry editor window so end
End Try
End Sub
''' <summary>
''' Sub to pause execution for n number of milliseconds
''' </summary>
''' <param name="Milliseconds">Number of milliseconds to pause As Long</param>
''' <remarks></remarks>
Private Sub Snooze(ByVal Milliseconds As Long)
System.Threading.Thread.Sleep(Milliseconds)
End Sub
''' <summary>
''' Sub to Kill Regedit process if found.
''' </summary>
''' <remarks></remarks>
Private Sub KillRegedit()
Dim myProcesses As Process() = Process.GetProcessesByName("regedit")
Dim myProcess As Process
For Each myProcess In myProcesses
If myProcess.MainWindowTitle = "Registry Editor" Then myProcess.Kill()
Next myProcess
End Sub
' Clear "enter hostname" if found otherwise SelectAll text
Private Sub txtRegRemoteHost_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles txtRegRemoteHost.Click
If txtRegRemoteHost.Text = "enter hostname" Then txtRegRemoteHost.Text = ""
If txtRegRemoteHost.Text > "" Then txtRegRemoteHost.SelectAll()
End Sub
' Pressing Enter in hostname textbox clicks btnOpenReg
Private Sub txtRegRemoteHost_KeyDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtRegRemoteHost.KeyDown
If e.KeyCode = Keys.Enter Then
btnOpenReg.PerformClick()
End If
End Sub
End Class
Points of Interest
This code could easily be modified to work with any other program as long as the app can be manipulated by the keyboard.
Note: When entering key strokes with kbd_event
it simply presses the key, in lower case, as you would with the keyboard. But when pressing ALT, CTRL, SHIFT or the Windows keys they stay down until told to release. So experimenting with this code can cause your keyboard to do funny things. If they seem stuck; pressing each of the ALT, CTRL, SHIFT and Windows keys a few times seems to release them.
History
I plan on writing a console version that accepts "regconnect \\<hostname>
" in the near future. I will post it when I do.
- 11/13/2008 2:32 PM - While writing the console version, I found that backslash gets converted into the hex value for the Windows key (&H5C). So entering
\\L
for a hostname gets interpreted into<Windows key><Windows key>L
which is the hotkey for "lock the desktop".