ric*_*k_1 1 c process createprocess named-pipes visual-studio
我有以下c代码,我从这个问题的第一个答案中获取,我在VS2008中使用C89进行编译,所以我对代码进行了一些更改以正常工作,它编译得很好,但它不能成功创建namedpipe后创建进程(CreateProcessA
不工作)始终返回错误2并在panic
函数中打印消息.
我试图在CreateProcessA中运行的程序可以在这里下载,我通常运行它并按如下方式使用它:
> C:\qhichwa>cmd.exe /c "C:\qhichwa\flookup.exe -bx C:\qhichwa\qhichwa.fst"
wasi <user writes wasi>
wasi <program responds printing wasi>
hola <user writes hola>
+ ? <program responds printing + ?>
<pres ctrl + c to terminate program>
> C:\qhichwa>
Run Code Online (Sandbox Code Playgroud)
两者之间的界限< comments >
只是评论.
为了成功创建命名管道需要哪些更正?
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
// name of our glorious pipe
#define PIPE_NAME L"\\\\.\\pipe\\whatever" // bloody unicode string
// exit on fatal error
void panic(const char * msg)
{
int err = GetLastError();
fprintf(stderr, "***PANIC*** %s\n", msg);
printf("In the child thread: Last Error is %lu\n", err);
exit(-1);
}
// father process
void father(const char * own_name) // name of our own executable to launch a copy of ourselve
{
printf("Father process starting\n");
// create a monodirectional father->child named pipe
HANDLE pipe = CreateNamedPipe(
PIPE_NAME, // name of the pipe
PIPE_ACCESS_OUTBOUND, // send only
PIPE_TYPE_BYTE, // send data as a byte stream
1, // only one instance
0, 0, 0, NULL); // default junk
if (pipe == INVALID_HANDLE_VALUE) panic("could not create pipe 1");
// spawn child process
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcessA( // using ASCII variant to be compatible with argv
"cmd.exe", // executable name (ourself)
"/c \"C:\\qhichwa\\flookup.exe -bx C:\\qhichwa\\qhichwa.fst\"", // command line. This will be seen as argv[0]
NULL, NULL, FALSE, // default junk
CREATE_NEW_CONSOLE, // launch in another console window
NULL, NULL, // more junk
&si, &pi)) // final useless junk
panic("could not create child process 2");
}
// connect to child process
BOOL result = ConnectNamedPipe(pipe, NULL);
if (!result) panic("could not connect to child process");
// talk to child
for (;;)
{
// read an input line
char line[100];
printf("Say something >");
if (fgets(line, sizeof(line), stdin) == NULL)
panic("could not read from standard input");
// exit on an empty line
if (!strcmp(line, "\n")) break;
// send the line to the child
DWORD written = 0;
if (!WriteFile(
pipe,
line, // sent data
strlen(line), // data length
&written, // bytes actually written
NULL))
panic("could not write to pipe");
}
// close the pipe
CloseHandle(pipe);
}
void child(void)
{
printf("Child process starting\n");
// retrieve communication pipe
HANDLE pipe = CreateFile(
PIPE_NAME, // name of the pipe
GENERIC_READ, // read ONLY access (or else the call will fail)
0, NULL, // junk
OPEN_EXISTING, // opens existing pipe
0, NULL); // more junk
if (pipe == INVALID_HANDLE_VALUE) panic("could not connect to the pipe");
// read father's input
for (;;)
{
char buffer[80];
DWORD read = 0;
if (!ReadFile(
pipe,
buffer, // read data
sizeof(buffer)-1, // max length (leave room for terminator)
&read, // bytes actually read
NULL))
break; // exit if the pipe has closed
// display what our father said
buffer[read] = '\0'; // make sure what we just read will be displayable as a string
printf("Father said: %s", buffer);
}
// close pipe
CloseHandle(pipe);
}
int main(int argc, char *argv[])
{
// wait for a <return> keypress on exit
atexit(getchar);
father(argv[0]);
// decide whether we are the father or the child
//if (!strcmp(argv[0], "child")) child();
//else father(argv[0]);
printf("Done\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
问题出在这里:
fprintf(stderr, "***PANIC*** %s\n", msg);
printf("In the child thread: Last Error is %lu\n", GetLastError());
Run Code Online (Sandbox Code Playgroud)
这是一个标准的Windows编程错误,每个程序员都犯了一次这个错误.只有一次,这是如此难以诊断,你永远不会忘记失去你的生命周试图发现它.
潜在的问题是GetLastError()的工作方式.它返回一个内部全局变量的值,它存储在TEB(线程环境块)中.它对全局变量有如此常见的问题,你对winapi函数的每次调用都有可能改变它,包括那些实际上没有失败的函数.Windows本身也使用该变量.ERROR_INVALID_NAME是一个非常受欢迎的内部错误代码.
你无法看到这些winapi通话,这更加复杂.破坏错误代码的是fprintf().它在带有winapi调用的CRT中实现.必然如此,I/O是一个操作系统职责.
所以绝对必要的是你在做其他事情之前立即获得错误代码.虽然你最好将值传递给你的panic()函数,因为它无法预测其他代码在它之前运行,快速解决方法是重写它如下:
int err = GetLastError();
fprintf(stderr, "***PANIC*** %s\n", msg);
printf("In the child thread: Last Error is %lu\n", err);
Run Code Online (Sandbox Code Playgroud)
您现在将获得真正的错误代码,即CreateNamedPipe()生成的错误代码.应该给你一个更好的诊断问题的机会.如果您在解释问题时仍然有问题,请更新您的问题.
归档时间: |
|
查看次数: |
1139 次 |
最近记录: |