Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.79/43: Рейтинг темы: голосов - 43, средняя оценка - 4.79
19 / 19 / 7
Регистрация: 17.05.2013
Сообщений: 72

Передача считанного файла через pipe

11.10.2013, 17:30. Показов 8327. Ответов 32
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
прошу помощи разобраться с чтением файла и передачей прочитанных данных через анонимный pipe

сам смысл задачи:программа запускается из консоли с двумя аргументами - стандартная команда из cmd и имя файла, в которой хранятся входные данные для самой команды..
пока застрял на осознании как работать с каналами в winapi.. в unix, ИМХО, проще как то..

есть набросок кода, но я не удивлюсь, если я там и близко не подошел к поставленной задаче.. собственно как исправить это чудовище, чтобы появилась возможность считанные данные запихать в новый процесс?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include <Windows.h>
#include <conio.h>
#include <tchar.h>
#include <wchar.h>
#include <locale>
#define BUF_SIZE 256
 
 
int _tmain(int argc, TCHAR* argv[])
{
     PROCESS_INFORMATION pi;
     CHAR buffer[BUF_SIZE];
     setlocale(LC_ALL, "");
     HANDLE handleFile;
 
     //открытие файла
     handleFile=CreateFile(argv[2],GENERIC_READ,0,0,OPEN_EXISTING,0,0);
     if(handleFile==INVALID_HANDLE_VALUE)
     {
         printf("Невозможно открыть файл. Ошибка: %x\n",GetLastError());
         return 1;
     }
     
 
     //создание анонимного канала
     SECURITY_ATTRIBUTES pipeSA ={sizeof(SECURITY_ATTRIBUTES),NULL,TRUE};
     HANDLE hReadPipe, hWritePipe;
     if (!CreatePipe(&hReadPipe,&hWritePipe,&pipeSA,0))
     {
         printf("Невозможно создать канал. Ошибка: %x\n",GetLastError());
         return 1;
     }
 
     DWORD nIn;
//   while(ReadFile(handleFile,hWritePipe,BUF_SIZE,&nIn,0))
    //   continue;
 
 
     //создание дочернего процесса 
     TCHAR * command = L"sort";
     STARTUPINFO si;
     CloseHandle(handleFile);
     //si.hStdInput=hReadPipe;
     if(!CreateProcess(NULL, command,
                NULL,NULL,TRUE,
                CREATE_NEW_CONSOLE,
                NULL,NULL,&si,&pi))
     {
         printf("Невозможно создать процесс. Ошибка:%x\n",GetLastError());
         return 2;
     }
 
     
     system("pause");
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.10.2013, 17:30
Ответы с готовыми решениями:

Передача сообщений через pipe
Прошу помочь с реализацией курсового проекта. Я очень плохо шарю в c++, поэтому ничего не могу понять( Нужно через pipe реализовать...

Передача системного времени через pipe
Всем привет, пишу программу, дочерний процесс должен передать системное время родительскому процессу через pipe, но в чем-то ошибка. Буду...

Передача данных дочернему процессу посредством pipe(): иммитация нажатия enter через терминал
Всем привет. Столкнулся с такой проблемой: есть программа, считывающая логин и пароль (последовательно, сначала логин, после ввода запрос...

32
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
16.10.2013, 13:38
Студворк — интернет-сервис помощи студентам
используй тс named pipe, геморрой бы уже давно был забыт (это я по поводу "начать с простого" и "что тут делать? передал хэндл и дело в шляпе")
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
16.10.2013, 13:43
novi4ok, ну и чем именованные пайпы здесь помогут ?
О каком таком "геморрое" Вы вообще говорите ?
Передача хэндла в дочерний процесс - это тривиальнейшая операция, да и весь
код с редиректом вывода, например, можно уложить строк так в 50 от силы.
У топикстартера проблема не с этим, а с тем, что он не может пока четко
сформулировать то, что именно он хочет сделать с этими пайпами.
0
19 / 19 / 7
Регистрация: 17.05.2013
Сообщений: 72
16.10.2013, 13:50  [ТС]
Цитата Сообщение от novi4ok Посмотреть сообщение
используй тс named pipe, геморрой бы уже давно был забыт (это я по поводу "начать с простого" и "что тут делать? передал хэндл и дело в шляпе")
хорошо.. может эта причина будет более веской.. по условию в дочернем процессе запускается стандартная команда интепретатора команд.. а для подключения к именованному каналу,насколько я знаю и правильно прочитал несколько печатных источник, надо явным образом подключаться к этому самому пайпу в коде вызываемого процесса.. и что делать тогда с именованным пайпом? заменять все стандартные команды командной строки на версии, которые будут подключаться к моему каналу?) это выглядит бредовой затеей..

Добавлено через 25 секунд
если я не прав, поправьте меня

Добавлено через 5 минут
Убежденный, просто поставлено условие так, что я должен видимо связать концы трубы со стандартными потоками ввода/вывода.. за счет это как раз исчезнет необходимость в использовании writefile.. что препод подсказывал, что нужно тут как то использовать _dup2, для линковки хэндлов, что в коде на unix ( там тоже все дело решается юниксовым dup2).. только там с этим делом легче.. открыл файл функцией open, он вернулся дескриптор в виде int.. и юзай спокойно dup2.. а под win это усложняется тем, что для создания трубы нужен именно HANDLE тип, который не воспринимает dup2.. соответственно, я так думаю, просто надо как то преобразовать в int
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
16.10.2013, 14:06
Цитата Сообщение от EndWar Посмотреть сообщение
по условию в дочернем процессе запускается стандартная команда интепретатора команд.
Что такое "стандартная команда интерпретатора команд" ?
0
19 / 19 / 7
Регистрация: 17.05.2013
Сообщений: 72
16.10.2013, 14:07  [ТС]
кстати, есть предположение, что краш программы происходит из-за такого приведения типа (int)pHandle..
но ведь HANDLE это указатель на воид? я правильно понимаю? то есть чтобы привести к int, надо сначала разыменовать, а потом приводить к int.. но VS отказывается наотрез это делать.. как быть?
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
16.10.2013, 14:08
Цитата Сообщение от EndWar Посмотреть сообщение
Убежденный, просто поставлено условие так, что я должен видимо связать концы трубы со стандартными потоками ввода/вывода.. за счет это как раз исчезнет необходимость в использовании writefile.
Так ведь в примере с MSDN именно так и делается - хэндлы пайпа пишутся в STARTUPINFO,
"представляясь" для дочернего процесса хэндлами стандартных потоков. И дочерний процесс
может писать и читать стандартный ввод и вывод через std::cout и std::cin, но при этом
чтение и запись будут идти в пайп.

Цитата Сообщение от EndWar Посмотреть сообщение
кстати, есть предположение, что краш программы происходит из-за такого приведения типа (int)pHandle..
HANDLE нельзя приводить к int.
На x64 размер HANDLE равен 8 байтам, а int - 4. Усечение.
0
19 / 19 / 7
Регистрация: 17.05.2013
Сообщений: 72
16.10.2013, 14:18  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Что такое "стандартная команда интерпретатора команд" ?
всякие там sort, dir, cd и тд.. не знаю как еще их назвать кроме как стандартные команды интерпретатора команд)
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
16.10.2013, 14:52
Ок, вот код, который запускает дочерним процессом командный интерпретатор и
вызывает в нем команду dir (вывод сведений о текущей папке). Вывод перенаправляется в
консоль родительского процесса. Обработка ошибок и очистка ресурсов для наглядности
опущены:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// PipeRedirect.cpp
 
#include <iostream>
#include <string>
#include <Windows.h>
 
int main()
{
    // Создаем пайп.
 
    HANDLE hRead;
    HANDLE hWrite;
 
    CreatePipe(&hRead, &hWrite, NULL, 0);
 
    // Устанавливаем параметры наследования для хэндла на запись.
    // То же самое можно сделать, используя структуру SECURITY_ATTRIBUTES,
    // либо функцию DuplicateHandle(Ex).
 
    SetHandleInformation(hWrite, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
 
    // Создаем дочерний процесс и прокидываем в него хэндл пайпа на запись,
    // под видом стандартного потока вывода (stdout).
 
    STARTUPINFOW si;
    GetStartupInfoW(&si);
    si.dwFlags |= STARTF_USESTDHANDLES;
    si.hStdOutput = hWrite;
 
    wchar_t pCmdLine[] = {L"cmd.exe /c dir"};
 
    PROCESS_INFORMATION pi;
 
    CreateProcessW(NULL,
        pCmdLine,
        NULL,
        NULL,
        TRUE, // Наследовать хэндлы.
        NORMAL_PRIORITY_CLASS,
        NULL,
        NULL,
        &si,
        &pi);
 
    // Ждем, пока процесс завершится.
 
    WaitForSingleObject(pi.hProcess, INFINITE);
 
    // Читаем информацию из пайпа.
    // Хэндл записи предварительно следует закрыть, иначе функция
    // чтения может зависнуть в бесконечном цикле.
 
    CloseHandle(hWrite);
 
    std::string Output;
 
    DWORD const BuffSize = 100;
    char pBuffer[BuffSize];
    DWORD nBytes;
 
    // Длина принимаемых данных неизвестна, поэтому будем накапливать
    // их в std::string, пока функция чтения не завершится с ошибкой,
    // либо пока не будет достигнут конец.
 
    for (;;)
    {
        if (FALSE == ReadFile(hRead, pBuffer, BuffSize, &nBytes, NULL))
        {
            break;
        }
 
        if (0 == nBytes) // EOF
        {
            break;
        }
 
        Output.append(pBuffer, nBytes);
    }
 
    std::cout << Output << std::endl;
 
    return 0;
}


Вывод:
Code
1
2
3
4
5
6
7
8
9
10
11
12
 Том в устройстве C не имеет метки.
 Серийный номер тома: 1C30-51D9
 
 Содержимое папки C:\Users\Олег\Documents\Visual Studio 2012\Projects\PipeRedirect\x64\Debug
 
16.10.2013  13:46    <DIR>          .
16.10.2013  13:46    <DIR>          ..
16.10.2013  13:46            74*240 PipeRedirect.exe
16.10.2013  13:46           429*640 PipeRedirect.ilk
16.10.2013  13:46           773*120 PipeRedirect.pdb
               3 файлов      1*277*000 байт
               2 папок  101*913*300*992 байт свободно


Если нужно вводить какие-то команды или данные, придется сделать второй пайп (stdin) и
из посылать их из родительского процесса. По мотивам все того же примера из MSDN.
1
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
16.10.2013, 19:10
Цитата Сообщение от Убежденный Посмотреть сообщение
novi4ok, ну и чем именованные пайпы здесь помогут ?
О каком таком "геморрое" Вы вообще говорите ?
Передача хэндла в дочерний процесс - это тривиальнейшая операция, да и весь
код с редиректом вывода, например, можно уложить строк так в 50 от силы.
У топикстартера проблема не с этим, а с тем, что он не может пока четко
сформулировать то, что именно он хочет сделать с этими пайпами.
я думаю, он хочет в одном процессе открыть файл и передать в другой, чтобы тот принял и сохранил.
вариант с named pipe для него проще, т.к. задача с пайпом остается, но отпадает задача передавать хэндл.
0
19 / 19 / 7
Регистрация: 17.05.2013
Сообщений: 72
18.10.2013, 16:30  [ТС]
Убежденный, то, что нужно) спасибо) я не догадался, что можно и в стринг из трубы данные запихать и вывести через cout.. надеялся все же что можно как нибудь системными вызовами избавиться от writefile)
а можно дочернему процессу сказать что его hStdInput - это файл какой нибудь? я пробовал, но ничего хорошего из этого не вышло) такое ощущение, что процесс просто не хочет воспринимать входные данные с файла
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
18.10.2013, 17:20
Цитата Сообщение от EndWar Посмотреть сообщение
а можно дочернему процессу сказать что его hStdInput - это файл какой нибудь?
Должно работать. В Windows ввод-вывод унифицирован: туда, где ожидается хэндл, в
большинстве случаев можно передавать объекты разных типов. Главное - сохранить семантику.
Если, например, пайп заменяется файлом, то файл должен вести себя, как пайп.
1
19 / 19 / 7
Регистрация: 17.05.2013
Сообщений: 72
18.10.2013, 19:27  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Должно работать.
мм, получилось)
правда такой вариант не сработал
C++
1
2
3
4
5
6
TCHAR * path=L"text.txt";
    HANDLE handleFile;
     
     handleFile=CreateFile(path,GENERIC_READ,0,NULL,
                            OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); 
     SetHandleInformation(handleFile,HANDLE_FLAG_INHERIT,0);
