Files
mRemoteNG/mRemoteV1/Tools/ExternalTool.cs
David Sparer 99ffe9eac2 made ExternalTool implement INotifyPropertyChanged
Also codified the rule that "WaitForExit" cannot be set at the same time as "TryIntegrate". TryIntegrate will always be settable, but WaitForExit will have to defer its state.
2017-11-11 18:20:36 -06:00

206 lines
6.0 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Messages;
// ReSharper disable ArrangeAccessorOwnerBody
namespace mRemoteNG.Tools
{
public class ExternalTool : INotifyPropertyChanged
{
private readonly IConnectionInitiator _connectionInitiator = new ConnectionInitiator();
private string _displayName;
private string _fileName;
private bool _waitForExit;
private string _arguments;
private string _workingDir;
private bool _tryIntegrate;
private bool _showOnToolbar = true;
private bool _runElevated;
#region Public Properties
public string DisplayName
{
get { return _displayName; }
set { SetField(ref _displayName, value, nameof(DisplayName)); }
}
public string FileName
{
get { return _fileName; }
set { SetField(ref _fileName, value, nameof(FileName)); }
}
public bool WaitForExit
{
get { return _waitForExit; }
set
{
// WaitForExit cannot be turned on when TryIntegrate is true
if (TryIntegrate)
return;
SetField(ref _waitForExit, value, nameof(WaitForExit));
}
}
public string Arguments
{
get { return _arguments; }
set { SetField(ref _arguments, value, nameof(Arguments)); }
}
public string WorkingDir
{
get { return _workingDir; }
set { SetField(ref _workingDir, value, nameof(WorkingDir)); }
}
public bool TryIntegrate
{
get { return _tryIntegrate; }
set
{
// WaitForExit cannot be turned on when TryIntegrate is true
if (value)
WaitForExit = false;
SetField(ref _tryIntegrate, value, nameof(TryIntegrate));
}
}
public bool ShowOnToolbar
{
get { return _showOnToolbar; }
set { SetField(ref _showOnToolbar, value, nameof(ShowOnToolbar)); }
}
public bool RunElevated
{
get { return _runElevated; }
set { SetField(ref _runElevated, value, nameof(RunElevated)); }
}
public ConnectionInfo ConnectionInfo { get; set; }
public Icon Icon
{
get { return File.Exists(FileName) ? MiscTools.GetIconFromFile(FileName) : Resources.mRemote_Icon; }
}
public Image Image
{
get { return Icon?.ToBitmap() ?? Resources.mRemote_Icon.ToBitmap(); }
}
#endregion
public ExternalTool(string displayName = "", string fileName = "", string arguments = "", string workingDir = "", bool runElevated = false)
{
DisplayName = displayName;
FileName = fileName;
Arguments = arguments;
WorkingDir = workingDir;
RunElevated = runElevated;
}
public void Start(ConnectionInfo startConnectionInfo = null)
{
try
{
if (string.IsNullOrEmpty(FileName))
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, "ExternalApp.Start() failed: FileName cannot be blank.");
return;
}
ConnectionInfo = startConnectionInfo;
if (TryIntegrate)
StartIntegrated();
else
StartExternalProcess();
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("ExternalApp.Start() failed.", ex);
}
}
private void StartExternalProcess()
{
var process = new Process();
SetProcessProperties(process, ConnectionInfo);
process.Start();
if (WaitForExit)
{
process.WaitForExit();
}
}
private void SetProcessProperties(Process process, ConnectionInfo startConnectionInfo)
{
var argParser = new ExternalToolArgumentParser(startConnectionInfo);
process.StartInfo.UseShellExecute = true;
process.StartInfo.FileName = argParser.ParseArguments(FileName);
process.StartInfo.Arguments = argParser.ParseArguments(Arguments);
if (WorkingDir != "") process.StartInfo.WorkingDirectory = argParser.ParseArguments(WorkingDir);
if (RunElevated) process.StartInfo.Verb = "runas";
}
private void StartIntegrated()
{
try
{
var newConnectionInfo = BuildConnectionInfoForIntegratedApp();
_connectionInitiator.OpenConnection(newConnectionInfo);
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("ExternalApp.StartIntegrated() failed.", ex);
}
}
private ConnectionInfo BuildConnectionInfoForIntegratedApp()
{
var newConnectionInfo = GetAppropriateInstanceOfConnectionInfo();
SetConnectionInfoFields(newConnectionInfo);
return newConnectionInfo;
}
private ConnectionInfo GetAppropriateInstanceOfConnectionInfo()
{
var newConnectionInfo = ConnectionInfo == null ? new ConnectionInfo() : ConnectionInfo.Clone();
return newConnectionInfo;
}
private void SetConnectionInfoFields(ConnectionInfo newConnectionInfo)
{
newConnectionInfo.Protocol = ProtocolType.IntApp;
newConnectionInfo.ExtApp = DisplayName;
newConnectionInfo.Name = DisplayName;
newConnectionInfo.Panel = Language.strMenuExternalTools;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChangedEvent(object sender, string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, string propertyName)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
RaisePropertyChangedEvent(this, propertyName);
return true;
}
}
}