IronRDP/ffi/dotnet/Devolutions.IronRdp.ConnectExample/Program.cs
irvingouj@Devolutions d3e0cb17e1
Some checks failed
CI / Check formatting (push) Has been cancelled
CI / Check typos (push) Has been cancelled
Coverage / Coverage Report (push) Has been cancelled
Release crates / Open release PR (push) Has been cancelled
Release crates / Release crates (push) Has been cancelled
CI / Checks [linux] (push) Has been cancelled
CI / Checks [macos] (push) Has been cancelled
CI / Checks [windows] (push) Has been cancelled
CI / Fuzzing (push) Has been cancelled
CI / Web Client (push) Has been cancelled
CI / FFI (push) Has been cancelled
CI / Success (push) Has been cancelled
feat(ffi): expose RDCleanPath (#1014)
Add RDCleanPath support for Devolutions.IronRDP .NET package
2025-10-30 16:38:41 +00:00

193 lines
7 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
namespace Devolutions.IronRdp.ConnectExample
{
class Program
{
static async Task Main(string[] args)
{
Log.InitWithEnv();
var arguments = ParseArguments(args);
if (arguments == null)
{
return;
}
var serverName = arguments["--serverName"];
var username = arguments["--username"];
var password = arguments["--password"];
var domain = arguments["--domain"];
try
{
var (res, framed) = await Connection.Connect(buildConfig(username, password, domain, 1980, 1080), serverName, null);
var decodedImage = DecodedImage.New(PixelFormat.RgbA32, res.GetDesktopSize().GetWidth(), res.GetDesktopSize().GetHeight());
var activeState = ActiveStage.New(res);
var keepLooping = true;
while (keepLooping)
{
var readPduTask = framed.ReadPdu();
Action? action = null;
byte[]? payload = null;
if (readPduTask == await Task.WhenAny(readPduTask, Task.Delay(2000)))
{
var pduReadTask = await readPduTask;
action = pduReadTask.Item1;
payload = pduReadTask.Item2;
Console.WriteLine($"Action: {action}");
}
else
{
Console.WriteLine("Timeout");
break;
}
var outputIterator = activeState.Process(decodedImage, action, payload);
while (!outputIterator.IsEmpty())
{
var output = outputIterator.Next()!; // outputIterator.Next() is not null since outputIterator.IsEmpty() is false
Console.WriteLine($"Output type: {output.GetType()}");
if (output.GetEnumType() == ActiveStageOutputType.Terminate)
{
Console.WriteLine("Connection terminated.");
keepLooping = false;
}
if (output.GetEnumType() == ActiveStageOutputType.ResponseFrame)
{
var responseFrame = output.GetResponseFrame()!;
byte[] responseFrameBytes = new byte[responseFrame.GetSize()];
responseFrame.Fill(responseFrameBytes);
await framed.Write(responseFrameBytes);
}
}
}
saveImage(decodedImage, "output.png");
}
catch (Exception e)
{
Console.WriteLine($"An error occurred: {e.Message}\n\nStackTrace:\n{e.StackTrace}");
}
}
private static void saveImage(DecodedImage decodedImage, string v)
{
int width = decodedImage.GetWidth();
int height = decodedImage.GetHeight();
var data = decodedImage.GetData();
var bytes = new byte[data.GetSize()];
data.Fill(bytes);
using Image<Rgba32> image = new Image<Rgba32>(width, height);
// Well mutate this struct instead of creating a new one for performance reasons.
Rgba32 color = new Rgba32(0, 0, 0);
for (int col = 0; col < width; ++col)
{
for (int row = 0; row < height; ++row)
{
var idx = (row * width + col) * 4;
color.R = bytes[idx];
color.G = bytes[idx + 1];
color.B = bytes[idx + 2];
image[col, row] = color;
}
}
// Save the image as bitmap.
image.Save("./output.bmp");
}
static Dictionary<string, string>? ParseArguments(string[] args)
{
if (args.Length == 0 || Array.Exists(args, arg => arg == "--help"))
{
PrintHelp();
return null;
}
var arguments = new Dictionary<string, string>();
string? lastKey = null;
foreach (var arg in args)
{
if (arg.StartsWith("--"))
{
if (lastKey != null)
{
Console.WriteLine($"Error: Missing value for {lastKey}.");
PrintHelp();
return null;
}
if (!IsValidArgument(arg))
{
Console.WriteLine($"Error: Unknown argument {arg}.");
PrintHelp();
return null;
}
lastKey = arg;
}
else
{
if (lastKey == null)
{
Console.WriteLine("Error: Value without a preceding flag.");
PrintHelp();
return null;
}
arguments[lastKey] = arg;
lastKey = null;
}
}
if (lastKey != null)
{
Console.WriteLine($"Error: Missing value for {lastKey}.");
PrintHelp();
return null;
}
return arguments;
}
static bool IsValidArgument(string argument)
{
var validArguments = new List<string> { "--serverName", "--username", "--password", "--domain" };
return validArguments.Contains(argument);
}
static void PrintHelp()
{
Console.WriteLine("Usage: dotnet run -- [OPTIONS]");
Console.WriteLine("Options:");
Console.WriteLine(" --serverName <serverName> The name of the server to connect to.");
Console.WriteLine(" --username <username> The username for connection.");
Console.WriteLine(" --password <password> The password for connection.");
Console.WriteLine(" --domain <domain> The domain of the server.");
Console.WriteLine(" --help Show this message and exit.");
}
private static Config buildConfig(string username, string password, string domain, int width, int height)
{
ConfigBuilder configBuilder = ConfigBuilder.New();
configBuilder.WithUsernameAndPassword(username, password);
configBuilder.SetDomain(domain);
configBuilder.SetDesktopSize((ushort)height, (ushort)width);
configBuilder.SetClientName("IronRdp");
configBuilder.SetClientDir("C:\\");
configBuilder.SetPerformanceFlags(PerformanceFlags.NewDefault());
return configBuilder.Build();
}
}
}