Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
Gork
Založen: 25. 06. 2015 Příspěvky: 8
|
Zaslal: 25. červen 2015, 11:43:10 Předmět: RedirectStandardInput u Torque3D dedicated serveru |
|
|
Ahoj!
Pracuju na "remote console multiple-dedicated server" manageru pro Torque3D hru a trochu jsem se zasekl na psaní do StandardInput(stdin) streamu.
Psal jsem prakticky identický program pro Open Transport Tycoon, kde vše fungovalo perfektně. Nutno dodat, že outputy mi fungují. Server má na input reagovat minimálně errorem, na můj input(skrze můj manager) nereaguje vůbec nijak. Zapisuji přes StreamWriter, zkoušel jsem však i BinaryWriter.
Viz pár důležitých řádek kódu:
kód: |
sessionProc = new Process();
sessionProc.StartInfo.FileName = Config.ExecPath;
sessionProc.StartInfo.UseShellExecute = false;
sessionProc.StartInfo.RedirectStandardInput = true;
sessionProc.StartInfo.RedirectStandardOutput = true;
sessionProc.StartInfo.RedirectStandardError = true; |
kód: |
...
StreamWriter writer = sessionProc.StandardInput;
public void Write(string input)
{
if (writer != null)
{
writer.Write(input);
writer.Flush();
}
} |
Jako bonus mám ještě v kódu úpravu binárky tak, aby se její okno dalo úplně schovat:
kód: |
FileStream file = new FileStream(Config.ExecPath, FileMode.Open, FileAccess.ReadWrite);
byte[] buffer = new byte[file.Length];
file.Read(buffer, 0, buffer.Length);
int offset = (((buffer[0x3f] << 8 | buffer[0x3e]) << 8 | buffer[0x3d]) << 8 | buffer[0x3c]) + 92;
if (buffer[offset] == 2)
{
buffer[offset] = 3;
file.Seek(0, SeekOrigin.Begin);
file.Write(buffer, 0, buffer.Length);
} |
Ovšem input nefunguje i bez upravené binárky, takže v tom problém nebude. Uvádím jen preventivně.
Nemá někdo tušení, co můžu mít špatně? Server označuje začátek inputu znakem '%', ale to bude předpokládám jen grafické znázornění. Pokud by měl někdo alespoň nápad, co bych měl zkusit, budu si toho velmi vážit. Už třetí den si s tím nevím rady. Díky!
PS: Postřeh na závěr. Ptát se na StackOverflow asi nemá smysl, než si toho někdo všimne, zmizí to v záplavě dalších dotazů. Na oficiálním fóru se k tomu taky nikdo nevyjadřuje... Snad se na mě nevykašlete alespoň vy |
|
Návrat nahoru |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 25. červen 2015, 21:27:09 Předmět: Re: RedirectStandardInput u Torque3D dedicated serveru |
|
|
kód: |
int offset = (((buffer[0x3f] << 8 | buffer[0x3e]) << 8 | buffer[0x3d]) << 8 | buffer[0x3c]) + 92;
|
Tohle je typo, ne? Ať už patchuješ cokoliv Pokud je offset do 64k, tak to ale bude jedno.
(Jinak s SO mám celkem dobré zkušenosti, jednou jsem se ptal na něco velmi specifického a po třech měsících mi někdo odpověděl a opravdu to můj problém vyřešilo) |
|
Návrat nahoru |
|
|
Gork
Založen: 25. 06. 2015 Příspěvky: 8
|
Zaslal: 25. červen 2015, 21:36:30 Předmět: |
|
|
Abych pravdu řekl, kód jsem převzal od nějakého chlapce z OTTD scény. Používalo se to na skrytí konzole. Neznám teorii za tím, ale funguje to. Takže místo prázdného okna původní aplikace(prázdné je, protože mám vše redirectnuté) mám jen okno své aplikace. Zkusím to ještě dohledat a pak to rozvedu
UPDATE: Někde jsem našel, že je problém se zápisem do stdin, když C++ appka používá k čtení konzole f-ci ReadConsoleInput(což Torque3D využívá). Bohužel příliš kódu C++ nerozumím... |
|
Návrat nahoru |
|
|
mar
Založen: 16. 06. 2012 Příspěvky: 608
|
Zaslal: 25. červen 2015, 22:08:31 Předmět: |
|
|
No na 0x3c je offset na PE header.
Vzhledem k tomu, že je vždycky blízko (používá se většinou jenom LSByte), tak to problém není. Teoreticky by ale být mohl.
Správně je
kód: |
int offset = (((buffer[0x3f] << 24 | buffer[0x3e]) << 16 | buffer[0x3d]) << 8 | buffer[0x3c])
|
Na tom offsetu je typ subsystému. 3 je GUI (tj. vytváří si okno sám) a 2 je konzole.
Nicméně to tvůj problém bohužel neřeší.
EDIT: Jinak pokud se dá věřit ReactOSu, že to mají stejně jako windows,
tak WriteFile pokud je to console handle tak automaticky volá WriteConsole, jinak volá NtWriteFile, takže teoreticky by to fungovat mělo.
EDIT2: Nevšiml jsem si těch závorek, ten kód byl správně
Naposledy upravil mar dne 26. červen 2015, 19:32:23, celkově upraveno 1 krát |
|
Návrat nahoru |
|
|
Gork
Založen: 25. 06. 2015 Příspěvky: 8
|
Zaslal: 25. červen 2015, 23:54:44 Předmět: |
|
|
Našel jsem o tom nějakou teorii. Pokud jsem správně pochopil, musím využít low-level zápis do input bufferu(CONIN$?). Všechno je to pro mě španělská vesnice, doufal jsem, že nikdy nebudu muset do WinAPI zabředávat(nejsem programátor, studuju medicínu).
Dokázal bys mě trochu nasměrovat? Jak zjistit handle, do kterého zapisovat? Chápu to tak, že využívají(TGE) f-ci, která "obchází" high-level redirect. Nějak jsem došel k API f-cím na CreateFile(google mě směruje na ten CONIN$) a WriteFile. Nějak mi ale nejde do hlavy, jak zjistit handle toho inputu. Asi míchám jablka s hruškama. Fakt mě z toho bolí hlava
Díky za odpovědi a trpělivost!
EDIT: http://pastebin.com/D1g3Lx7J
Funkce konzole u TGE. |
|
Návrat nahoru |
|
|
Radis
Založen: 29. 03. 2014 Příspěvky: 235
|
Zaslal: 26. červen 2015, 06:52:26 Předmět: |
|
|
Zkusil bych kombinaci FindWindow + SetForegroundWindow (WinAPI) + .NET SendKeys. Kdyz nechces, aby to okno bylo videt, tak pouzij SetWindowPos (WinAPI) a nastav oknu souradnice mimo obrazovku treba na (-2000,-2000) nebo neco takoveho. (Protoze ProcStartInfo.CreateNoWindow pouzit nemuzes, jinak bys mu nemohl posilat SendKeys). Exe soubor bych nepatchoval, je to zbytecne |
|
Návrat nahoru |
|
|
Gork
Založen: 25. 06. 2015 Příspěvky: 8
|
Zaslal: 26. červen 2015, 11:54:34 Předmět: |
|
|
Chtěl jsem se co nejvíce vyhnout volání API funkcí. Z osobní zkušenosti ale můžu říct, že daleko víc vadí omylem vypnout prázdné okno serveru, než patchování exe souboru. Každopádně se o tom můžeme později pobavit, byla to spíše záležitost estetiky, kterou si mohl kdokoliv vypnout. Teď ale prosím všechny: vyjadřujte se jen k mému dotazu. Přesto si cením všech reakcí(né těch biochemických, za pár dní mě čeká zkouška ). |
|
Návrat nahoru |
|
|
Radis
Založen: 29. 03. 2014 Příspěvky: 235
|
Zaslal: 26. červen 2015, 12:34:15 Předmět: |
|
|
citace: |
vyjadřujte se jen k mému dotazu |
To nebylo na me, ze ne? Protoze jsem si nevsiml, ze bych mluvil nejak mimo tema
Zkus to takhle nejak (FindWindow nakonec ani neni potreba, protoze handle okna se da ziskat primo z Processu):
kód: |
void TestSendKeys()
{
var procInfo = new ProcessStartInfo {
FileName = "program.exe",
RedirectStandardOutput = true,
UseShellExecute = false,
};
var process = Process.Start(procInfo);
IntPtr handle = IntPtr.Zero;
while ((handle = process.MainWindowHandle) == IntPtr.Zero) {
Thread.Sleep(10);
}
SetWindowPos(handle, IntPtr.Zero, -2000, -2000, 1, 1, 0);
SetForegroundWindow(handle);
System.Windows.Forms.SendKeys.Send("ahoj");
}
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError=true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int flags);
|
|
|
Návrat nahoru |
|
|
Gork
Založen: 25. 06. 2015 Příspěvky: 8
|
Zaslal: 26. červen 2015, 21:59:00 Předmět: |
|
|
Promiň, viděl jsem něco o SetWindowPos a už jsem tak nějak tušil, že se bude řešit pozice okna a jeho skrytí
Tvé řešení bohužel nefunguje. Aplikace je bez reakce. |
|
Návrat nahoru |
|
|
|