В Windows/C# Как открыть трубку и получить от них йоханал?C#

Место общения программистов C#
Ответить
Anonymous
 В Windows/C# Как открыть трубку и получить от них йоханал?

Сообщение Anonymous »

Я хотел бы построить фальшивый хост Gimp в C# для запроса /запустить плагин Windows Gimp.

для справки, в конце этого сообщения вы найдете то, что я понял из протокола, чтобы поговорить с плагином Gimp. 3 вещи < /p>

[*] Используйте CreatePipe из kernel32, затем iochannel.fromhandle

// сбои с системой. />
// Не удается после
Некоторые секунды с (0xc0000409) < /p>
< /li>
Использовать _pipe из msvcrt.dll then _get_osfhandle (fd [0]) затем
ikannel.fromhandle(radehandle); /> system.accessviolationException
< /li>
< /ul>
Последние два «лучше», потому что они используют _pipe, которая возвращает дескриптор файла int, который мне нужен, когда первые возвращают intptr.

Код: Выделить всё

using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using GLib;

class PipeTalker
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe,
IntPtr lpPipeAttributes, uint nSize);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);

[DllImport("msvcrt.dll", SetLastError = true)]
private static extern int _pipe(out IntPtr filedes, uint size, int textmode);

// For _pipe, you pass an int array of 2 elements. This signature adapted accordingly:
[DllImport("msvcrt.dll", SetLastError = true)]
private static extern int _pipe(int[] pfds, uint size, int textmode);

[DllImport("msvcrt.dll", SetLastError = true)]
private static extern IntPtr _get_osfhandle(int fd);

const int _O_BINARY = 0x8000; // 0x0200 0x8000 ?

private IOChannel ioRead;
private IOChannel ioWrite;

private bool GioIn(IOChannel source, IOCondition condition)
{
if ((condition & IOCondition.Hup) == IOCondition.Hup)
{
Console.WriteLine("Read end of pipe closed.");
return false; // Arrêter le watch
}

try
{
source.ReadLine(out string line, out ulong length);
if (line != null)
{
Console.WriteLine($"Received ({length} bytes): {line}");
}
}
catch (Exception e)
{
Console.WriteLine("Error reading from pipe: " + e.Message);
return false;
}
return true; // Continuer le watch
}

private bool GioOut(IOChannel source, IOCondition condition)
{
if ((condition & IOCondition.Hup) == IOCondition.Hup)
{
Console.WriteLine("Write end of pipe closed.");
return false;
}

string message = "The price of greatness is responsibility.\n";

try
{
source.WriteChars(Encoding.ASCII.GetBytes(message), out ulong length);
source.Flush();
Console.WriteLine($"Sent {length} bytes.");
}
catch (Exception e)
{
Console.WriteLine("Error writing to pipe: " + e.Message);
return false;
}

return false;
}

public void InitChannels()
{
bool success = CreatePipe(out IntPtr readHandle, out IntPtr writeHandle, IntPtr.Zero, 4096);
if (!success)
{
Console.WriteLine("Failed to create pipe. Error code: " + Marshal.GetLastWin32Error());
return;
}

ioRead  = IOChannel.FromHandle(readHandle); // FAILS with System.AccessViolationException
ioWrite = IOChannel.FromHandle(writeHandle);

// alternative.  Fails too

int[] fd = new int[2]; // file descriptor
int ret;

// setup a pipe
// was  ret = Posix.pipe(fd);
ret = _pipe(fd, 4096, _O_BINARY);

if (ret == -1)
{
Console.Write("Creating pipe failed: \n"); // use IOChannel.ErrorFromErrno ?
return;
}

ioRead = new IOChannel(fd[0]); // FAILS after some seconds with (0xc0000409)

// other alternative
readHandle = _get_osfhandle(fd[0]);
ioRead = IOChannel.FromHandle(readHandle); // FAILS with System.AccessViolationException 

if (ioRead == null || ioWrite == null)
{
Console.WriteLine("Failed to create IOChannels.");
return;
}

// Ajouter watcher pour lecture (IN | HUP)
ioRead.AddWatch(0,IOCondition.In | IOCondition.Hup, GioIn);

// Ajouter watcher pour écriture (OUT | HUP)
ioWrite.AddWatch(0,IOCondition.Out | IOCondition.Hup, GioOut);
}

static void Main()
{
string gtklibs = @"C:\gtk\bin"; //
string currentPath = Environment.GetEnvironmentVariable("PATH") ?? "";
if (!currentPath.Split(';').Contains(gtklibs))
{
Environment.SetEnvironmentVariable("PATH", gtklibs + ";" + currentPath);
}

GLib.ExceptionManager.UnhandledException += (sender) =>
{
;
Exception e = (Exception)sender.ExceptionObject;
Console.WriteLine("GLib Unhandled Exception: " + e.Message);
sender.ExitApplication = true;
};

var pt = new PipeTalker();
pt.InitChannels();

Console.WriteLine("Starting GLib MainLoop...");
var loop = new MainLoop();
loop.Run();

Console.WriteLine("MainLoop exited, cleaning up.");

// free handles
if (pt.ioRead != null)
CloseHandle(pt.ioRead.Handle);
if (pt.ioWrite != null)
CloseHandle(pt.ioWrite.Handle);
}
}
< /code>
Программа собирается с использованием Visual Studio в качестве «любого ЦП» без «предпочтения 32 бита».
Глиб ссылается через NUGET. < /p>
==== />Open pipe;
[*]Fork the program;
[*]run '"C:\Program Files\GIMP 3\lib\gimp\3.0\plug-ins\fractal-explorer\fractal-explorer.exe" -gimp 277 5 4 -query 0' as the child
ping/pong text in the трубы.ARG_PROGNAME,           // self explaining
ARG_GIMP,               // string "-gimp"
ARG_PROTOCOL_VERSION,   // 277 looks strange but will pass it anyways
ARG_READ_FD,            // int that maps the file descriptor for reading; here 5
ARG_WRITE_FD,           // int that maps the file descriptor for reading; here 4
ARG_MODE,               // string '-run', '-query','-init'
ARG_STACK_TRACE_MODE,   // debug mode 0 = no debug
Команды будут прочитаны в плагине

см. https://gitlab.gnome.org/gnome/gimp/-/b ... imp/gimp.c строка 440

Код: Выделить всё

...
read_channel  = g_io_channel_win32_new_fd (atoi (argv[ARG_READ_FD]));
write_channel = g_io_channel_win32_new_fd (atoi (argv[ARG_WRITE_FD]));
...
= это создаст iochannel для общения с родительским процессом.>

Подробнее здесь: https://stackoverflow.com/questions/797 ... -from-them
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»