Author: Lothar Hummel
Date: 11:53:07 04/07/04
Go up one level in this thread
On April 06, 2004 at 15:53:19, Andreas Herrmann wrote:
>On April 06, 2004 at 14:48:57, Lothar Hummel wrote:
>
>>On April 06, 2004 at 13:18:24, Andreas Herrmann wrote:
>>
>>>On April 06, 2004 at 13:09:53, Andreas Herrmann wrote:
>>>
>>>>On April 06, 2004 at 10:35:54, Lothar Hummel wrote:
>>>>
>>>>>
>>>>>Wie kann ich von einem in Delphi 3 geschriebenen Programm (also aus GUI-Sicht)
>>>>>eine UCI-Engine aufrufen ? Nach langer Suche habe ich nur den "shellexecute"
>>>>>gefunden, dann erscheint aber das aufgerufene Programm als eigenständiger Task
>>>>>unter Windows, ohne jede Verbindung zum aufrufenden Programm.
>>>>>
>>>>>Die Standard-Ein/Ausgabe gibts zwar auch in Delphi, sie funktioniert aber nur
>>>>>bei sogenannten "Konsolenanwendungen", eine GUI ist aber genau das Gegenteil
>>>>>davon. Kennt zufällig jemand eine konkrete Lösung für Aufruf und Datenaustausch
>>>>>?
>>>>
>>>>Hi,
>>>>
>>>>du solltest hier im Netz nach "Redirect standard input ouput" suchen. Da findest
>>>>du ein oder zwei C Beispiele im Netz, die du dann nach deinen Anforderungen
>>>>übersetzten und anpassen kannst. Du kannst aber z.B. auch in der Win API Hilfe
>>>>nach "CreatePipe","PeekNamedPipe" ... suchen und es selbst erarbeiten. Ev.
>>>>findest du auch etwas in der Microsoft MSDN dazu.
>>>>
>>>>Ich habe da letztes Jahr auch eine Delphi Komponente entwickelt. Falls du einige
>>>>Wochen warten kannst, findest du dann meine Delphi Komponente auf
>>>>http://wbholmes.de. Die momentane Version kann nur mit einem externen Prozess
>>>>kommunizieren und läuft auch noch nicht in einem separaten Thread. Sobald ich
>>>>Zeit habe werde ich die Komponente aber neu schreiben, damit auch die eben
>>>>beschriebenen Nachteile behoben sind.
>>>>
>>>>Andreas
>>>
>>>noch vergessen zu erwähnen: Anstatt ShellExecute mußt du CreateProcess
>>>verwenden. Siehe dazu vor allem auch unter LPSTARTUPINFO, da mußt du die
>>>Input/Output Handles entsprechend zuweisen.
>>>
>>>viel Erfolg
>>>Andreas
>>
>>hallo Andreas,
>>Danke erstmal für Deine Tips ! Den "createprocess" habe ich gefunden, allerdings
>>sind ja da unendlich viele Parameter mitzugeben ! Bei meiner Delphi-Version 3,
>>damals original in Deutsch gekauft (keine Raubkopie), ist zu Win api keinerlei
>>Dokumentation oder Hilfe beigefügt. Was man nicht erahnen kann, ist dann,
>>zumindest für mich, meist nicht anzuwenden. Gibts irgendwo Hilfe zu den ganzen
>>Windows-Schnittstellen ?
>>
>>Grüße, Lothar
>
>ich kann dir das folgende Buch dazu empfehlen:
>Delphi Win32 Lösungen
>Andreas Kosch
>Software & Support Verlag
>ISBN 3-9806738-2-0
>
>Das Buch behandelt u.a. auch verschiedene Möglichkeiten der Interprozess
>Kommunikation, wie z.B. Named Pipes.
>
>Im Entwickler Forum (http://www.entwickler.com/) hilft man dir bestimmt auch
>weiter. Der Author des obigen Buches beantwortet dort übrigens auch oft Fragen.
>
>Und noch etwas source code, den ich irendwo im Internet gefunden hatte, und der
>mir bei der Entwicklung der Delphi Komponente auch hilfreich war.
>
>
>Subject: How to create a process and control its flow by redirecting its
>standard input/output to your parent process.
>Introduction: In this article, I will explain how to spawn a console application
>and redirect its standard input/output using anonymous pipes. An anonymous pipe
>is a pipe that goes only in one direction (read pipe, write pipe, etc.). Maybe
>you are asking, "why would I ever need to do this sort of thing?" One example
>would be a Windows telnet server, where you spawn a shell and listen on a port
>and send and receive data between the shell and the socket client. (Windows does
>not really have a built-in remote shell).
>First, we should talk about pipes. A pipe in Windows is simply a method of
>communication, often between process. The SDK defines a pipe as "a communication
>conduit with two ends; a process with a handle to one end can communicate with a
>process having a handle to the other end." In our case, we are using "anonymous"
>pipes, one-way pipes that "transfer data between a parent process and a child
>process or between two child processes of the same parent process." It's easiest
>to imagine a pipe as its namesake. An actual pipe running between processes that
>can carry data.
>
>We are using anonymous pipes because the console app we are spawning is a child
>process. We use the CreatePipe function which will create an anonymous pipe and
>return a read handle and a write handle. We will create two pipes, on for stdin
>and one for stdout. We will then monitor the read end of the stdout pipe to
>check for display on our child process. Every time there is something availabe
>for reading, we will display it in our app. Consequently, we check for input in
>our app and send it off to the write end of the stdin pipe.
>
>Code: Sample app that spawns a shell and redirects its i/o
>//------------Sample using CreateProcess and Anonymous Pipes-----------------
>//---------------------childspawn.cpp----------------------------------------
>//---------------------use freely--------------------------------------------
>#include <windows.h>
>#include <stdio.h>
>#include <conio.h>
>#include <string.h>
>#pragma hdrstop
>#include <condefs.h>
>
>#define bzero(a) memset(a,0,sizeof(a)) //easier -- shortcut
>
>bool IsWinNT() //check if we're running NT
>{
> OSVERSIONINFO osv;
> osv.dwOSVersionInfoSize = sizeof(osv);
> GetVersionEx(&osv);
> return (osv.dwPlatformId == VER_PLATFORM_WIN32_NT);
>}
>
>void ErrorMessage(char *str) //display detailed error info
>{
> LPVOID msg;
> FormatMessage(
> FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
> NULL,
> GetLastError(),
> MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
> (LPTSTR) &msg,
> 0,
> NULL
> );
> printf("%s: %s\n",str,msg);
> LocalFree(msg);
>}
>
>//---------------------------------------------------------------------------
>void main()
>{
> char buf[1024]; //i/o buffer
>
> STARTUPINFO si;
> SECURITY_ATTRIBUTES sa;
> SECURITY_DESCRIPTOR sd; //security information for pipes
> PROCESS_INFORMATION pi;
> HANDLE newstdin,newstdout,read_stdout,write_stdin; //pipe handles
>
> if (IsWinNT()) //initialize security descriptor (Windows NT)
> {
> InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
> SetSecurityDescriptorDacl(&sd, true, NULL, false);
> sa.lpSecurityDescriptor = &sd;
> }
> else sa.lpSecurityDescriptor = NULL;
> sa.nLength = sizeof(SECURITY_ATTRIBUTES);
> sa.bInheritHandle = true; //allow inheritable handles
>
> if (!CreatePipe(&newstdin,&write_stdin,&sa,0)) //create stdin pipe
> {
> ErrorMessage("CreatePipe");
> getch();
> return;
> }
> if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //create stdout pipe
> {
> ErrorMessage("CreatePipe");
> getch();
> CloseHandle(newstdin);
> CloseHandle(write_stdin);
> return;
> }
>
> GetStartupInfo(&si); //set startupinfo for the spawned process
> /*
> The dwFlags member tells CreateProcess how to make the process.
> STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW
> validates the wShowWindow member.
> */
> si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
> si.wShowWindow = SW_HIDE;
> si.hStdOutput = newstdout;
> si.hStdError = newstdout; //set the new handles for the child process
> si.hStdInput = newstdin;
> char app_spawn[] = "d:\\winnt\\system32\\cmd.exe"; //sample, modify for your
> //system
>
> //spawn the child process
> if (!CreateProcess(app_spawn,NULL,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
> NULL,NULL,&si,&pi))
> {
> ErrorMessage("CreateProcess");
> getch();
> CloseHandle(newstdin);
> CloseHandle(newstdout);
> CloseHandle(read_stdout);
> CloseHandle(write_stdin);
> return;
> }
>
> unsigned long exit=0; //process exit code
> unsigned long bread; //bytes read
> unsigned long avail; //bytes available
>
> bzero(buf);
> for(;;) //main program loop
> {
> GetExitCodeProcess(pi.hProcess,&exit); //while the process is running
> if (exit != STILL_ACTIVE)
> break;
> PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);
> //check to see if there is any data to read from stdout
> if (bread != 0)
> {
> bzero(buf);
> if (avail > 1023)
> {
> while (bread >= 1023)
> {
> ReadFile(read_stdout,buf,1023,&bread,NULL); //read the stdout pipe
> printf("%s",buf);
> bzero(buf);
> }
> }
> else {
> ReadFile(read_stdout,buf,1023,&bread,NULL);
> printf("%s",buf);
> }
> }
> if (kbhit()) //check for user input.
> {
> bzero(buf);
> *buf = (char)getche();
> //printf("%c",*buf);
> WriteFile(write_stdin,buf,1,&bread,NULL); //send it to stdin
> if (*buf == '\r') {
> *buf = '\n';
> printf("%c",*buf);
> WriteFile(write_stdin,buf,1,&bread,NULL); //send an extra newline char,
> //if necessary
> }
> }
> }
> CloseHandle(pi.hThread);
> CloseHandle(pi.hProcess);
> CloseHandle(newstdin); //clean stuff up
> CloseHandle(newstdout);
> CloseHandle(read_stdout);
> CloseHandle(write_stdin);
>}
>//----------------------------EOF--------------------------------------------
>//---------------------------------------------------------------------------
>
>
>Gruß
>Andreas
hallo Andreas,
habe das Ganze in Delphi umgeschrieben und bei mir eingebaut und siehe da, es
funktioniert tadellos ! Danke nochmal, Du warst mir eine große Hilfe !
Gruß
LOthar
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.