mirror of
https://github.com/Stone-Red-Code/RemoteExec.git
synced 2026-09-04 09:06:20 +02:00
Initial commit
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CuteUtils" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RemoteExec.Shared\RemoteExec.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
[Serializable]
|
||||
internal class RemoteExecutionException(string message) : Exception(message)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using Microsoft.AspNetCore.SignalR.Client;
|
||||
|
||||
using RemoteExec.Shared;
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace RemoteExec.Client;
|
||||
|
||||
public class RemoteExecutor(string url)
|
||||
{
|
||||
private readonly HubConnection _connection =
|
||||
new HubConnectionBuilder()
|
||||
.WithUrl(url)
|
||||
.WithAutomaticReconnect()
|
||||
.Build();
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _connection.StartAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public bool TryExecute<TDelegate, TResult>(TDelegate del, out TResult? result, params object[] args) where TDelegate : Delegate
|
||||
{
|
||||
try
|
||||
{
|
||||
result = Execute<TDelegate, TResult>(del, args);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryExecute<TDelegate, TResult>(TDelegate del, out TResult? result, [NotNullWhen(false)] out Exception? exception, params object[] args) where TDelegate : Delegate
|
||||
{
|
||||
try
|
||||
{
|
||||
result = Execute<TDelegate, TResult>(del, args);
|
||||
exception = null;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result = default;
|
||||
exception = ex;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public TResult Execute<TDelegate, TResult>(TDelegate del, params object[] args) where TDelegate : Delegate
|
||||
{
|
||||
object? execResult = Execute(del, args);
|
||||
|
||||
if (execResult is TResult typedResult)
|
||||
{
|
||||
return typedResult;
|
||||
}
|
||||
else if (execResult is JsonElement jsonElement)
|
||||
{
|
||||
return jsonElement.Deserialize<TResult>()!;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidCastException("The result cannot be cast to the specified type.");
|
||||
}
|
||||
}
|
||||
|
||||
public object? Execute<T>(T del, params object[] args) where T : Delegate
|
||||
{
|
||||
MethodInfo method = del.Method;
|
||||
Type declaringType = method.DeclaringType!;
|
||||
Assembly asm = declaringType.Assembly;
|
||||
|
||||
if (!method.IsStatic)
|
||||
{
|
||||
throw new InvalidOperationException("Only static methods supported");
|
||||
}
|
||||
|
||||
if (asm.IsDynamic)
|
||||
{
|
||||
throw new InvalidOperationException("Dynamic assemblies are not supported");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(asm.Location))
|
||||
{
|
||||
throw new InvalidOperationException("Assembly location is not available");
|
||||
}
|
||||
|
||||
byte[] dllBytes = File.ReadAllBytes(asm.Location);
|
||||
|
||||
RemoteExecutionRequest request = new RemoteExecutionRequest
|
||||
{
|
||||
AssemblyBytes = dllBytes,
|
||||
TypeName = declaringType.FullName!,
|
||||
MethodName = method.Name,
|
||||
ArgumentTypes = [.. method.GetParameters().Select(p => p.ParameterType.AssemblyQualifiedName!)],
|
||||
Arguments = args
|
||||
};
|
||||
|
||||
RemoteExecutionResult result = _connection
|
||||
.InvokeAsync<RemoteExecutionResult>("Execute", request)
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
|
||||
if (result.Exception != null)
|
||||
{
|
||||
throw new RemoteExecutionException(result.Exception);
|
||||
}
|
||||
|
||||
return result.Result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user