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

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

11.10.2013, 17:30. Показов 8571. Ответов 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
Ответ Создать тему
Новые блоги и статьи
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru