различия работы DOS программы под различные ОС
От: Зрение  
Дата: 25.07.05 06:39
Оценка:
Здравствуйте Все!

Дано: есть программа А под 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 потока, не доделав работы, закрывается?

Есть ли у кого идеи?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.