Improve handling of variables in external tool arguments.

Code cleanup.
This commit is contained in:
Riley McArdle
2013-11-15 23:27:10 -06:00
parent fd73b28061
commit b6004117e6
31 changed files with 1156 additions and 560 deletions

View File

@@ -9,6 +9,7 @@
Removed invalid "Site" configuration option from PuTTY Saved Sessions.
Fixed PuTTY Saved Sessions still showing if all saved sessions are removed.
Fixed config panel showing settings from previously loaded connection file after loading a new one.
Improved handling of variables in external tool arguments.
1.72 (2013-11-13):
Fixed issue MR-592 - Unable to run VBS script as an external tool

10
Local.testsettings Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="Local" id="2a25bb82-f5ff-4a67-b5e9-c6aaa54d1e80" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Description>These are default test settings for a local test run.</Description>
<Deployment enabled="false" />
<Execution>
<TestTypeSpecific />
<AgentRule name="Execution Agents">
</AgentRule>
</Execution>
</TestSettings>

View File

@@ -0,0 +1,145 @@
Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports mRemoteNG.Tools
Imports mRemoteNG.Connection.PuttySession
'''<summary>
'''This is a test class for ExternalToolTest and is intended
'''to contain all ExternalToolTest Unit Tests
'''</summary>
<TestClass()> _
Public Class ExternalToolTest
'''<summary>
'''Gets or sets the test context which provides
'''information about and functionality for the current test run.
'''</summary>
Public Property TestContext() As TestContext
#Region "Additional test attributes"
'
'You can use the following additional attributes as you write your tests:
'
'Use ClassInitialize to run code before running the first test in the class
'<ClassInitialize()> _
'Public Shared Sub MyClassInitialize(ByVal testContext As TestContext)
'End Sub
'
'Use ClassCleanup to run code after all tests in a class have run
'<ClassCleanup()> _
'Public Shared Sub MyClassCleanup()
'End Sub
'
'Use TestInitialize to run code before running each test
'<TestInitialize()> _
'Public Sub MyTestInitialize()
'End Sub
'
'Use TestCleanup to run code after each test has run
'<TestCleanup()> _
'Public Sub MyTestCleanup()
'End Sub
'
#End Region
'''<summary>
'''A test for ParseArguments
'''</summary>
<TestMethod(), _
DeploymentItem("mRemoteNG.exe")> _
Public Sub ParseArgumentsTest()
Dim externalTool As New ExternalTool
' ReSharper disable StringLiteralTypo
externalTool.ConnectionInfo = New Info()
With externalTool.ConnectionInfo
.Name = "EMAN"
.Hostname = "EMANTSOH"
.Port = 9876
.Username = "EMANRESU"
.Password = "DROWSSAP"
.Domain = "NIAMOD"
.Description = "NOITPIRCSED"
.MacAddress = "SSERDDACAM"
.UserField = "DLEIFRESU"
End With
Assert.AreEqual("EMAN, EMANTSOH, 9876, EMANRESU, DROWSSAP, NIAMOD, NOITPIRCSED, SSERDDACAM, DLEIFRESU", externalTool.ParseArguments("%NAME%, %HOSTNAME%, %PORT%, %USERNAME%, %PASSWORD%, %DOMAIN%, %DESCRIPTION%, %MACADDRESS%, %USERFIELD%"))
' ReSharper restore StringLiteralTypo
Assert.AreEqual(Environment.ExpandEnvironmentVariables("%PATH%"), externalTool.ParseArguments("%!PATH%"))
externalTool.ConnectionInfo.Name = "()%!^""<>&|\""\\"
Assert.AreEqual("%%", externalTool.ParseArguments("%%"))
Assert.AreEqual("% %", externalTool.ParseArguments("% %"))
Assert.AreEqual("%-%", externalTool.ParseArguments("%-%"))
Assert.AreEqual("%!%", externalTool.ParseArguments("%!%"))
Assert.AreEqual("%^%", externalTool.ParseArguments("%^%"))
Assert.AreEqual("%%%", externalTool.ParseArguments("%%%"))
Assert.AreEqual("%foobar%", externalTool.ParseArguments("%foobar%"))
Assert.AreEqual("%-foobar%", externalTool.ParseArguments("%-foobar%"))
Assert.AreEqual("%!foobar%", externalTool.ParseArguments("%!foobar%"))
Assert.AreEqual("%-!^\", externalTool.ParseArguments("%-!^\"))
Assert.AreEqual("^(^)^%^!^^\^""^<^>^&^|\\\^""\\", externalTool.ParseArguments("%NAME%"))
Assert.AreEqual("^(^)^%^!^^^""^<^>^&^|\^""\\", externalTool.ParseArguments("%-NAME%"))
Assert.AreEqual("()%!^""<>&|\""\\", externalTool.ParseArguments("%!NAME%"))
Assert.AreEqual("^(^)^%^!^^\^""^<^>^&^|\\\^""\\", externalTool.ParseArguments("%name%"))
Assert.AreEqual("%^(^)^%^!^^\^""^<^>^&^|\\\^""\\", externalTool.ParseArguments("%%name%"))
Assert.AreEqual("^(^)^%^!^^\^""^<^>^&^|\\\^""\\%", externalTool.ParseArguments("%name%%"))
Assert.AreEqual("^(^)^%^!^^\^""^<^>^&^|\\\^""\\ ^(^)^%^!^^\^""^<^>^&^|\\\^""\\", externalTool.ParseArguments("%name% %name%"))
Assert.AreEqual("%-^(^)^%^!^^\^""^<^>^&^|\\\^""\\", externalTool.ParseArguments("%-%name%"))
Assert.AreEqual("^(^)^%^!^^\^""^<^>^&^|\\\^""\\-%", externalTool.ParseArguments("%name%-%"))
Assert.AreEqual("%!^(^)^%^!^^\^""^<^>^&^|\\\^""\\", externalTool.ParseArguments("%!%name%"))
Assert.AreEqual("^(^)^%^!^^\^""^<^>^&^|\\\^""\\!%", externalTool.ParseArguments("%name%!%"))
Assert.AreEqual("\^(^)^%^!^^\^""^<^>^&^|\\\^""\\", externalTool.ParseArguments("\%NAME%"))
Assert.AreEqual("\^(^)^%^!^^\^""^<^>^&^|\\\^""\\NAME%", externalTool.ParseArguments("\%NAME%NAME%"))
Assert.AreEqual("%NAME\%", externalTool.ParseArguments("%NAME\%"))
Assert.AreEqual("""^(^)^%^!^^\^""^<^>^&^|\\\^""\\\\""", externalTool.ParseArguments("""%NAME%"""))
Assert.AreEqual("""^(^)^%^!^^^""^<^>^&^|\^""\\""", externalTool.ParseArguments("""%-NAME%"""))
Assert.AreEqual("""()%!^""<>&|\""\\""", externalTool.ParseArguments("""%!NAME%"""))
Assert.AreEqual("""^(^)^%^!^^\^""^<^>^&^|\\\^""\\", externalTool.ParseArguments("""%NAME%"))
Assert.AreEqual("""^(^)^%^!^^^""^<^>^&^|\^""\\", externalTool.ParseArguments("""%-NAME%"))
Assert.AreEqual("""()%!^""<>&|\""\\", externalTool.ParseArguments("""%!NAME%"))
Assert.AreEqual("^(^)^%^!^^\^""^<^>^&^|\\\^""\\\\""", externalTool.ParseArguments("%NAME%"""))
Assert.AreEqual("^(^)^%^!^^^""^<^>^&^|\^""\\""", externalTool.ParseArguments("%-NAME%"""))
Assert.AreEqual("()%!^""<>&|\""\\""", externalTool.ParseArguments("%!NAME%"""))
Assert.AreEqual(Environment.ExpandEnvironmentVariables("%USERNAME%"), externalTool.ParseArguments("\%USERNAME\%"))
Assert.AreEqual(Environment.ExpandEnvironmentVariables("%USERNAME%"), externalTool.ParseArguments("\%-USERNAME\%"))
Assert.AreEqual(Environment.ExpandEnvironmentVariables("%USERNAME%"), externalTool.ParseArguments("\%!USERNAME\%"))
Assert.AreEqual("\^(^)^%^!^^\^""^<^>^&^|\\\^""\\", externalTool.ParseArguments("\%NAME%"))
Assert.AreEqual("%NAME\%", externalTool.ParseArguments("%NAME\%"))
Assert.AreEqual("\\%NAME\\%", externalTool.ParseArguments("\\%NAME\\%"))
Assert.AreEqual("\\\%NAME\\\%", externalTool.ParseArguments("\\\%NAME\\\%"))
Assert.AreEqual("\\\\%NAME\\\\%", externalTool.ParseArguments("\\\\%NAME\\\\%"))
Assert.AreEqual("\\\\\%NAME\\\\\%", externalTool.ParseArguments("\\\\\%NAME\\\\\%"))
Assert.AreEqual("%NAME%", externalTool.ParseArguments("^%NAME^%"))
Assert.AreEqual("%-NAME%", externalTool.ParseArguments("^%-NAME^%"))
Assert.AreEqual("\%NAME\%", externalTool.ParseArguments("\^%NAME\^%"))
Assert.AreEqual("\%-NAME\%", externalTool.ParseArguments("\^%-NAME\^%"))
Assert.AreEqual("^%NAME^%", externalTool.ParseArguments("^^%NAME^^%"))
Assert.AreEqual("^%-NAME^%", externalTool.ParseArguments("^^%-NAME^^%"))
Assert.AreEqual("^^^^%NAME^^^^%", externalTool.ParseArguments("^^^^^%NAME^^^^^%"))
Assert.AreEqual("^^^^%-NAME^^^^%", externalTool.ParseArguments("^^^^^%-NAME^^^^^%"))
Assert.AreEqual("^^^^%!NAME^^^^%", externalTool.ParseArguments("^^^^^%!NAME^^^^^%"))
Assert.AreEqual("blah%blah", externalTool.ParseArguments("blah%blah"))
Assert.AreEqual("blah^%blah", externalTool.ParseArguments("blah^%blah"))
Assert.AreEqual("blah^^%blah", externalTool.ParseArguments("blah^^%blah"))
Assert.AreEqual("blah^^^%blah", externalTool.ParseArguments("blah^^^%blah"))
Assert.AreEqual("^^^^%-NAME^^^^% ^(^)^%^!^^\^""^<^>^&^|\\\^""\\", externalTool.ParseArguments("^^^^^%-NAME^^^^^% %NAME%"))
End Sub
End Class

View File

@@ -0,0 +1,37 @@
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
' General Information about an assembly is controlled through the following
' set of attributes. Change these attribute values to modify the information
' associated with an assembly.
' Review the values of the assembly attributes
<Assembly: AssemblyTitle("TestProject")>
<Assembly: AssemblyDescription("")>
<Assembly: AssemblyCompany("")>
<Assembly: AssemblyProduct("TestProject")>
<Assembly: AssemblyCopyright("Copyright © 2013")>
<Assembly: AssemblyTrademark("")>
<Assembly: CLSCompliant(True)>
<Assembly: ComVisible(False)>
'The following GUID is for the ID of the typelib if this project is exposed to COM
<Assembly: Guid("8918ad54-4841-44e9-abda-e1b787b02c7c")>
' Version information for an assembly consists of the following four values:
'
' Major Version
' Minor Version
' Build Number
' Revision
'
' You can specify all the values or you can default the Build and Revision Numbers
' by using the '*' as shown below:
' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("1.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")>

View File

@@ -0,0 +1,2 @@
mRemoteNG.exe
Desktop

View File

@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>
</SchemaVersion>
<ProjectGuid>{24E0689D-95C0-4AAB-A93F-B8D6B7F0CB97}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>TestProject</RootNamespace>
<AssemblyName>TestProject</AssemblyName>
<FileAlignment>512</FileAlignment>
<MyType>Windows</MyType>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{F184B08F-C81C-45F6-A57F-5ABD9991F28F}</ProjectTypeGuids>
<ReferencePath>$(DevEnvDir)PublicAssemblies\</ReferencePath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<DefineDebug>true</DefineDebug>
<DefineTrace>true</DefineTrace>
<OutputPath>bin\Debug\</OutputPath>
<DocumentationFile>TestProject.xml</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<DefineDebug>false</DefineDebug>
<DefineTrace>true</DefineTrace>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DocumentationFile>TestProject.xml</DocumentationFile>
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
</PropertyGroup>
<PropertyGroup>
<OptionExplicit>On</OptionExplicit>
</PropertyGroup>
<PropertyGroup>
<OptionCompare>Binary</OptionCompare>
</PropertyGroup>
<PropertyGroup>
<OptionStrict>Off</OptionStrict>
</PropertyGroup>
<PropertyGroup>
<OptionInfer>On</OptionInfer>
</PropertyGroup>
<ItemGroup>
<Reference Include="ADTree">
<HintPath>..\mRemoteV1\References\ADTree.dll</HintPath>
</Reference>
<Reference Include="AxInterop.MSTSCLib">
<HintPath>..\mRemoteV1\obj\Debug\AxInterop.MSTSCLib.dll</HintPath>
</Reference>
<Reference Include="AxInterop.WFICALib">
<HintPath>..\mRemoteV1\obj\Debug\AxInterop.WFICALib.dll</HintPath>
</Reference>
<Reference Include="DiffieHellman">
<HintPath>..\mRemoteV1\References\DiffieHellman.dll</HintPath>
</Reference>
<Reference Include="FilteredPropertyGrid">
<HintPath>..\mRemoteV1\References\FilteredPropertyGrid.dll</HintPath>
</Reference>
<Reference Include="Interop.EOLWTSCOM">
<HintPath>..\mRemoteV1\obj\Debug\Interop.EOLWTSCOM.dll</HintPath>
<EmbedInteropTypes>True</EmbedInteropTypes>
<Private>True</Private>
</Reference>
<Reference Include="Interop.MSTSCLib">
<HintPath>..\mRemoteV1\obj\Debug\Interop.MSTSCLib.dll</HintPath>
<EmbedInteropTypes>True</EmbedInteropTypes>
<Private>True</Private>
</Reference>
<Reference Include="Interop.SHDocVw">
<HintPath>..\mRemoteV1\obj\Debug\Interop.SHDocVw.dll</HintPath>
<EmbedInteropTypes>True</EmbedInteropTypes>
<Private>True</Private>
</Reference>
<Reference Include="Interop.WFICALib">
<HintPath>..\mRemoteV1\obj\Debug\Interop.WFICALib.dll</HintPath>
<EmbedInteropTypes>True</EmbedInteropTypes>
<Private>True</Private>
</Reference>
<Reference Include="IPTextBox">
<HintPath>..\mRemoteV1\References\IPTextBox.dll</HintPath>
</Reference>
<Reference Include="log4net">
<HintPath>..\mRemoteV1\References\log4net.dll</HintPath>
</Reference>
<Reference Include="MagicLibrary, Version=1.7.4.0, Culture=neutral, PublicKeyToken=3a6eb82f876a49bc">
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.VisualBasic.PowerPacks.Vs, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="MiniGeckoBrowser">
<HintPath>..\mRemoteV1\References\MiniGeckoBrowser.dll</HintPath>
</Reference>
<Reference Include="MiniTabControl">
<HintPath>..\mRemoteV1\References\MiniTabControl.dll</HintPath>
</Reference>
<Reference Include="Org.Mentalis.Security">
<HintPath>..\mRemoteV1\References\Org.Mentalis.Security.dll</HintPath>
</Reference>
<Reference Include="PSTaskDialog">
<HintPath>..\mRemoteV1\References\PSTaskDialog.dll</HintPath>
</Reference>
<Reference Include="Skybound.Gecko">
<HintPath>..\mRemoteV1\References\Skybound.Gecko.dll</HintPath>
</Reference>
<Reference Include="stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.DirectoryServices" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="Tamir.SharpSSH">
<HintPath>..\mRemoteV1\References\Tamir.SharpSSH.dll</HintPath>
</Reference>
<Reference Include="VncSharpNG">
<HintPath>..\mRemoteV1\References\VncSharpNG.dll</HintPath>
</Reference>
<Reference Include="WeifenLuo.WinFormsUI.Docking">
<HintPath>..\mRemoteV1\References\WeifenLuo.WinFormsUI.Docking.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Import Include="System" />
<Import Include="System.Collections" />
<Import Include="System.Collections.Generic" />
<Import Include="System.Data" />
<Import Include="System.Diagnostics" />
<Import Include="System.Linq" />
<Import Include="System.Xml.Linq" />
<Import Include="Microsoft.VisualBasic" />
<Import Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
<ItemGroup>
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
<Visible>False</Visible>
</CodeAnalysisDependentAssemblyPaths>
</ItemGroup>
<ItemGroup>
<Compile Include="ExternalToolTest.vb" />
<Compile Include="My Project\AssemblyInfo.vb" />
</ItemGroup>
<ItemGroup>
<Shadow Include="Test References\mRemoteNG.accessor" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\SharedLibraryNG\SharedLibraryNG\SharedLibraryNG.csproj">
<Project>{0F615504-5F30-4CF2-8341-1DE7FEC95A23}</Project>
<Name>SharedLibraryNG</Name>
</ProjectReference>
<ProjectReference Include="..\mRemoteV1\mRemoteV1.vbproj">
<Project>{4934A491-40BC-4E5B-9166-EA1169A220F6}</Project>
<Name>mRemoteV1</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.VisualBasic.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="Trace and Test Impact" id="e062ce86-3357-43c9-b5c3-6b38a0dc3776" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Description>These are test settings for Trace and Test Impact.</Description>
<Execution>
<TestTypeSpecific />
<AgentRule name="Execution Agents">
<DataCollectors>
<DataCollector uri="datacollector://microsoft/SystemInfo/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TestTools.DataCollection.SystemInfo.SystemInfoDataCollector, Microsoft.VisualStudio.TestTools.DataCollection.SystemInfo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="System Information">
</DataCollector>
<DataCollector uri="datacollector://microsoft/HttpProxy/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TraceCollector.HttpProxyCollector, Microsoft.VisualStudio.TraceCollector, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="ASP.NET Client Proxy for IntelliTrace and Test Impact">
</DataCollector>
<DataCollector uri="datacollector://microsoft/TestImpact/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TraceCollector.TestImpactDataCollector, Microsoft.VisualStudio.TraceCollector, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="Test Impact">
</DataCollector>
<DataCollector uri="datacollector://microsoft/TraceDebugger/1.0" assemblyQualifiedName="Microsoft.VisualStudio.TraceCollector.TraceDebuggerDataCollector, Microsoft.VisualStudio.TraceCollector, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" friendlyName="IntelliTrace">
</DataCollector>
</DataCollectors>
</AgentRule>
</Execution>
</TestSettings>

View File

@@ -5,7 +5,19 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "mRemoteV1", "mRemoteV1\mRem
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedLibraryNG", "..\SharedLibraryNG\SharedLibraryNG\SharedLibraryNG.csproj", "{0F615504-5F30-4CF2-8341-1DE7FEC95A23}"
EndProject
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "TestProject", "TestProject\TestProject.vbproj", "{24E0689D-95C0-4AAB-A93F-B8D6B7F0CB97}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{38EB1EFD-C8C8-49A2-BCA7-63F7A02B3153}"
ProjectSection(SolutionItems) = preProject
Local.testsettings = Local.testsettings
mRemoteV1.vsmdi = mRemoteV1.vsmdi
TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
EndProjectSection
EndProject
Global
GlobalSection(TestCaseManagementSettings) = postSolution
CategoryFile = mRemoteV1.vsmdi
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug Portable|Any CPU = Debug Portable|Any CPU
Debug|Any CPU = Debug|Any CPU
@@ -29,6 +41,14 @@ Global
{0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release Portable|Any CPU.Build.0 = Release|Any CPU
{0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F615504-5F30-4CF2-8341-1DE7FEC95A23}.Release|Any CPU.Build.0 = Release|Any CPU
{24E0689D-95C0-4AAB-A93F-B8D6B7F0CB97}.Debug Portable|Any CPU.ActiveCfg = Debug|Any CPU
{24E0689D-95C0-4AAB-A93F-B8D6B7F0CB97}.Debug Portable|Any CPU.Build.0 = Debug|Any CPU
{24E0689D-95C0-4AAB-A93F-B8D6B7F0CB97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{24E0689D-95C0-4AAB-A93F-B8D6B7F0CB97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{24E0689D-95C0-4AAB-A93F-B8D6B7F0CB97}.Release Portable|Any CPU.ActiveCfg = Release|Any CPU
{24E0689D-95C0-4AAB-A93F-B8D6B7F0CB97}.Release Portable|Any CPU.Build.0 = Release|Any CPU
{24E0689D-95C0-4AAB-A93F-B8D6B7F0CB97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{24E0689D-95C0-4AAB-A93F-B8D6B7F0CB97}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

6
mRemoteV1.vsmdi Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
<RunConfiguration id="2a25bb82-f5ff-4a67-b5e9-c6aaa54d1e80" name="Local" storage="local.testsettings" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</TestList>
</TestLists>

View File

@@ -1731,7 +1731,7 @@ Namespace App
Case Protocol.Protocols.ICA
newProtocol = New Protocol.ICA
Case Protocol.Protocols.IntApp
newProtocol = New Protocol.IntApp
newProtocol = New Protocol.IntegratedProgram
If newConnectionInfo.ExtApp = "" Then
Throw New Exception(My.Language.strNoExtAppDefined)
@@ -1908,18 +1908,18 @@ Namespace App
#Region "External Apps"
Public Shared Sub GetExtApps()
Array.Clear(Tools.ExternalAppsTypeConverter.ExternalApps, 0, Tools.ExternalAppsTypeConverter.ExternalApps.Length)
Array.Resize(Tools.ExternalAppsTypeConverter.ExternalApps, ExternalTools.Count + 1)
Array.Clear(Tools.ExternalToolsTypeConverter.ExternalTools, 0, Tools.ExternalToolsTypeConverter.ExternalTools.Length)
Array.Resize(Tools.ExternalToolsTypeConverter.ExternalTools, ExternalTools.Count + 1)
Dim i As Integer = 0
For Each extA As Tools.ExternalTool In ExternalTools
Tools.ExternalAppsTypeConverter.ExternalApps(i) = extA.DisplayName
Tools.ExternalToolsTypeConverter.ExternalTools(i) = extA.DisplayName
i += 1
Next
Tools.ExternalAppsTypeConverter.ExternalApps(i) = ""
Tools.ExternalToolsTypeConverter.ExternalTools(i) = ""
End Sub
Public Shared Function GetExtAppByName(ByVal Name As String) As Tools.ExternalTool

View File

@@ -230,7 +230,7 @@ Namespace Connection
Browsable(True), _
LocalizedDisplayName("strPropertyNameExternalTool"), _
LocalizedDescription("strPropertyDescriptionExternalTool"), _
TypeConverter(GetType(Tools.ExternalAppsTypeConverter))> _
TypeConverter(GetType(Tools.ExternalToolsTypeConverter))> _
Public Property ExtApp() As String
Get
If Me._Inherit.ExtApp And Me._Parent IsNot Nothing Then
@@ -1012,7 +1012,7 @@ Namespace Connection
Browsable(True), _
LocalizedDisplayName("strPropertyNameExternalToolBefore"), _
LocalizedDescription("strPropertyDescriptionExternalToolBefore"), _
TypeConverter(GetType(Tools.ExternalAppsTypeConverter))> _
TypeConverter(GetType(Tools.ExternalToolsTypeConverter))> _
Public Overridable Property PreExtApp() As String
Get
If Me._Inherit.PreExtApp And Me._Parent IsNot Nothing Then
@@ -1039,7 +1039,7 @@ Namespace Connection
Browsable(True), _
LocalizedDisplayName("strPropertyNameExternalToolAfter"), _
LocalizedDescription("strPropertyDescriptionExternalToolAfter"), _
TypeConverter(GetType(Tools.ExternalAppsTypeConverter))> _
TypeConverter(GetType(Tools.ExternalToolsTypeConverter))> _
Public Overridable Property PostExtApp() As String
Get
If Me._Inherit.PostExtApp And Me._Parent IsNot Nothing Then
@@ -1581,7 +1581,7 @@ Namespace Connection
Case Connection.Protocol.Protocols.ICA
Return Connection.Protocol.ICA.Defaults.Port
Case Connection.Protocol.Protocols.IntApp
Return Connection.Protocol.IntApp.Defaults.Port
Return Connection.Protocol.IntegratedProgram.Defaults.Port
End Select
Catch ex As Exception
MessageCollector.AddExceptionMessage(My.Language.strConnectionSetDefaultPortFailed, ex, Messages.MessageClass.ErrorMsg)

View File

@@ -1,186 +0,0 @@
Imports mRemoteNG.App.Native
Imports System.Threading
Imports mRemoteNG.App.Runtime
Imports mRemoteNG.Tools
Namespace Connection
Namespace Protocol
Public Class IntApp
Inherits Connection.Protocol.Base
#Region "Private Properties"
Private IntAppProcessStartInfo As New ProcessStartInfo()
Private Arguments As String
Private ExtApp As Tools.ExternalTool
#End Region
#Region "Public Properties"
Private _IntAppHandle As IntPtr
Public Property IntAppHandle() As IntPtr
Get
Return Me._IntAppHandle
End Get
Set(ByVal value As IntPtr)
Me._IntAppHandle = value
End Set
End Property
Private _IntAppProcess As Process
Public Property IntAppProcess() As Process
Get
Return Me._IntAppProcess
End Get
Set(ByVal value As Process)
Me._IntAppProcess = value
End Set
End Property
Private _IntAppPath As String
Public Property IntAppPath() As String
Get
Return _IntAppPath
End Get
Set(ByVal value As String)
_IntAppPath = value
End Set
End Property
Public ReadOnly Property Focused() As Boolean
Get
If GetForegroundWindow() = IntAppHandle Then
Return True
Else
Return False
End If
End Get
End Property
#End Region
#Region "Private Events & Handlers"
Private Sub ProcessExited(ByVal sender As Object, ByVal e As System.EventArgs)
MyBase.Event_Closed(Me)
End Sub
#End Region
#Region "Public Methods"
Public Sub New()
End Sub
Public Overrides Function SetProps() As Boolean
ExtApp = App.Runtime.GetExtAppByName(InterfaceControl.Info.ExtApp)
If InterfaceControl.Info IsNot Nothing Then
ExtApp.ConnectionInfo = InterfaceControl.Info
End If
_IntAppPath = ExtApp.ParseText(ExtApp.FileName)
Arguments = ExtApp.ParseText(ExtApp.Arguments)
Return MyBase.SetProps()
End Function
Public Overrides Function Connect() As Boolean
Try
If ExtApp.TryIntegrate = False Then
ExtApp.Start(Me.InterfaceControl.Info)
Me.Close()
Return Nothing
End If
IntAppProcessStartInfo.UseShellExecute = True
IntAppProcessStartInfo.FileName = _IntAppPath
IntAppProcessStartInfo.Arguments = Arguments
IntAppProcess = Process.Start(IntAppProcessStartInfo)
IntAppProcess.EnableRaisingEvents = True
IntAppProcess.WaitForInputIdle()
AddHandler IntAppProcess.Exited, AddressOf ProcessExited
Dim TryCount As Integer = 0
Do Until IntAppProcess.MainWindowHandle <> IntPtr.Zero And Me.InterfaceControl.Handle <> IntPtr.Zero And Me.IntAppProcess.MainWindowTitle <> "Default IME"
If TryCount >= My.Settings.MaxPuttyWaitTime * 2 Then
Exit Do
End If
IntAppProcess.Refresh()
Thread.Sleep(500)
TryCount += 1
Loop
IntAppHandle = IntAppProcess.MainWindowHandle
MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, My.Language.strIntAppStuff, True)
MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, String.Format(My.Language.strIntAppHandle, IntAppHandle.ToString), True)
MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, String.Format(My.Language.strIntAppTitle, IntAppProcess.MainWindowTitle), True)
MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, String.Format(My.Language.strIntAppParentHandle, Me.InterfaceControl.Parent.Handle.ToString), True)
SetParent(Me.IntAppHandle, Me.InterfaceControl.Parent.Handle)
SetWindowLong(Me.IntAppHandle, 0, WS_VISIBLE)
ShowWindow(Me.IntAppHandle, SW_SHOWMAXIMIZED)
Resize(Me, New EventArgs)
MyBase.Connect()
Return True
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, My.Language.strIntAppConnectionFailed & vbNewLine & ex.Message)
Return False
End Try
End Function
Public Overrides Sub Focus()
Try
SetForegroundWindow(IntAppHandle)
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, My.Language.strIntAppFocusFailed & vbNewLine & ex.Message, True)
End Try
End Sub
Public Overrides Sub Resize(ByVal sender As Object, ByVal e As EventArgs)
Try
If InterfaceControl.Size = Size.Empty Then Return
MoveWindow(IntAppHandle, -SystemInformation.FrameBorderSize.Width, -(SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height), Me.InterfaceControl.Width + (SystemInformation.FrameBorderSize.Width * 2), Me.InterfaceControl.Height + SystemInformation.CaptionHeight + (SystemInformation.FrameBorderSize.Height * 2), True)
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, My.Language.strIntAppResizeFailed & vbNewLine & ex.Message, True)
End Try
End Sub
Public Overrides Sub Close()
Try
If IntAppProcess.HasExited = False Then
IntAppProcess.Kill()
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, My.Language.strIntAppKillFailed & vbNewLine & ex.Message, True)
End Try
Try
If IntAppProcess.HasExited = False Then
IntAppProcess.Dispose()
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, My.Language.strIntAppDisposeFailed & vbNewLine & ex.Message, True)
End Try
MyBase.Close()
End Sub
#End Region
#Region "Public Shared Methods"
#End Region
#Region "Enums"
Public Enum Defaults
Port = 0
End Enum
#End Region
End Class
End Namespace
End Namespace

View File

@@ -0,0 +1,121 @@
Imports mRemoteNG.App.Native
Imports System.Threading
Imports mRemoteNG.App.Runtime
Imports mRemoteNG.Tools
Namespace Connection
Namespace Protocol
Public Class IntegratedProgram
Inherits Base
#Region "Public Methods"
Public Overrides Function SetProps() As Boolean
If InterfaceControl.Info IsNot Nothing Then
_externalTool = GetExtAppByName(InterfaceControl.Info.ExtApp)
_externalTool.ConnectionInfo = InterfaceControl.Info
End If
Return MyBase.SetProps()
End Function
Public Overrides Function Connect() As Boolean
Try
If _externalTool.TryIntegrate = False Then
_externalTool.Start(InterfaceControl.Info)
Close()
Return Nothing
End If
_process = New Process()
With _process.StartInfo
.UseShellExecute = True
.FileName = _externalTool.FileName
.Arguments = _externalTool.ParseArguments(_externalTool.Arguments)
End With
_process.EnableRaisingEvents = True
AddHandler _process.Exited, AddressOf ProcessExited
_process.Start()
_process.WaitForInputIdle(My.Settings.MaxPuttyWaitTime * 1000)
Dim startTicks As Integer = Environment.TickCount
While _handle.ToInt32 = 0 And Environment.TickCount < startTicks + (My.Settings.MaxPuttyWaitTime * 1000)
_process.Refresh()
If Not _process.MainWindowTitle = "Default IME" Then _handle = _process.MainWindowHandle
If _handle.ToInt32 = 0 Then Thread.Sleep(0)
End While
SetParent(_handle, InterfaceControl.Handle)
MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, My.Language.strIntAppStuff, True)
MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, String.Format(My.Language.strIntAppHandle, _handle.ToString), True)
MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, String.Format(My.Language.strIntAppTitle, _process.MainWindowTitle), True)
MessageCollector.AddMessage(Messages.MessageClass.InformationMsg, String.Format(My.Language.strIntAppParentHandle, InterfaceControl.Parent.Handle.ToString), True)
Resize(Me, New EventArgs)
MyBase.Connect()
Return True
Catch ex As Exception
MessageCollector.AddExceptionMessage(My.Language.strIntAppConnectionFailed, ex)
Return False
End Try
End Function
Public Overrides Sub Focus()
Try
If ConnectionWindow.InTabDrag Then Return
SetForegroundWindow(_handle)
Catch ex As Exception
MessageCollector.AddExceptionMessage(My.Language.strIntAppFocusFailed, ex, , True)
End Try
End Sub
Public Overrides Sub Resize(ByVal sender As Object, ByVal e As EventArgs)
Try
If InterfaceControl.Size = Size.Empty Then Return
MoveWindow(_handle, -SystemInformation.FrameBorderSize.Width, -(SystemInformation.CaptionHeight + SystemInformation.FrameBorderSize.Height), InterfaceControl.Width + (SystemInformation.FrameBorderSize.Width * 2), InterfaceControl.Height + SystemInformation.CaptionHeight + (SystemInformation.FrameBorderSize.Height * 2), True)
Catch ex As Exception
MessageCollector.AddExceptionMessage(My.Language.strIntAppResizeFailed, ex, , True)
End Try
End Sub
Public Overrides Sub Close()
Try
If Not _process.HasExited Then _process.Kill()
Catch ex As Exception
MessageCollector.AddExceptionMessage(My.Language.strIntAppKillFailed, ex, , True)
End Try
Try
If Not _process.HasExited Then _process.Dispose()
Catch ex As Exception
MessageCollector.AddExceptionMessage(My.Language.strIntAppDisposeFailed, ex, , True)
End Try
MyBase.Close()
End Sub
#End Region
#Region "Private Fields"
Private _externalTool As ExternalTool
Private _handle As IntPtr
Private _process As Process
#End Region
#Region "Private Methods"
Private Sub ProcessExited(ByVal sender As Object, ByVal e As EventArgs)
Event_Closed(Me)
End Sub
#End Region
#Region "Enumerations"
Public Enum Defaults
Port = 0
End Enum
#End Region
End Class
End Namespace
End Namespace

View File

@@ -1,113 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>External Applications</title>
<link href="Main.css" rel="stylesheet" type="text/css" />
</head>
<body>
<p>
<span class="heading1">Introduction to External Applications</span></p>
<p>
External applications can help you get things done that can&#39;t be done in
mRemote.<br />
You can for example start a CMD Console or launch your favorite FTP tool from
within mRemote.<br />
This wouldn&#39;t make much sense by itself because you can already launch your
applications by using the Windows Start Menu, Quick Launch or whatever you
prefer to use
to start your apps.</p>
<p>
But there&#39;s more!</p>
<p>
In mRemote you can launch applications and tell them what to do with the use of
arguments (parameters) and variables of the currently selected Connection.<br />
You can for example select your home router&#39;s SSH Connection entry and do a
traceroute (tracert) on that host.</p>
<p>
This is much more comfortable and powerful than opening the console and typing
tracert YourHost.</p>
<p class="heading4">
Notes:</p>
<ul>
<li>Throught this document I will refer to External Applications as Ext. apps or
Ext. app.</li>
<li>Ext. apps are stored in c:\documents and settings\username\local
settings\application data\Felix_Deimel\mRemote\extApps.xml</li>
</ul>
<p>
<span class="heading1">Variables</span></p>
<p>
Variables and arguments can be used to tell the ext. app what to do.<br />
Here&#39;s a list of variables currently supported by mRemote:</p>
<ul>
<li>%Name%</li>
<li>%Hostname%</li>
<li>%Port%</li>
<li>%Username%</li>
<li>%Password%</li>
<li>%Domain%</li>
<li>%Description%</li>
<li>%MacAddress%</li>
<li>%UserField%</li>
</ul>
<p>
The variables always refer to the currently selected Connection.</p>
<p>
<span class="heading1">Example</span></p>
<p>
First of all start the Ext. Apps management interface. To do this click Tools in the main menu and
select External Applications.<br />
You will see a screen like on the following screenshot.</p>
<p>
<img alt="" src="Screenshots/External%20Apps/01.png" /></p>
<p>
The fields below the list are greyed out because you haven&#39;t created a Ext. App
entry yet.<br />
To create one right click the blank area in the list and select Add like in the
screenshot below.</p>
<p>
<img alt="" src="Screenshots/External%20Apps/02.png" /></p>
<p>
This is what you&#39;ll get:</p>
<p>
<img alt="" src="Screenshots/External%20Apps/03.png" /></p>
<p>
So the three fields are now available and need to be filled.<br />
The Display Name is simply the name you will see when you want to launch that
application, so give it a descriptive name.<br />
I named mine Traceroute as I will create a Ext. App launcher that will do a
tracert command in the console.</p>
<p>
<img alt="" src="Screenshots/External%20Apps/04.png" /></p>
<p>
Ok, the next thing we&#39;ll need is a filename. This is the application that we
want to be executed.<br />
I simply type in cmd for a windows cmd console.</p>
<p>
<img alt="" src="Screenshots/External%20Apps/05.png" /></p>
<p>
Now the fun part comes in - the arguments.<br />
The windows cmd has a command line argument that tells the console to launch the
command followed by that argument and stay open.<br />
It&#39;s /K. (There&#39;s also /C, this is useful when you want the console to close
after the command was executed)<br />
In this case I&#39;ll use /K as I want to scan through the result when the command
completes.<br />
After that I just type tracert %HostName%. This tells the console to do a
traceroute on the hostname of the currently selected Connection.</p>
<p>
<img alt="" src="Screenshots/External%20Apps/06.png" /></p>
<p>
Alright! That&#39;s all we&#39;ll need.<br />
Now right click one of you connections, click Tools, External Applications
and select Traceroute.</p>
<p>
<img alt="" src="Screenshots/External%20Apps/07.png" /></p>
<p>
Voil<69>! A console window will popup and execute your tracert command.</p>
<p>
<img alt="" src="Screenshots/External%20Apps/08.png" /></p>
</body>
</html>

View File

@@ -0,0 +1,245 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>External Tools</title>
<link href="Main.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.style1
{
white-space: nowrap;
font-family: 'Courier New', monospace;
height: 25px;
}
</style>
</head>
<body>
<p>
<span class="heading1">Introduction to External Tools</span></p>
<p>
External Tools can help you get things done that can&#39;t be done in
mRemoteNG.<br />
You can for example start a command prompt or launch your favorite FTP tool from
within mRemoteNG.<br />
This wouldn&#39;t make much sense by itself because you can already launch your
applications by using the Windows Start Menu, Quick Launch or whatever you
prefer to use
to start your apps.</p>
<p>
But there&#39;s more!</p>
<p>
In mRemoteNG, you can launch applications and tell them what to do with the use of
arguments (parameters) and variables of the currently selected Connection.
You can, for example, select your home router&#39;s SSH Connection entry and do a
traceroute (tracert) on that host.
This is much quicker and more powerful than opening the console and typing
&quot;tracert yourhost&quot;.</p>
<p>
The external tools configuration is stored in %APPDATA%\mRemoteNG\extApps.xml</p>
<p>
<span class="heading1">Variables</span>
</p>
<p>
Variables and arguments can be used to tell the external tool what to do.</p>
<p>
This is the list of variables supported by mRemoteNG:
</p>
<ul>
<li>%NAME%</li>
<li>%HOSTNAME%</li>
<li>%PORT%</li>
<li>%USERNAME%</li>
<li>%PASSWORD%</li>
<li>%DOMAIN%</li>
<li>%DESCRIPTION%</li>
<li>%MACADDRESS%</li>
<li>%USERFIELD%</li>
</ul>
<p>
Variables always refer to the currently selected connection. Variable names are case-insensitive.
Variables can be used in both the Filename and Arguments fields.</p>
<p>
mRemoteNG will also expand environment variables such as %PATH% and
%USERPROFILE%.
If you need to use an environment variable with the same name as an mRemoteNG
variable, use \% instead of %. The most common use of this is for the USERNAME
environment variable. %USERNAME% will be expanded to the username set in the
currently selected connection. \%USERNAME\% will be expanded to the value set in
the USERNAME environment variable.</p>
<p>If you need to send a variable name to a program without mRemoteNG expanding it,
use ^% instead of %. mRemoteNG will remove the caret (^) and leave the rest
unchanged. For example, ^%USERNAME^% will be sent to the program as %USERNAME%
and will not be expanded.</p>
<p>
<span class="heading1">Special Character Escaping</span>
</p>
<p>
Expanded variables will be escaped using the rules below. There are two levels
of escaping that are done. The first is escaping for standard argument splitting
(C/C++ argv, CommandLineToArgvW, etc). The second is escaping shell
metacharacters for ShellExecute.</p>
<p>
<span class="heading2">Argument splitting escaping:</span></p>
<ul>
<li>Each quotation mark will be escaped by a backslash.</li>
<li>One or more backslashes (\) followed by a quotation mark ("):
<ul>
<li>Each backslash will be escaped by another backslash.</li>
<li>The quotation mark will be escaped by a backslash.</li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If the connection's user field contains
&quot;This&quot; is a \"test\&quot;.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Then %USERFIELD% is replaced with
\&quot;This\&quot; is a \\\&quot;test\\\&quot;.
</ul>
</li>
<li>A variable name followed by a quotation mark (for example, %USERFIELD%&quot;) with
a value ending in one or more backslashes:
<ul>
<li>Each backslash will be escaped by another backslash.</li>
<li>Example:</li>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If the connection's user field contains c:\Example\<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Then "%USERFIELD%" is replaced with "c:\Example\\"
</ul>
</li>
</ul>
<p>
To disable
argument splitting escaping for a variable, precede its name with a minus (-)
sign. For example, %-USERFIELD%.</p>
<p>
<span class="heading2">Shell metacharacter escaping:</span></p>
<ul>
<li>The shell metacharacters are ( ) % ! ^ &quot; &lt; &gt; &amp; |</li>
<li>Each shell metacharacter will be escaped by a caret (^).</li>
</ul>
<p>
To disable both argument splitting and shell metacharacter escaping for a
variable, precede its name with an exclamation point (!). For example,
%!USERFIELD%. This is not recommended and may cause unexpected results.</p>
<p>
Only variables that have been expanded will be escaped. It is up to you to
escape the rest of the arguments.</p>
<p>
<span class="heading1">Variable Examples</span></p>
<table>
<tr><th>Arguments</th><th>User Field</th><th>Result</th></tr>
<tr>
<td class='monospace'>%USERFIELD%</td><td class='monospace'>&quot;Example&quot; Text</td><td class='monospace'>
\^&quot;Example\^&quot; Text</td>
</tr>
<tr>
<td class='monospace'>%-USERFIELD%</td><td class='monospace'>&quot;Example&quot; Text</td><td class='monospace'>
^&quot;Example^&quot; Text</td>
</tr>
<tr>
<td class='monospace'>%!USERFIELD%</td><td class='monospace'>&quot;Example&quot; Text</td><td class='monospace'>
&quot;Example&quot; Text</td>
</tr>
<tr>
<td class='style1'>^%USERFIELD^%</td><td class='style1'>&quot;Example&quot; Text</td>
<td class='style1'>%USERFIELD%</td>
</tr>
<tr>
<td class='monospace'>^^%USERFIELD^^%</td><td class='monospace'>&quot;Example&quot; Text</td><td class='monospace'>
^%USERFIELD^%</td>
</tr>
<tr>
<td class='monospace'>-d &quot;%USERFIELD%&quot;</td><td class='monospace'>c:\Example\</td><td class='monospace'>-d &quot;c:\Example\\&quot;</td>
</tr>
<tr>
<td class='monospace'>-d &quot;%-USERFIELD%&quot;</td><td class='monospace'>c:\Example\</td><td class='monospace'>-d &quot;c:\Example\&quot;</td>
</tr>
<tr>
<td class='monospace'>-d &quot;%USERFIELD%&quot;</td><td class='monospace'>Left
&amp; Right</td><td class='monospace'>-d &quot;Left ^&amp; Right&quot;</td>
</tr>
<tr>
<td class='monospace'>-d &quot;%!USERFIELD%&quot;</td><td class='monospace'>Left
&amp; Right</td><td class='monospace'>-d &quot;Left &amp; Right&quot;</td>
</tr>
<tr>
<td class='monospace'>%WINDIR%</td><td>N/A</td><td class='monospace'>c:\Windows\</td>
</tr>
<tr>
<td class='monospace'>\%WINDIR\%</td><td>N/A</td><td class='monospace'>c:\Windows\</td>
</tr>
<tr>
<td class='monospace'>\^%WINDIR\^%</td><td>N/A</td><td class='monospace'>
\%WINDIR\%</td>
</tr>
<tr>
<td class='monospace'>\\%WINDIR\\%</td><td>N/A</td><td class='monospace'>\\%WINDIR\\%</td>
</tr>
</table>
<p>
<span class="heading1">Example</span></p>
<p>
First of all, start the external tools editor. To do this, click Tools in the main menu and
select External Tools.<br />
You will see a screen like on the following screenshot.</p>
<p>
<img alt="" src="Screenshots/External Tools/01.png" /></p>
<p>
The fields below the list are greyed out because you haven&#39;t created an external tool
entry yet.<br />
To create one, right click the blank area in the list and select Add, as in the
screenshot below.</p>
<p>
<img alt="" src="Screenshots/External Tools/02.png" /></p>
<p>
This is what you&#39;ll get:</p>
<p>
<img alt="" src="Screenshots/External Tools/03.png" /></p>
<p>
So the three fields are now available and need to be filled.<br />
The Display Name is simply the name you will see when you want to launch that
tool, so give it a descriptive name.<br />
I named mine Traceroute as I will create a external tool that will start the
tracert command in the console.</p>
<p>
<img alt="" src="Screenshots/External Tools/04.png" /></p>
<p>
Ok, the next thing we&#39;ll need is a filename. This is the program that we
want to be executed.<br />
I simply type in cmd for a Windows cmd console.</p>
<p>
<img alt="" src="Screenshots/External Tools/05.png" /></p>
<p>
Now the fun part comes in&mdash;the arguments.<br />
The Windows cmd has a command line argument that tells the console to launch the
command followed by that argument and stay open.<br />
It&#39;s /K. (There&#39;s also /C, this is useful when you want the console to close
after the command was executed)<br />
In this case, I&#39;ll use /K as I want to look through the result when the command
completes.<br />
After that, I just type tracert %HostName%. This tells the console to do a
traceroute on the hostname of the currently selected Connection.</p>
<p>
<img alt="" src="Screenshots/External Tools/06.png" /></p>
<p>
Alright! That&#39;s all we&#39;ll need.<br />
Now right click one of you connections, click Tools, External Tools
and select Traceroute.</p>
<p>
<img alt="" src="Screenshots/External Tools/07.png" /></p>
<p>
Voil<69>! A console window will popup and execute your tracert command.</p>
<p>
<img alt="" src="Screenshots/External Tools/08.png" /></p>
</body>
</html>

View File

@@ -30,7 +30,7 @@
<li><a href="SSHFileTransfer.htm">SSH File Transfer</a></li>
<li><a href="QuickConnect.htm">Quick Connect</a></li>
<li><a href="ImportFromAD.htm">Import from Active Directory</a></li>
<li><a href="ExternalApps.htm">External Applications</a></li>
<li><a href="ExternalTools.htm">External Tools</a></li>
<li><a href="PortScan.htm">Port Scan</a></li>
</ul>
<p><a href="QuickReference.htm">Quick Reference</a></p>

View File

@@ -107,6 +107,25 @@ a:hover
/* TABLES */
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid black;
}
th,td {
padding: 5px;
}
th {
background-color: lightgrey;
text-align: left;
}
/* MISC STYLES */
@@ -117,4 +136,13 @@ a:hover
color: #000000;
font-family: 'Courier New' , Monospace;
background-color: #C1C1C1;
}
}
.monospace {
white-space: nowrap;
font-family: 'Courier New', monospace;
}
.nowrap {
white-space: nowrap
}

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -52,17 +52,19 @@ Namespace Tools
Return Regex.Replace(argument, "(\\*)""", "$1$1\""")
End Function
Public Shared Function QuoteArgument(ByVal argument As String, Optional ByVal forceQuotes As Boolean = False) As String
If Not forceQuotes And Not String.IsNullOrEmpty(argument) And Not argument.Contains(" ") Then Return argument
Public Shared Function EscapeBackslashesForTrailingQuote(ByVal argument As String) As String
If String.IsNullOrEmpty(argument) Then Return argument
' Sequence of backslashes followed by the end of the string
' (which will become a double quote):
' double up all the backslashes
If Not String.IsNullOrEmpty(argument) Then
argument = Regex.Replace(argument, "(\\*)$", "$1$1")
End If
Return Regex.Replace(argument, "(\\*)$", "$1$1")
End Function
Return """" & argument & """"
Public Shared Function QuoteArgument(ByVal argument As String, Optional ByVal forceQuotes As Boolean = False) As String
If Not forceQuotes And Not String.IsNullOrEmpty(argument) And Not argument.Contains(" ") Then Return argument
Return """" & EscapeBackslashesForTrailingQuote(argument) & """"
End Function
Public Shared Function EscapeShellMetacharacters(ByVal argument As String) As String

View File

@@ -0,0 +1,297 @@
Imports mRemoteNG.App.Runtime
Imports System.IO
Imports System.ComponentModel
Namespace Tools
Public Class ExternalTool
#Region "Public Properties"
Public Property DisplayName() As String
Public Property FileName() As String
Public Property WaitForExit() As Boolean
Public Property Arguments() As String
Public Property TryIntegrate() As Boolean
Public Property ConnectionInfo() As Connection.Info
Public ReadOnly Property Icon() As Icon
Get
If File.Exists(FileName) Then
Return Misc.GetIconFromFile(FileName)
Else
Return Nothing
End If
End Get
End Property
Public ReadOnly Property Image() As Image
Get
If Icon IsNot Nothing Then
Return Icon.ToBitmap
Else
Return Nothing
End If
End Get
End Property
#End Region
#Region "Constructors"
Public Sub New(Optional ByVal displayName As String = "", Optional ByVal fileName As String = "", Optional ByVal arguments As String = "")
Me.DisplayName = displayName
Me.FileName = fileName
Me.Arguments = arguments
End Sub
#End Region
#Region "Public Methods"
' Start external app
Public Sub Start(Optional ByVal startConnectionInfo As Connection.Info = Nothing)
Try
If String.IsNullOrEmpty(_FileName) Then Throw New InvalidOperationException("FileName cannot be blank.")
If TryIntegrate Then
StartIntegrated(startConnectionInfo)
Return
End If
ConnectionInfo = startConnectionInfo
Dim process As New Process()
With process.StartInfo
.UseShellExecute = True
.FileName = FileName
.Arguments = ParseArguments(Arguments)
End With
process.Start()
If WaitForExit Then process.WaitForExit()
Catch ex As Exception
MessageCollector.AddExceptionMessage("ExternalApp.Start() failed.", ex)
End Try
End Sub
' Start external app integrated
Public Sub StartIntegrated(Optional ByVal startConnectionInfo As Connection.Info = Nothing)
Try
ConnectionInfo = startConnectionInfo
Dim newConnectionInfo As New Connection.Info
newConnectionInfo.Protocol = Connection.Protocol.Protocols.IntApp
newConnectionInfo.ExtApp = DisplayName
newConnectionInfo.Name = DisplayName
newConnectionInfo.Panel = "Int. Apps"
newConnectionInfo.Hostname = ConnectionInfo.Hostname
newConnectionInfo.Port = ConnectionInfo.Port
newConnectionInfo.Username = ConnectionInfo.Username
newConnectionInfo.Password = ConnectionInfo.Password
newConnectionInfo.Domain = ConnectionInfo.Domain
newConnectionInfo.Description = ConnectionInfo.Description
newConnectionInfo.MacAddress = ConnectionInfo.MacAddress
newConnectionInfo.UserField = ConnectionInfo.UserField
newConnectionInfo.Description = ConnectionInfo.Description
newConnectionInfo.PreExtApp = ConnectionInfo.PreExtApp
newConnectionInfo.PostExtApp = ConnectionInfo.PostExtApp
OpenConnection(newConnectionInfo)
Catch ex As Exception
MessageCollector.AddExceptionMessage("ExternalApp.StartIntegrated() failed.", ex, , True)
End Try
End Sub
Private Enum EscapeType
All
ShellMetacharacters
None
End Enum
Private Structure Replacement
Public Sub New(ByVal start As Integer, ByVal length As Integer, ByVal value As String)
Me.Start = start
Me.Length = length
Me.Value = value
End Sub
Public Property Start As Integer
Public Property Length As Integer
Public Property Value As String
End Structure
Public Function ParseArguments(ByVal input As String) As String
Dim index As Integer = 0
Dim replacements As New List(Of Replacement)
Do
Dim tokenStart As Integer = input.IndexOf("%", index, StringComparison.InvariantCulture)
If tokenStart = -1 Then Exit Do
Dim tokenEnd As Integer = input.IndexOf("%", tokenStart + 1, StringComparison.InvariantCulture)
If tokenEnd = -1 Then Exit Do
Dim tokenLength As Integer = tokenEnd - tokenStart + 1
Dim variableNameStart As Integer = tokenStart + 1
Dim variableNameLength As Integer = tokenLength - 2
Dim isEnvironmentVariable As Boolean = False
Dim variableName As String
If tokenStart > 0 Then
Dim tokenStartPrefix As Char = input.Substring(tokenStart - 1, 1)
Dim tokenEndPrefix As Char = input.Substring(tokenEnd - 1, 1)
If tokenStartPrefix = "\" And tokenEndPrefix = "\" Then
isEnvironmentVariable = True
' Add the first backslash to the token
tokenStart = tokenStart - 1
tokenLength = tokenLength + 1
' Remove the last backslash from the name
variableNameLength = variableNameLength - 1
ElseIf tokenStartPrefix = "^" And tokenEndPrefix = "^" Then
' Add the first caret to the token
tokenStart = tokenStart - 1
tokenLength = tokenLength + 1
' Remove the last caret from the name
variableNameLength = variableNameLength - 1
variableName = input.Substring(variableNameStart, variableNameLength)
replacements.Add(New Replacement(tokenStart, tokenLength, String.Format("%{0}%", variableName)))
index = tokenEnd
Continue Do
End If
End If
Dim token As String = input.Substring(tokenStart, tokenLength)
Dim escape As EscapeType = EscapeType.All
Dim prefix As String = input.Substring(variableNameStart, 1)
Select Case prefix
Case "-"
escape = EscapeType.ShellMetacharacters
Case "!"
escape = EscapeType.None
End Select
If Not escape = EscapeType.All Then
' Remove the escape character from the name
variableNameStart = variableNameStart + 1
variableNameLength = variableNameLength - 1
End If
If variableNameLength = 0 Then
index = tokenEnd
Continue Do
End If
variableName = input.Substring(variableNameStart, variableNameLength)
Dim replacementValue As String = token
If Not isEnvironmentVariable Then
replacementValue = GetVariableReplacement(variableName, token)
End If
Dim haveReplacement As Boolean = False
If Not replacementValue = token Then
haveReplacement = True
Else
replacementValue = Environment.GetEnvironmentVariable(variableName)
If replacementValue IsNot Nothing Then haveReplacement = True
End If
If haveReplacement Then
Dim trailing As Char
If tokenEnd + 2 <= input.Length Then
trailing = input.Substring(tokenEnd + 1, 1)
Else
trailing = String.Empty
End If
If escape = EscapeType.All Then
replacementValue = CommandLineArguments.EscapeBackslashes(replacementValue)
If trailing = """" Then
replacementValue = CommandLineArguments.EscapeBackslashesForTrailingQuote(replacementValue)
End If
End If
If escape = EscapeType.All Or escape = EscapeType.ShellMetacharacters Then
replacementValue = CommandLineArguments.EscapeShellMetacharacters(replacementValue)
End If
replacements.Add(New Replacement(tokenStart, tokenLength, replacementValue))
index = tokenEnd + 1
Else
index = tokenEnd
End If
Loop
Dim result As String = input
For index = result.Length To 0 Step -1
For Each replacement As Replacement In replacements
If Not replacement.Start = index Then Continue For
Dim before As String = result.Substring(0, replacement.Start)
Dim after As String = result.Substring(replacement.Start + replacement.Length)
result = before & replacement.Value & after
Next
Next
Return result
End Function
#End Region
#Region "Private Methods"
Private Function GetVariableReplacement(ByVal variable As String, ByVal original As String) As String
Dim replacement As String
Select Case variable.ToLowerInvariant()
Case "name"
If ConnectionInfo Is Nothing Then replacement = "" Else replacement = ConnectionInfo.Name
Case "hostname"
If ConnectionInfo Is Nothing Then replacement = "" Else replacement = ConnectionInfo.Hostname
Case "port"
If ConnectionInfo Is Nothing Then replacement = "" Else replacement = ConnectionInfo.Port
Case "username"
If ConnectionInfo Is Nothing Then replacement = "" Else replacement = ConnectionInfo.Username
Case "password"
If ConnectionInfo Is Nothing Then replacement = "" Else replacement = ConnectionInfo.Password
Case "domain"
If ConnectionInfo Is Nothing Then replacement = "" Else replacement = ConnectionInfo.Domain
Case "description"
If ConnectionInfo Is Nothing Then replacement = "" Else replacement = ConnectionInfo.Description
' ReSharper disable once StringLiteralTypo
Case "macaddress"
If ConnectionInfo Is Nothing Then replacement = "" Else replacement = ConnectionInfo.MacAddress
' ReSharper disable once StringLiteralTypo
Case "userfield"
If ConnectionInfo Is Nothing Then replacement = "" Else replacement = ConnectionInfo.UserField
Case Else
Return original
End Select
Return replacement
End Function
#End Region
End Class
Public Class ExternalToolsTypeConverter
Inherits StringConverter
Public Shared ExternalTools As String() = New String() {}
Public Overloads Overrides Function GetStandardValues(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValuesCollection
Return New StandardValuesCollection(ExternalTools)
End Function
Public Overloads Overrides Function GetStandardValuesExclusive(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
Return True
End Function
Public Overloads Overrides Function GetStandardValuesSupported(ByVal context As ITypeDescriptorContext) As Boolean
Return True
End Function
End Class
End Namespace

View File

@@ -1,220 +0,0 @@
Imports mRemoteNG.App.Runtime
Imports System.IO
Imports System.ComponentModel
Namespace Tools
Public Class ExternalTool
#Region "Properties"
Private _DisplayName As String
Public Property DisplayName() As String
Get
Return _DisplayName
End Get
Set(ByVal value As String)
_DisplayName = value
End Set
End Property
Private _FileName As String
Public Property FileName() As String
Get
Return _FileName
End Get
Set(ByVal value As String)
_FileName = value
End Set
End Property
Private _WaitForExit As Boolean
Public Property WaitForExit() As Boolean
Get
Return _WaitForExit
End Get
Set(ByVal value As Boolean)
_WaitForExit = value
End Set
End Property
Private _Arguments As String
Public Property Arguments() As String
Get
Return _Arguments
End Get
Set(ByVal value As String)
_Arguments = value
End Set
End Property
Private _TryIntegrate As Boolean
Public Property TryIntegrate() As Boolean
Get
Return _TryIntegrate
End Get
Set(ByVal value As Boolean)
_TryIntegrate = value
End Set
End Property
Private _ConnectionInfo As Connection.Info
Public Property ConnectionInfo() As Connection.Info
Get
Return _ConnectionInfo
End Get
Set(ByVal value As Connection.Info)
_ConnectionInfo = value
End Set
End Property
Public ReadOnly Property Icon() As Icon
Get
If File.Exists(Me._FileName) Then
Return Tools.Misc.GetIconFromFile(Me._FileName)
Else
Return Nothing
End If
End Get
End Property
Public ReadOnly Property Image() As Image
Get
Dim iC As Icon = Me.Icon
If iC IsNot Nothing Then
Return iC.ToBitmap
Else
Return Nothing
End If
End Get
End Property
#End Region
Public Sub New()
Me.New("")
End Sub
Public Sub New(ByVal DisplayName As String)
Me.New(DisplayName, "", "")
End Sub
Public Sub New(ByVal DisplayName As String, ByVal Filename As String, ByVal Arguments As String)
_DisplayName = DisplayName
_FileName = Filename
_Arguments = Arguments
End Sub
' Start external app
Public Function Start(Optional ByVal ConnectionInfo As Connection.Info = Nothing) As Process
Try
If _FileName = "" Then
Throw New Exception("No Filename specified!")
End If
If _TryIntegrate = True Then
StartIntApp(ConnectionInfo)
Return Nothing
End If
_ConnectionInfo = ConnectionInfo
Dim process As New Process()
With process.StartInfo
.UseShellExecute = True
.FileName = ParseText(_FileName)
.Arguments = ParseText(_Arguments)
End With
process.Start()
If _WaitForExit Then
process.WaitForExit()
End If
Return process
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, "Couldn't start external application." & vbNewLine & ex.Message)
Return Nothing
End Try
End Function
' Start external app integrated
Public Sub StartIntApp(Optional ByVal ConnectionInfo As Connection.Info = Nothing)
Try
_ConnectionInfo = ConnectionInfo
Dim nCI As New Connection.Info
nCI.Protocol = Connection.Protocol.Protocols.IntApp
nCI.ExtApp = Me.DisplayName
nCI.Name = Me.DisplayName
nCI.Panel = "Int. Apps"
nCI.Hostname = _ConnectionInfo.Hostname
nCI.Port = _ConnectionInfo.Port
nCI.Username = _ConnectionInfo.Username
nCI.Password = _ConnectionInfo.Password
nCI.Domain = _ConnectionInfo.Domain
nCI.Description = _ConnectionInfo.Description
nCI.MacAddress = _ConnectionInfo.MacAddress
nCI.UserField = _ConnectionInfo.UserField
nCI.Description = _ConnectionInfo.Description
nCI.PreExtApp = _ConnectionInfo.PreExtApp
nCI.PostExtApp = _ConnectionInfo.PostExtApp
OpenConnection(nCI)
Catch ex As Exception
End Try
End Sub
Public Function ParseText(ByVal Text As String) As String
Dim pText As String = Text
Try
If _ConnectionInfo IsNot Nothing Then
pText = Replace(pText, "%Name%", _ConnectionInfo.Name, , , CompareMethod.Text)
pText = Replace(pText, "%HostName%", _ConnectionInfo.Hostname, , , CompareMethod.Text)
pText = Replace(pText, "%Port%", _ConnectionInfo.Port, , , CompareMethod.Text)
pText = Replace(pText, "%UserName%", _ConnectionInfo.Username, , , CompareMethod.Text)
pText = Replace(pText, "%Password%", _ConnectionInfo.Password, , , CompareMethod.Text)
pText = Replace(pText, "%Domain%", _ConnectionInfo.Domain, , , CompareMethod.Text)
pText = Replace(pText, "%Description%", _ConnectionInfo.Description, , , CompareMethod.Text)
pText = Replace(pText, "%MacAddress%", _ConnectionInfo.MacAddress, , , CompareMethod.Text)
pText = Replace(pText, "%UserField%", _ConnectionInfo.UserField, , , CompareMethod.Text)
Else
pText = Replace(pText, "%Name%", "", , , CompareMethod.Text)
pText = Replace(pText, "%HostName%", "", , , CompareMethod.Text)
pText = Replace(pText, "%Port%", "", , , CompareMethod.Text)
pText = Replace(pText, "%UserName%", "", , , CompareMethod.Text)
pText = Replace(pText, "%Password%", "", , , CompareMethod.Text)
pText = Replace(pText, "%Domain%", "", , , CompareMethod.Text)
pText = Replace(pText, "%Description%", "", , , CompareMethod.Text)
pText = Replace(pText, "%MacAddress%", "", , , CompareMethod.Text)
pText = Replace(pText, "%UserField%", "", , , CompareMethod.Text)
End If
Catch ex As Exception
MessageCollector.AddMessage(Messages.MessageClass.WarningMsg, "ParseText failed (Tools.ExternalApp)" & vbNewLine & ex.Message, True)
End Try
Return pText
End Function
End Class
Public Class ExternalAppsTypeConverter
Inherits StringConverter
Public Shared ExternalApps As String() = New String() {}
Public Overloads Overrides Function GetStandardValues(ByVal context As System.ComponentModel.ITypeDescriptorContext) As System.ComponentModel.TypeConverter.StandardValuesCollection
Return New StandardValuesCollection(ExternalApps)
End Function
Public Overloads Overrides Function GetStandardValuesExclusive(ByVal context As System.ComponentModel.ITypeDescriptorContext) As Boolean
Return True
End Function
Public Overloads Overrides Function GetStandardValuesSupported(ByVal context As ITypeDescriptorContext) As Boolean
Return True
End Function
End Class
End Namespace

View File

@@ -368,15 +368,16 @@ Namespace Tree
SetNodeImageIndex(treeNode, Img)
End Sub
Private Delegate Sub SetNodeImageIndexCB(ByVal tNode As TreeNode, ByVal ImgIndex As Integer)
Private Shared Sub SetNodeImageIndex(ByVal tNode As TreeNode, ByVal ImgIndex As Integer)
If _TreeView.InvokeRequired Then
Dim s As New SetNodeImageIndexCB(AddressOf SetNodeImageIndex)
_TreeView.Invoke(s, New Object() {tNode, ImgIndex})
Else
tNode.ImageIndex = ImgIndex
tNode.SelectedImageIndex = ImgIndex
Private Delegate Sub SetNodeImageIndexDelegate(ByVal treeNode As TreeNode, ByVal imageIndex As Integer)
Private Shared Sub SetNodeImageIndex(ByVal treeNode As TreeNode, ByVal imageIndex As Integer)
If treeNode Is Nothing OrElse treeNode.TreeView Is Nothing Then Return
If treeNode.TreeView.InvokeRequired Then
treeNode.TreeView.Invoke(New SetNodeImageIndexDelegate(AddressOf SetNodeImageIndex), New Object() {treeNode, imageIndex})
Return
End If
treeNode.ImageIndex = imageIndex
treeNode.SelectedImageIndex = imageIndex
End Sub
Public Shared Sub SetNodeToolTip(ByVal e As MouseEventArgs, ByVal tTip As ToolTip)

View File

@@ -131,8 +131,8 @@ Namespace UI
TreeNode20.Tag = "ImportFromAD"
TreeNode20.Text = "Import From Active Directory"
TreeNode21.Name = "Node1"
TreeNode21.Tag = "ExternalApps"
TreeNode21.Text = "External Applications"
TreeNode21.Tag = "ExternalTools"
TreeNode21.Text = "External Tools"
TreeNode22.Name = "Node0"
TreeNode22.Tag = "PortScan"
TreeNode22.Text = "Port Scan"
@@ -218,9 +218,9 @@ Namespace UI
#End Region
#Region "Private Methods"
Private Sub Help_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.tvIndex.Nodes(0).Expand()
Me.tvIndex.SelectedNode = Me.tvIndex.Nodes(0).Nodes(0)
Private Sub Help_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
tvIndex.Nodes(0).ExpandAll()
tvIndex.SelectedNode = tvIndex.Nodes(0).Nodes(0)
End Sub
Private Sub Help_Shown(sender As Object, e As EventArgs) Handles Me.Shown

View File

@@ -286,7 +286,7 @@
<Compile Include="Connection\Connection.Protocol.HTTPBase.vb" />
<Compile Include="Connection\Connection.Protocol.HTTPS.vb" />
<Compile Include="Connection\Connection.Protocol.ICA.vb" />
<Compile Include="Connection\Connection.Protocol.IntApp.vb" />
<Compile Include="Connection\Connection.Protocol.IntegratedProgram.vb" />
<Compile Include="Connection\Connection.Protocol.List.vb" />
<Compile Include="Connection\Connection.Protocol.Protocols.vb" />
<Compile Include="Connection\Connection.Protocol.PuttyBase.vb" />
@@ -361,7 +361,7 @@
</Compile>
<Compile Include="Tools\Tools.Controls.vb">
</Compile>
<Compile Include="Tools\Tools.ExternalApp.vb" />
<Compile Include="Tools\ExternalTool.vb" />
<Compile Include="Tools\Tools.LocalizedAttributes.vb" />
<Compile Include="Tools\Tools.Misc.vb" />
<Compile Include="Tools\Tools.PortScan.vb" />
@@ -636,7 +636,7 @@
<Content Include="Help\PortScan.htm">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\ExternalApps.htm">
<Content Include="Help\ExternalTools.htm">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\ErrorsAndInfos.htm">
@@ -723,28 +723,28 @@
<Content Include="Help\Screenshots\Configuration\17.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\Screenshots\External Apps\01.png">
<Content Include="Help\Screenshots\External Tools\01.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\Screenshots\External Apps\02.png">
<Content Include="Help\Screenshots\External Tools\02.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\Screenshots\External Apps\03.png">
<Content Include="Help\Screenshots\External Tools\03.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\Screenshots\External Apps\04.png">
<Content Include="Help\Screenshots\External Tools\04.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\Screenshots\External Apps\05.png">
<Content Include="Help\Screenshots\External Tools\05.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\Screenshots\External Apps\06.png">
<Content Include="Help\Screenshots\External Tools\06.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\Screenshots\External Apps\07.png">
<Content Include="Help\Screenshots\External Tools\07.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\Screenshots\External Apps\08.png">
<Content Include="Help\Screenshots\External Tools\08.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Help\Screenshots\Main Menu\File.png">