2016-05-25 4 views
4

ОБНОВЛЕНИЕ Вопрос: Итак, я смог создать процесс и собрать программы для компиляции. Однако я столкнулся с новой проблемой. Когда я пытаюсь передать программу Source в программу Filter. Кажется, что он не подает ни один вход для программы раковины. Сообщение об ошибке отсутствует. Я также тестировал всю свою автономную программу, используя оператор трубы в Windows 'cmd.Создать процесс и анонимный канал

Я пытаюсь сделать этот небольшой проект, чтобы узнать об анонимной трубе и создать процесс. Я создал 3 небольшие автономные программы, называемые Source, Filter и Sink. Эти 3 уже скомпилированы и работают нормально. Ниже приведены описания для 3 автономных программ.

Источник: получает исходное текстовое имя файла из своей командной строки, открывает файл и считывает и копирует содержимое файла по одному символу за раз непосредственно до стандартного вывода (stdout). Когда файл был скопирован, Source завершает работу (закрывая все открытые дескрипторы файла).

Программа фильтра не использует параметры командной строки имени файла. Вместо этого фильтр считывает текстовый файл со стандартного ввода (stdin) и записывает на стандартный вывод (stdout) копию ввода со всеми прописными буквами, преобразованными в нижний регистр. Фильтр специально должен быть предназначен для чтения одного символа, преобразования его, вывода его и последующего цикла до тех пор, пока входящие данные не будут завершены.

Программа Sink получает имя файла текстового файла назначения из своей командной строки, открывает файл для записи, а затем считывает символы по одному из стандартного входного файла (stdin) и записывает каждый входящий символ непосредственно в файл приемника ,

Далее я запускаю программу основного драйвера отдельно, которая создает 2 канала и создает 3 независимых дочерних элемента с входами и выходами, сконфигурированными для выполнения указанного параллельного выполнения и потока данных. Что-то вроде этого:

  • srcfile -> Источник -> Pipe1 -> Фильтр -> Pipe2 -> Раковина -> DestFile

Программа водитель требует параметров линии 2 команды:

  • C:\> Driver.exe srcfile destfile

где srcfile это существующие данные текстового файла, и destfile - имя файла нового целевого файла, который должен быть создан приложением Sink.

Вот мой код для программы водителя. Это еще не закончено. Но при попытке создать процесс для исходной программы я столкнулся с икотой.

ОБНОВЛЕНО КОД:

#include <windows.h> 
#include <WinBase.h> 
#include <stdio.h> 


#define DELAY_A_WHILE() {volatile long j; for(j = 1; j< 10000; j++) ; } 

int main(int argc, char *argv[]) 
{ 
    HANDLE hPipeRead, hPipeWrite, hPipeRead2, hPipeWrite2; 
    STARTUPINFO StartupInfoSource; 
    STARTUPINFO StartupInfoFilter; 
    STARTUPINFO StartupInfoSink; 
    PROCESS_INFORMATION ProcInfoSource; 
    PROCESS_INFORMATION ProcInfoFilter; 
    PROCESS_INFORMATION ProcInfoSink; 
    SECURITY_ATTRIBUTES PipeAttributes; 
    SECURITY_ATTRIBUTES PipeAttributes2; 
    char cmdline[200]; 

    PipeAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); 
    PipeAttributes.lpSecurityDescriptor = NULL;  //ignore 
    PipeAttributes.bInheritHandle = TRUE;   //child can inherit 

    //Create first pipe 
    if (!CreatePipe(&hPipeRead, &hPipeWrite, &PipeAttributes, 0)) { 
     fprintf(stderr, "Error creating pipe: %d\n", GetLastError()); 
     exit(1); 
    } 

    sprintf_s(cmdline, 200, "Source.exe %s", argv[1]); 
    printf("Create process: %s\n", cmdline); 

    GetStartupInfo(&StartupInfoSource); 
    StartupInfoSource.dwFlags = StartupInfoSource.dwFlags | STARTF_USESTDHANDLES; 


    //Mapping 
    StartupInfoSource.hStdInput = GetStdHandle(STD_INPUT_HANDLE); 
    StartupInfoSource.hStdOutput = hPipeWrite; 
    StartupInfoSource.hStdError = GetStdHandle(STD_ERROR_HANDLE); 

    if (!CreateProcess(
     NULL, cmdline, NULL, NULL, 
     TRUE, 
     CREATE_NEW_CONSOLE, NULL, NULL, 
     &StartupInfoSource, 
     &ProcInfoSource)) 
    { 
     fprintf(stderr, "Error creating child process: %d",GetLastError()); 
     exit(1); 
    } 

    CloseHandle(hPipeWrite); 
    CloseHandle(ProcInfoSource.hProcess); 
    CloseHandle(ProcInfoSource.hThread); 

    PipeAttributes2.nLength = sizeof(SECURITY_ATTRIBUTES); 
    PipeAttributes2.lpSecurityDescriptor = NULL;  //ignore 
    PipeAttributes2.bInheritHandle = TRUE;   //child can inherit 
    //Create Second Pipe 
    if (!CreatePipe(&hPipeRead2, &hPipeWrite2, &PipeAttributes2, 0)) { 
     fprintf(stderr, "Error creating pipe: %d\n", GetLastError()); 
     exit(1); 
    } 

    GetStartupInfo(&StartupInfoFilter); 
    StartupInfoFilter.dwFlags = StartupInfoFilter.dwFlags | STARTF_USESTDHANDLES; 

    //Mapping 
    StartupInfoFilter.hStdInput = hPipeRead; 
    StartupInfoFilter.hStdOutput = hPipeWrite2; 
    StartupInfoFilter.hStdError = GetStdHandle(STD_ERROR_HANDLE); 

    sprintf_s(cmdline, 200, "Filter.exe"); 
    printf("Create process: %s\n", cmdline); 

    //Filter 
    GetStartupInfo(&StartupInfoFilter); 
    if (!CreateProcess(
     NULL, cmdline, NULL, NULL, 
     TRUE, 
     CREATE_NEW_CONSOLE, NULL, NULL, 
     &StartupInfoFilter, 
     &ProcInfoFilter)) 
    { 
     fprintf(stderr, "Error creating child process: %d", GetLastError()); 
     exit(1); 
    } 