хотел уже спросить что не так, но вспомнил, что на msdn'e где то видел вариант где у SetHandleInformation оба последних флага имели значения HANDLE_FLAG_INHERIT. заменил - заработал)
C++
1
SetHandleInformation(handleFile,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT);
хотя в то же время, я где то читал, что оба флага отвечает примерно за одно и то же.. но в чем собственно разница?
P.S. вопрос снят, Побегайло ответил на него) спасибо за активную помощь)
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
18.10.2013, 19:34
Цитата Сообщение от EndWar Посмотреть сообщение
хотел уже спросить что не так, но вспомнил, что на msdn'e где то видел вариант где у SetHandleInformation оба последних флага имели значения HANDLE_FLAG_INHERIT. заменил - заработал)
Цитата Сообщение от EndWar Посмотреть сообщение
хотя в то же время, я где то читал, что оба флага отвечает примерно за одно и то же.. но в чем собственно разница?
Цитата Сообщение от EndWar Посмотреть сообщение
P.S. вопрос снят, Побегайло ответил на него)
В документацию нужно заглядывать почаще (MSDN).
Там есть ответы если не на все, то на большую часть вопросов.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
18.10.2013, 19:34
Помогаю со студенческими работами здесь

Интегрирование полинома, считанного из файла
Из файла считывается степень полинома и его коэффициенты. Например, ============== 5 1 2 3 4 5 6 ============== ~ 1 + 2*x + 3*x^2...

Заполнить массив цифрами числа, считанного через cin
Здрасти, как ввести в массив int mMass число 12345 с помощью cin&gt;&gt;? Нужно чтобы в mMass записалась 1, в mMass записалась 2 .... и...

Обработка массива, считанного из файла; найти ошибку
Есть задание: программа считывает из файла массив целых чисел. Найти максимум (max) и минимум (min) среди них, после чего найти среднее...

Передача данных между процессами (pipe)
Всем доброго времени суток. Обращаюсь к вам с вопросиком. Передо мной стоит задача написать код, который: 1. Создавай процесс 2....

Передача данных между консолью с использованием Pipe
Добрый день! Не получается организовать передачу данных между двумя консольными приложениями при использовании буфера с типом wchar_t....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
33
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru