Стоит следующая задача. Надо скормить блокноту файл из пайпа. Т.е. чтобы блокнот, имеющий последовательность вызовов CreateFile + ReadFile прочитал данные из подсунутого пайпа вместо обычного файла. Запуск блокнота осуществляется так: notepad.exe //./pipe/mynamepipe2 Ниже приведен код, который функционирует следующим образом. При запуске создается пайм и в Месте Б программа ждет подключения к пайпу. Запускаем нотепад с указанием имени файла - наш пайп. Нотепад открыл пайп, увидел его, все оки. Программа пошла дальнейшее выполнение и в месте В я делаю WriteFile в пайп строку "77777777" и жду ее в нотепаде. Ее там естественно нет, так как нотепад уже сделал ReadFile до вызова мною WriteFile. Отсюда вывод что запись в пайп должна быть до соединения его клиентом. То есть в месте А. Причем при создании пайпа было указано что буфер на чтение 512 байт и на запись тоже 512 байт. Но как только я не ипался с WriteFile в месте А - вылетали всяческие ошибки вида ERROR_PIPE_CONNECTED и так далее, не позволяя мне писать в неоткрытый клиентом пайп. Все. Требуется помощь гуру по решению указанной задачи. Текст исходной программы для экспериментов: Код (C): #include <windows.h> #include <cstdio> int main() { char buf100 = "notepad.exe "; LPTSTR pipe = TEXT("\\\\.\\pipe\\mynamedpipe2"); HANDLE hPipe = CreateNamedPipe(pipe, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1 /*PIPE_UNLIMITED_INSTANCES*/, 512, 512, 0, NULL); if (hPipe == INVALID_HANDLE_VALUE) { printf(TEXT("CreateNamedPipe failed, GLE=%d.\n"), GetLastError()); return -1; } //Место А //Место Б // Ожидаем соединения со стороны клиента bool fConnected = ConnectNamedPipe(hPipe, NULL); // При возникновении ошибки выводим ее код if(!fConnected) { switch(GetLastError()) { case ERROR_NO_DATA: fprintf(stdout,"ConnectNamedPipe: ERROR_NO_DATA"); CloseHandle(hPipe); return 0; break; case ERROR_PIPE_CONNECTED: printf("ConnectNamedPipe: ERROR_PIPE_CONNECTED"); CloseHandle(hPipe); return 0; break; case ERROR_PIPE_LISTENING: printf("ConnectNamedPipe: ERROR_PIPE_LISTENING"); CloseHandle(hPipe); return 0; break; case ERROR_CALL_NOT_IMPLEMENTED: printf("ConnectNamedPipe: ERROR_CALL_NOT_IMPLEMENTED"); CloseHandle(hPipe); return 0; break; default: printf("ConnectNamedPipe: Error %ld\n",GetLastError()); CloseHandle(hPipe); return 0; break; } CloseHandle(hPipe); return 0; } char bufw[20] = "777777777777"; DWORD dw; //Место В if (!WriteFile( hPipe, bufw, 10, &dw, 0)) { printf( "WriteFile failed (%d).\n", GetLastError() ); return -3; } /*if (!CreateProcess( NULL, // No module name (use command line) buf, // Command line NULL, // Process handle not inheritable NULL, // Thread handle not inheritable FALSE, // Set handle inheritance to FALSE 0, // No creation flags NULL, // Use parent's environment block NULL, // Use parent's starting directory 0, // Pointer to STARTUPINFO structure 0 )) // Pointer to PROCESS_INFORMATION structure { printf( "CreateProcess failed (%d).\n", GetLastError() ); return -2; }*/ CloseHandle(hPipe); return 0; }
ltshck, То, что notepad.exe не дочитывает исходный файл регулярно, не смущает? Он при старте вычитает пайп, засандалит его в EDIT и будет думать что больше там ничего нет. Остальное — WM_CHAR и проч.
baldr, не смущает. потому как задача другая. не требуется чтобы в нотепаде появлялись буквы по мере их появления в пайпе. естественно в нотепаде нет цикла чтения данных с пайпа. там один раз читается само собой. требуется чтобы при первом открытии пайпа нотепадом появилась строка "77777777", которая была в пайпе до открытия еще, в буфере, который 512 байт... т.е: 1. создаем пайп 2. пишем ему в буфер строку "777777" 3. октрываем пайп нотепадом 4. хочется увидеть в нотепаде строку "77777" которую он прочитал один раз после открытия пайпа, а ее нет. как такое сделать? сабж открыт. baldr просьба не беспокоиться, нужна дельная помощь.
То, что notepad не кушает пайпы, это известная фича. Дело в том, что он использует CreateFileMapping, а не ReadFile.
Попытка номер 2. Извиняюсь за паскаль Код (Text): uses Windows; type TBuf=array[0..1023] of AnsiChar; var map,pipe,pipefile: THandle; PBuf: ^tbuf; i: Cardinal; overlapped: _OVERLAPPED; startupinfo: _STARTUPINFOA=(cb: sizeof(_STARTUPINFOA)); ProcInfo: _PROCESS_INFORMATION; begin map :=CreateFileMapping(INVALID_HANDLE_VALUE,0,PAGE_READWRITE,0,sizeof(TBuf),'Global\buf.txt'); PBuf:=MapViewOfFile(map,FILE_MAP_ALL_ACCESS,0,0,sizeof(TBuf)); PBuf^:='qwerty'; CreateProcessA(0,'notepad \\.\Global\buf.txt',0,0,false,0,0,0,startupinfo,ProcInfo); pipe:=CreateNamedPipeW('\\.\pipe\buf.txt',PIPE_ACCESS_DUPLEX+FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE+PIPE_NOWAIT,PIPE_UNLIMITED_INSTANCES,sizeof(TBuf),sizeof(TBuf),0,0); pipefile:=CreateFileW('\\.\pipe\buf.txt',GENERIC_READ+GENERIC_WRITE,FILE_SHARE_READ+FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0); WriteFile(pipefile,PBuf^,sizeof(TBuf),i,@overlapped); CreateProcessA(0,'notepad \\.\pipe\buf.txt',0,0,false,0,0,0,startupinfo,ProcInfo); MessageBoxW(0,0,0,0); end. Вначале подсовываю именованную область памяти и получаю это (если нажать да ничего не происходит) Далее подсовываю асинхронный именованный канал и вот То есть нотепад всё-таки понимает, что это пайп. Кто что думает?
Блокнот после открытия файла в обязательном порядке кастует на него CreateFileMappingW и MapViewOfFile, что-то мне подсказывает, что это не очень сочетается с пайпами. (windows 8.1 x64) ЗЫ: гораздо проще ворд или IE накормить через ole-автоматизацию.
Технически не вижу препятствий. При создании пайпа мы ведь указываем размер входного и выходного буферов. Теоретически система может смапить буфер. Или не?
Для открытия файла (8.1 x64) блокнот создает COM-объект DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7 (IFileOpenDialog) и где-то в методе Show (+0x18) этот объект обламывает все пытаясь найти через RPC сетевой путь "\\.\pipe\buf.txt", до CreateFileW даже не доходит. Больше с этим делать нечего, тупик, по крайней мере для более-менее актуальных версий Windows (если конечно кое-кто не хочет реализовать альтернативный IFileOpenDialog подменив им оригинал). ЗЫ: точку в имени файла я не забыл, он сам ее убрал. --- Сообщение объединено, 5 мар 2019 --- Вобщем я идиот и ничего не понял. Код (Text): notepad \\.\pipe\buf.txt Код (ASM): format pe console 4.0 include 'win32ax.inc' entry main section '.code' code data readable executable proc main locals hPipe dd ? nCount dd ? endl .next: invoke CreateNamedPipe,pipename,PIPE_ACCESS_OUTBOUND,PIPE_TYPE_BYTE + PIPE_READMODE_BYTE ,PIPE_UNLIMITED_INSTANCES,1024,1024,0,0 .if eax <> INVALID_HANDLE_VALUE mov [hPipe],eax @@: invoke WriteFile,[hPipe],pipename,sizeof.pipename,addr nCount,0 test eax,eax .if ZERO? jmp @B .endif invoke CloseHandle,[hPipe] jmp .next .endif ret endp pipename db '\\.\pipe\buf.txt',0 sizeof.pipename = $ - pipename section '.data' data readable writable data import library kernel32,'kernel32.dll',user32,'user32.dll' include 'api\kernel32.inc' include 'api\user32.inc' end data Удается создать пайп, дождаться когда блокнот его откроет (иначе WriteFile вернет ERROR_PIPE_LISTENING, возможно есть способ лучше, пофиг), но как я и предупреждал: Код (Text): 00007FF62E1A1E4F | 45 33 C9 | xor r9d,r9d | 00007FF62E1A1E52 | 33 D2 | xor edx,edx | 00007FF62E1A1E54 | 45 8D 41 02 | lea r8d,[r9+0x2] | 00007FF62E1A1E58 | 48 8B 0D 69 82 01 00 | mov rcx,[0x7FF62E1BA0C8] | 00007FF62E1A1E5F | FF 15 3B C2 01 00 | call [<&CreateFileMappingW>] | 00007FF62E1A1E65 | 48 8B C8 | mov rcx,rax | 00007FF62E1A1E68 | 48 89 44 24 58 | mov [rsp+0x58],rax | 00007FF62E1A1E6D | 48 85 C0 | test rax,rax | 00007FF62E1A1E70 | 74 2B | je notepad.7FF62E1A1E9D | 00007FF62E1A1E72 | 4C 89 64 24 20 | mov [rsp+0x20],r12 | 00007FF62E1A1E77 | 45 33 C9 | xor r9d,r9d | 00007FF62E1A1E7A | 45 33 C0 | xor r8d,r8d | 00007FF62E1A1E7D | 41 8D 51 04 | lea edx,[r9+0x4] | 00007FF62E1A1E81 | FF 15 11 C2 01 00 | call [<&MapViewOfFile>] | 00007FF62E1A1E87 | 48 8B F0 | mov rsi,rax | 00007FF62E1A1E8A | 48 89 44 24 78 | mov [rsp+0x78],rax | 00007FF62E1A1E8F | 48 8B 4C 24 58 | mov rcx,[rsp+0x58] | 00007FF62E1A1E94 | FF 15 26 C3 01 00 | call [<&CloseHandle>] | 00007FF62E1A1E9A | EB 01 | jmp notepad.7FF62E1A1E9D | CreateFileMappingW возвращает 0.
Надо попробовать так: "\\?\\\.\pipe\buf.txt". Всё, что после префикса "\\?\" должно остаться без изменений.
"Недопустимое имя файла". Ну через открытие файла скорей всего точно не выйдет, через аргумент вон получилось хотя бы CreateFileW чтоб прошло (с твоим примером INVALID_HANDLE_VALUE на выходе).