mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
Add PuTTY Session Settings command to the Config panel for PuTTY Saved Sessions.
Fix handling of the plus (+) character in PuTTY session names.
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
Fixed issue MR-392 - Sessions Panel - context menu entries need to be context aware
|
||||
Fixed issue MR-422 - Gives error Object reference not set to an instance of an object.
|
||||
Fixed issue MR-424 - Import of a few Linux SSH2 hosts discovered via the port scan tool results in a UE
|
||||
Added PuTTY Session Settings command to the Config panel for PuTTY Saved Sessions.
|
||||
Fixed an exception or crash when choosing unnamed colors for themes.
|
||||
Fixed possible error "Control does not support transparent background colors" when modifying themes.
|
||||
Fixed changes to the active theme not being saved reliably.
|
||||
Fixed handling of the plus (+) character in PuTTY session names.
|
||||
Changed Internet Explorer to no longer force IE7 compatibility mode.
|
||||
Changed the "Launch PuTTY" button in the "Options" dialog to open PuTTY from the path the user has currently set, instead of what was previously saved.
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ Namespace Config
|
||||
If raw Then
|
||||
sessionNames.Add(sessionName)
|
||||
Else
|
||||
sessionNames.Add(Web.HttpUtility.UrlDecode(sessionName))
|
||||
sessionNames.Add(Web.HttpUtility.UrlDecode(sessionName.Replace("+", "%2B")))
|
||||
End If
|
||||
Next
|
||||
Return sessionNames.ToArray()
|
||||
@@ -89,7 +89,7 @@ Namespace Config
|
||||
Dim sessionKey As RegistryKey = sessionsKey.OpenSubKey(sessionName)
|
||||
If sessionKey Is Nothing Then Return Nothing
|
||||
|
||||
sessionName = Web.HttpUtility.UrlDecode(sessionName)
|
||||
sessionName = Web.HttpUtility.UrlDecode(sessionName.Replace("+", "%2B"))
|
||||
|
||||
Dim sessionInfo As New Connection.PuttySession.Info
|
||||
With sessionInfo
|
||||
|
||||
@@ -13,22 +13,19 @@ Namespace Connection
|
||||
|
||||
#Region "Commands"
|
||||
<Command(),
|
||||
DisplayName("Edit in PuTTY")> _
|
||||
Public Sub LaunchPutty()
|
||||
LocalizedDisplayName("strPuttySessionSettings")> _
|
||||
Public Sub SessionSettings()
|
||||
Try
|
||||
Dim process As New Process
|
||||
With process.StartInfo
|
||||
.UseShellExecute = False
|
||||
If Settings.UseCustomPuttyPath Then
|
||||
.FileName = Settings.CustomPuttyPath
|
||||
Else
|
||||
.FileName = App.Info.General.PuttyPath
|
||||
End If
|
||||
End With
|
||||
process.Start()
|
||||
process.WaitForExit()
|
||||
Dim puttyProcess As New PuttyProcessController
|
||||
If Not puttyProcess.Start() Then Return
|
||||
If puttyProcess.SelectListBoxItem(PuttySession) Then
|
||||
puttyProcess.ClickButton("&Load")
|
||||
End If
|
||||
puttyProcess.SetControlText("Button", "&Cancel", "&Close")
|
||||
puttyProcess.SetControlVisible("Button", "&Open", False)
|
||||
puttyProcess.WaitForExit()
|
||||
Catch ex As Exception
|
||||
MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strPuttyStartFailed & vbNewLine & ex.Message, True)
|
||||
MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strErrorCouldNotLaunchPutty & vbNewLine & ex.Message, False)
|
||||
End Try
|
||||
End Sub
|
||||
#End Region
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
Imports System.ComponentModel
|
||||
Imports mRemoteNG.Messages
|
||||
Imports mRemoteNG.My
|
||||
Imports mRemoteNG.Tools
|
||||
Imports PSTaskDialog
|
||||
Imports WeifenLuo.WinFormsUI.Docking
|
||||
Imports mRemoteNG.App.Runtime
|
||||
Imports mRemoteNG.Themes
|
||||
@@ -2059,19 +2061,19 @@ Public Class frmOptions
|
||||
|
||||
Private Sub btnLaunchPutty_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLaunchPutty.Click
|
||||
Try
|
||||
Dim process As New Process
|
||||
With process.StartInfo
|
||||
.UseShellExecute = False
|
||||
If chkUseCustomPuttyPath.Checked Then
|
||||
.FileName = txtCustomPuttyPath.Text
|
||||
Else
|
||||
.FileName = App.Info.General.PuttyPath
|
||||
End If
|
||||
End With
|
||||
process.Start()
|
||||
process.WaitForExit()
|
||||
Dim puttyProcess As New PuttyProcessController
|
||||
Dim fileName As String
|
||||
If chkUseCustomPuttyPath.Checked Then
|
||||
fileName = txtCustomPuttyPath.Text
|
||||
Else
|
||||
fileName = App.Info.General.PuttyPath
|
||||
End If
|
||||
puttyProcess.Start(fileName)
|
||||
puttyProcess.SetControlText("Button", "&Cancel", "&Close")
|
||||
puttyProcess.SetControlVisible("Button", "&Open", False)
|
||||
puttyProcess.WaitForExit()
|
||||
Catch ex As Exception
|
||||
MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strPuttyStartFailed & vbNewLine & ex.Message, True)
|
||||
cTaskDialog.MessageBox(Application.Info.ProductName, Language.strErrorCouldNotLaunchPutty, "", ex.Message, "", "", eTaskDialogButtons.OK, eSysIcons.Error, Nothing)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
|
||||
18
mRemoteV1/Language/Language.Designer.vb
generated
18
mRemoteV1/Language/Language.Designer.vb
generated
@@ -1542,6 +1542,15 @@ Namespace My
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Looks up a localized string similar to PuTTY could not be launched..
|
||||
'''</summary>
|
||||
Friend Shared ReadOnly Property strErrorCouldNotLaunchPutty() As String
|
||||
Get
|
||||
Return ResourceManager.GetString("strErrorCouldNotLaunchPutty", resourceCulture)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Looks up a localized string similar to Decryption failed. {0}.
|
||||
'''</summary>
|
||||
@@ -4394,6 +4403,15 @@ Namespace My
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Looks up a localized string similar to PuTTY Session Settings.
|
||||
'''</summary>
|
||||
Friend Shared ReadOnly Property strPuttySessionSettings() As String
|
||||
Get
|
||||
Return ResourceManager.GetString("strPuttySessionSettings", resourceCulture)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
'''<summary>
|
||||
''' Looks up a localized string similar to PuTTY Settings.
|
||||
'''</summary>
|
||||
|
||||
@@ -2226,4 +2226,10 @@ mRemoteNG will now quit and begin with the installation.</value>
|
||||
<data name="strMenuSessionRetrieve" xml:space="preserve">
|
||||
<value>Retrieve</value>
|
||||
</data>
|
||||
<data name="strPuttySessionSettings" xml:space="preserve">
|
||||
<value>PuTTY Session Settings</value>
|
||||
</data>
|
||||
<data name="strErrorCouldNotLaunchPutty" xml:space="preserve">
|
||||
<value>PuTTY could not be launched.</value>
|
||||
</data>
|
||||
</root>
|
||||
40
mRemoteV1/Tools/EnumWindows.vb
Normal file
40
mRemoteV1/Tools/EnumWindows.vb
Normal file
@@ -0,0 +1,40 @@
|
||||
Namespace Tools
|
||||
Public Class EnumWindows
|
||||
Public Shared Function EnumWindows() As List(Of IntPtr)
|
||||
Dim handleList As New List(Of IntPtr)
|
||||
|
||||
HandleLists.Add(handleList)
|
||||
Dim handleIndex As Integer = HandleLists.IndexOf(handleList)
|
||||
Win32.EnumWindows(AddressOf EnumCallback, handleIndex)
|
||||
HandleLists.Remove(handleList)
|
||||
|
||||
Return handleList
|
||||
End Function
|
||||
|
||||
Public Shared Function EnumChildWindows(ByVal hWndParent As IntPtr) As List(Of IntPtr)
|
||||
Dim handleList As New List(Of IntPtr)
|
||||
|
||||
HandleLists.Add(handleList)
|
||||
Dim handleIndex As Integer = HandleLists.IndexOf(handleList)
|
||||
Win32.EnumChildWindows(hWndParent, AddressOf EnumCallback, handleIndex)
|
||||
HandleLists.Remove(handleList)
|
||||
|
||||
Return handleList
|
||||
End Function
|
||||
|
||||
Private Shared ReadOnly HandleLists As New List(Of List(Of IntPtr))
|
||||
|
||||
Private Shared Function EnumCallback(hwnd As Integer, lParam As Integer) As Boolean
|
||||
HandleLists(lParam).Add(hwnd)
|
||||
Return True
|
||||
End Function
|
||||
|
||||
' ReSharper disable ClassNeverInstantiated.Local
|
||||
Private Class Win32
|
||||
' ReSharper restore ClassNeverInstantiated.Local
|
||||
Public Delegate Function EnumWindowsProc(ByVal hwnd As Integer, ByVal lParam As Integer) As Boolean
|
||||
Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As Integer) As Boolean
|
||||
Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As IntPtr, ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As Integer) As Boolean
|
||||
End Class
|
||||
End Class
|
||||
End Namespace
|
||||
181
mRemoteV1/Tools/ProcessController.vb
Normal file
181
mRemoteV1/Tools/ProcessController.vb
Normal file
@@ -0,0 +1,181 @@
|
||||
Imports System.Runtime.InteropServices
|
||||
Imports System.Text
|
||||
Imports mRemoteNG.My
|
||||
|
||||
Namespace Tools
|
||||
Public Class ProcessController
|
||||
#Region "Public Methods"
|
||||
Public Function Start(ByVal fileName As String, Optional ByVal arguments As CommandLineArguments = Nothing) As Boolean
|
||||
With Process.StartInfo
|
||||
.UseShellExecute = False
|
||||
.FileName = fileName
|
||||
If arguments IsNot Nothing Then .Arguments = arguments.ToString()
|
||||
End With
|
||||
|
||||
If Not Process.Start() Then Return False
|
||||
GetMainWindowHandle()
|
||||
|
||||
Return True
|
||||
End Function
|
||||
|
||||
Public Function SetControlVisible(ByVal className As String, ByVal text As String, Optional ByVal visible As Boolean = True) As Boolean
|
||||
If Process Is Nothing OrElse Process.HasExited Then Return False
|
||||
If Handle = IntPtr.Zero Then Return False
|
||||
|
||||
Dim controlHandle As IntPtr = GetControlHandle(className, text)
|
||||
If controlHandle = IntPtr.Zero Then Return False
|
||||
|
||||
Dim nCmdShow As Integer
|
||||
If visible Then
|
||||
nCmdShow = Win32.SW_SHOW
|
||||
Else
|
||||
nCmdShow = Win32.SW_HIDE
|
||||
End If
|
||||
|
||||
Win32.ShowWindow(controlHandle, nCmdShow)
|
||||
|
||||
Return True
|
||||
End Function
|
||||
|
||||
Public Function SetControlText(ByVal className As String, ByVal oldText As String, ByVal newText As String) As Boolean
|
||||
If Process Is Nothing OrElse Process.HasExited Then Return False
|
||||
If Handle = IntPtr.Zero Then Return False
|
||||
|
||||
Dim controlHandle As IntPtr = GetControlHandle(className, oldText)
|
||||
If controlHandle = IntPtr.Zero Then Return False
|
||||
|
||||
Dim result As IntPtr = Win32.SendMessage(controlHandle, Win32.WM_SETTEXT, 0, New StringBuilder(newText))
|
||||
If Not result.ToInt32() = Win32.TRUE Then Return False
|
||||
|
||||
Return True
|
||||
End Function
|
||||
|
||||
Public Function SelectListBoxItem(ByVal itemText As String) As Boolean
|
||||
If Process Is Nothing OrElse Process.HasExited Then Return False
|
||||
If Handle = IntPtr.Zero Then Return False
|
||||
|
||||
Dim listBoxHandle As IntPtr = GetControlHandle("ListBox")
|
||||
If listBoxHandle = IntPtr.Zero Then Return False
|
||||
|
||||
Dim result As IntPtr = Win32.SendMessage(listBoxHandle, Win32.LB_SELECTSTRING, -1, New StringBuilder(itemText))
|
||||
If result.ToInt32() = Win32.LB_ERR Then Return False
|
||||
|
||||
Return True
|
||||
End Function
|
||||
|
||||
Public Function ClickButton(ByVal text As String) As Boolean
|
||||
If Process Is Nothing OrElse Process.HasExited Then Return False
|
||||
If Handle = IntPtr.Zero Then Return False
|
||||
|
||||
Dim buttonHandle As IntPtr = GetControlHandle("Button", text)
|
||||
If buttonHandle = IntPtr.Zero Then Return False
|
||||
|
||||
Dim buttonControlId As Integer = Win32.GetDlgCtrlID(buttonHandle)
|
||||
Win32.SendMessage(Handle, Win32.WM_COMMAND, buttonControlId, buttonHandle)
|
||||
|
||||
Return True
|
||||
End Function
|
||||
|
||||
Public Sub WaitForExit()
|
||||
If Process Is Nothing OrElse Process.HasExited Then Return
|
||||
Process.WaitForExit()
|
||||
End Sub
|
||||
#End Region
|
||||
|
||||
#Region "Protected Fields"
|
||||
Protected Process As New Process
|
||||
Protected Handle As IntPtr = IntPtr.Zero
|
||||
Protected Controls As New List(Of IntPtr)
|
||||
#End Region
|
||||
|
||||
#Region "Protected Methods"
|
||||
Protected Function GetMainWindowHandle() As IntPtr
|
||||
If Process Is Nothing OrElse Process.HasExited Then Return IntPtr.Zero
|
||||
|
||||
Process.WaitForInputIdle(Settings.MaxPuttyWaitTime * 1000)
|
||||
|
||||
Handle = IntPtr.Zero
|
||||
Dim startTicks As Integer = Environment.TickCount
|
||||
While Handle = IntPtr.Zero And Environment.TickCount < startTicks + (Settings.MaxPuttyWaitTime * 1000)
|
||||
Process.Refresh()
|
||||
Handle = Process.MainWindowHandle
|
||||
If Handle = IntPtr.Zero Then Threading.Thread.Sleep(0)
|
||||
End While
|
||||
|
||||
Return Handle
|
||||
End Function
|
||||
|
||||
Protected Function GetControlHandle(ByVal className As String, Optional ByVal text As String = "") As IntPtr
|
||||
If Process Is Nothing OrElse Process.HasExited Then Return IntPtr.Zero
|
||||
If Handle = IntPtr.Zero Then Return IntPtr.Zero
|
||||
|
||||
If Controls.Count = 0 Then
|
||||
Controls = EnumWindows.EnumChildWindows(Handle)
|
||||
End If
|
||||
|
||||
Dim stringBuilder As New System.Text.StringBuilder
|
||||
Dim controlHandle As IntPtr = IntPtr.Zero
|
||||
For Each control As IntPtr In Controls
|
||||
Win32.GetClassName(control, stringBuilder, stringBuilder.Capacity)
|
||||
If (stringBuilder.ToString() = className) Then
|
||||
If String.IsNullOrEmpty(text) Then
|
||||
controlHandle = control
|
||||
Exit For
|
||||
Else
|
||||
Win32.SendMessage(control, Win32.WM_GETTEXT, stringBuilder.Capacity, stringBuilder)
|
||||
If (stringBuilder.ToString() = text) Then
|
||||
controlHandle = control
|
||||
Exit For
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
Next
|
||||
|
||||
Return controlHandle
|
||||
End Function
|
||||
#End Region
|
||||
|
||||
#Region "Win32"
|
||||
' ReSharper disable ClassNeverInstantiated.Local
|
||||
Private Class Win32
|
||||
' ReSharper restore ClassNeverInstantiated.Local
|
||||
' ReSharper disable InconsistentNaming
|
||||
' ReSharper disable UnusedMethodReturnValue.Local
|
||||
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
|
||||
Public Shared Sub GetClassName(ByVal hWnd As IntPtr, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer)
|
||||
End Sub
|
||||
|
||||
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
|
||||
Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
|
||||
End Function
|
||||
|
||||
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
|
||||
Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As System.Text.StringBuilder) As IntPtr
|
||||
End Function
|
||||
|
||||
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
|
||||
Public Shared Function GetDlgCtrlID(ByVal hwndCtl As Integer) As Integer
|
||||
End Function
|
||||
|
||||
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
|
||||
Public Shared Function ShowWindow(ByVal hWnd As IntPtr, ByVal nCmdShow As Integer) As Boolean
|
||||
End Function
|
||||
|
||||
Public Const LB_ERR As Integer = -1
|
||||
Public Const LB_SELECTSTRING As Integer = &H18C
|
||||
|
||||
Public Const WM_SETTEXT As Integer = &HC
|
||||
Public Const WM_GETTEXT As Integer = &HD
|
||||
Public Const WM_COMMAND As Integer = &H111
|
||||
|
||||
Public Const SW_HIDE As Integer = 0
|
||||
Public Const SW_SHOW As Integer = 5
|
||||
|
||||
Public Const [TRUE] As Integer = 1
|
||||
' ReSharper restore UnusedMethodReturnValue.Local
|
||||
' ReSharper restore InconsistentNaming
|
||||
End Class
|
||||
#End Region
|
||||
End Class
|
||||
End Namespace
|
||||
|
||||
17
mRemoteV1/Tools/PuttyProcessController.vb
Normal file
17
mRemoteV1/Tools/PuttyProcessController.vb
Normal file
@@ -0,0 +1,17 @@
|
||||
Imports mRemoteNG.My
|
||||
|
||||
Namespace Tools
|
||||
Public Class PuttyProcessController
|
||||
Inherits ProcessController
|
||||
Public Overloads Function Start(Optional ByVal arguments As CommandLineArguments = Nothing) As Boolean
|
||||
Dim filename As String
|
||||
If Settings.UseCustomPuttyPath Then
|
||||
filename = Settings.CustomPuttyPath
|
||||
Else
|
||||
filename = App.Info.General.PuttyPath
|
||||
End If
|
||||
Return Start(filename, arguments)
|
||||
End Function
|
||||
End Class
|
||||
End Namespace
|
||||
|
||||
@@ -188,6 +188,7 @@
|
||||
<Compile Include="Config\Config.Settings.Save.vb" />
|
||||
<Compile Include="Config\ConfirmClose.vb" />
|
||||
<Compile Include="Config\PuttySessions.vb" />
|
||||
<Compile Include="Tools\EnumWindows.vb" />
|
||||
<Compile Include="Tools\PropertyGridCommandSite.vb" />
|
||||
<Compile Include="Connection\PuttySession.Info.vb" />
|
||||
<Compile Include="Root\PuttySessions.Info.vb" />
|
||||
@@ -272,6 +273,8 @@
|
||||
<Compile Include="Security\Security.Impersonator.vb" />
|
||||
<Compile Include="Security\Security.Save.vb" />
|
||||
<Compile Include="Tools\IeBrowserEmulation.vb" />
|
||||
<Compile Include="Tools\ProcessController.vb" />
|
||||
<Compile Include="Tools\PuttyProcessController.vb" />
|
||||
<Compile Include="Tools\ReconnectGroup.Designer.vb">
|
||||
<DependentUpon>ReconnectGroup.vb</DependentUpon>
|
||||
</Compile>
|
||||
|
||||
Reference in New Issue
Block a user