Author: Andreas Herrmann
Date: 12:53:19 04/06/04
Go up one level in this thread
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
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.