Здравствуйте Все!
Дано: есть программа А под DOS, ее пользовательский интерфейс очень не френдли, исходников ее нет, работает только под Win98 (потому как она работает с железом), переписать ее функционал невозможно в силу определенных адекватных причин.
Задача: написать программу Б, которая будет управлять программой А, но будет еще и другие функции выполнять и иметь красивый пользовательский интерфейс.
Я написала программу Б' пока консольную, чтобы отработать подходы. Теперь, у меня есть консольная Б' оболочка программы А, которая ей и управляет.
Но! я это все делала под WinXP, а под Win98 эта программа не работает.
Стала разбираться:
1. я перенаправляю поток ввода, задавая указатель на HANDLE созданного pipe, в этот pipe я пишу WriteFile нужные символы. Почему именно так: потому что если не создавать pipe а создавать HANDLE by CreateFile, то когда заканчивается поток из файла, программа А закрывается, не доделав работу. А если создать pipe, то его я закрываю CloseHandle через секунд ~30, чтобы программа А все успела сделать.
2. в Win98 если я делаю CreateFile то данные из него отправляются в А, но она рано закрывается (т.е. программа не начинает работать с железом, а сразу закрывается). Если я делаю CreatePipe то данные в нее вообще не отправляются.
Я написала тестовую программку A'
#include <stdio.h>
int main (void)
{
FILE* file = fopen("test.txt", "w");
char ch[1000];
scanf("%s", &ch);
fprintf(file, "%s\n", ch);
fclose(file);
return 0;
}
Вот код оболочки Б' для A.
#include <windows.h>
#include <conio.h>
#define BUFSIZE 4096
#define PROGA "test.exe"
DWORD main(int argc, char *argv[])
{
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
HANDLE hChildStdinRd, hChildStdinWr;
BOOL boo = CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0);
HANDLE hChildStdinWrDup;
BOOL fSuccess = DuplicateHandle(
GetCurrentProcess()
, hChildStdinWr
, GetCurrentProcess()
, &hChildStdinWrDup
, 0
, FALSE
, DUPLICATE_SAME_ACCESS
);
CloseHandle(hChildStdinWr);
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.lpReserved = NULL;
siStartInfo.lpDesktop = NULL;
siStartInfo.lpTitle = NULL;
siStartInfo.dwFlags = STARTF_USESTDHANDLES;
siStartInfo.cbReserved2 = 0;
siStartInfo.lpReserved2 = NULL;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.hStdError = NULL;
siStartInfo.hStdOutput = NULL;
BOOL bFuncRetn = ::CreateProcess(
NULL
, PROGA // command line
, &saAttr // process security attributes
, NULL // primary thread security attributes
, TRUE // handles are inherited
, 0 // creation flags
, NULL // use parent's environment
, NULL // use parent's current directory
, &siStartInfo // STARTUPINFO pointer
, &piProcInfo); // receives PROCESS_INFORMATION
if (bFuncRetn)
{
DWORD dwWritten;
CHAR chBuf[BUFSIZE] = "IV";
WriteFile(hChildStdinWrDup, chBuf, strlen(chBuf), &dwWritten, NULL);
// если закрыть этот hChildStdinWrDup, то прога закроется точно также, как при
// CreateFile или <. Но, мне нужно дождаться работы программы А, поэтому,
// я жду 30 секунд
//Sleep(30*1000);
//CloseHandle(hChildStdinWrDup);
// либо сделаю так
//DWORD dwWaitResult = ::WaitForSingleObject(piProcInfo.hProcess, INFINITE);
// как именно сделаю, я еще не знаю, т.к. не могу протестировать это под Win98
// сейчас для скорости
Sleep(1000);
CloseHandle(hChildStdinWrDup);
CloseHandle(piProcInfo.hThread);
CloseHandle(piProcInfo.hProcess);
}
return 0;
}
Приведенный код под Win98 работает, но! если вместо A' взять A, то этот же код под Win98 перестает работать, но под WinXP он работает!
Hints:
1. переопределять вывод не нужно, т.к. программа А создает файл, который и нужен потом будет.
2. повторюсь: Программе А нужно передать последовательность нажатий с клавиатуры следующих символов IV1\n\r\n\rYY, подождать 30 секунд и получить файл с результатами. Если я создаю файл c.txt с этой последовательностью символов и пишу А.exe < c.txt, то программа закрывается сразу, как только она отработает последний Y (это я успеваю увидеть на медленном компьютере), даже и не начиная работать с железом!!! Так же себя она ведет, если я переопределяю in поток и указываю HANDLE созданный CreateFile. Но! если я указываю HANDLE созданный CreatePipe и , передав строку, закрываю HANDLE другого конца трубы только через 30 секунд, то программа все успевает сделать, а если я закрываю его после Y, то она
сразу же закроется.
Теперь, вопрос более четко: что может быть причиной такой работы? Что там в А программе могло быть такого, что под WinXP это работает, а под Win98 нет? (под Win2000 я не проверяла). Почему программа А при завершении in потока, не доделав работы, закрывается?
Есть ли у кого идеи?