// int exitStatus; 
    // GetExitCodeProcess(ProcInfoFilter.hProcess, &exitStatus); 
    CloseHandle(hPipeRead); 
    CloseHandle(hPipeWrite2); 
    CloseHandle(ProcInfoFilter.hProcess); 
    CloseHandle(ProcInfoFilter.hThread); 


    GetStartupInfo(&StartupInfoSink); 
    StartupInfoSink.dwFlags = StartupInfoSink.dwFlags | STARTF_USESTDHANDLES; 



    //Mapping 
    StartupInfoSink.hStdInput = hPipeRead2; 
    StartupInfoSink.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 
    StartupInfoSink.hStdError = GetStdHandle(STD_ERROR_HANDLE); 

    sprintf_s(cmdline, 200, "Sink.exe %s", argv[2]); 
    printf("Create process: %s\n", cmdline); 

    GetStartupInfo(&StartupInfoSink); 
    if (!CreateProcess(
     NULL, cmdline, NULL, NULL, 
     TRUE, 
     CREATE_NEW_CONSOLE, NULL, NULL, 
     &StartupInfoSink, 
     &ProcInfoSink)) 
    { 
     fprintf(stderr, "Error creating child process: %d", GetLastError()); 
     exit(1); 
    } 

    CloseHandle(hPipeRead2); 
    CloseHandle(ProcInfoSink.hProcess); 
    CloseHandle(ProcInfoSink.hThread); 


    return 0; 
} 

Программа компилируется нормально. Однако, когда он пытается создать Process, он всегда терпит неудачу и завершается. Значение cmdline при анализе - «Source.exe test.txt», что я и использовал для выполнения автономной исходной программы. Может кто-нибудь объяснить, почему мой CreateProcess не удается? Это потому, что я анализирую неправильный параметр?

+0

Итак, вы говорите, что «CreateProcess» терпит неудачу? Затем вы должны изучить код ошибки, возвращаемый 'GetLastError'. Кстати, правильно ли вы передаете «STARTUPINFO» вызывающего процесса? Это передать дескрипторы stdin и stdout? –

+0

Когда я пытаюсь отлаживать, программа всегда выполняет кусок кода внутри, если (! CreateProcess()), который должен печатать ошибку, когда не удается создать и выйти из программы. –

ответ

2

Единственная проблема, которую я вижу здесь, - это возможность того, что приложение Source.exe не находится в том же каталоге, где находится Driver.exe. Я пробовал ваш код, и это был единственный случай, когда CreateProcess не удалось.

+0

My source.exe находится в той же папке, что и файл Driver.c. Правильно ли это место? –

+0

Nope. Ваш двоичный файл обычно помещается в папку «Отпуск» или «Отладка» (в зависимости от того, какую конфигурацию сборки вы используете). Если вы создали свой проект с включенной опцией «Создать каталог для решения», вы увидите две разные версии и две разные папки отладки. Вам нужен тот, который находится в верхних слоях структуры вашего каталога. В любом случае, просто попробуйте найти точное местоположение файла driver.exe и поместите source.exe в эту папку. –

+0

Я уже сделал. И он по-прежнему делает то же самое. –

-1

У меня есть причина, почему.Свойство моего проекта использовало набор символов Unicode. Когда я переключаюсь на многобайтовый набор символов, он работает нормально.

+0

Это явно не шина. Код в вопросе не был бы скомпилирован. Это то, что происходит, когда вы потеряли поддельный код. Позор тебе. Переключение на мультибайт - неправильный путь. Это 2016. Используйте Unicode уже! –

+0

Мой код в вопросе компилируется. Я рассмотрел некоторые другие вопросы здесь о stackoverflow, который сказал, что набор символов Unicode плохо поддерживается в консоли Win32 и не может отображаться правильно, поэтому лучше избегать. Итак, есть ли у вас предложение сделать это в наборе символов Unicode? –

+0

Если этот код компилируется, Unicode не определен. Unicode поддерживается консолью Windows. –

Смежные вопросы