我正在尝试使用命名管道将c#项目与c ++项目连接,但c ++项目无法连接。
ps:.exe都在同一个文件中
方面问题:我不明白在管道名称之前使用“\\。\ pipe \”。它做了什么,它确实是必要的?
这是我的代码,也许你可以发现错误
C#server:
Program.cs的
static class Program
{
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
pipeHandler pipe = new pipeHandler();
var proc = new Process();
proc.StartInfo.FileName = "cplpltestpipes.exe";
proc.Start();
pipe.establishConnection();
Application.Run(new Form1(pipe));
}
}
public class pipeHandler
{
private StreamReader re;
private StreamWriter wr;
private NamedPipeServerStream pipeServer;
public void establishConnection()
{
pipeServer = new NamedPipeServerStream("myNamedPipe1");
pipeServer.WaitForConnection();
re = new StreamReader(pipeServer);
wr = new StreamWriter(pipeServer);
}
public void writePipe(string text)
{
wr.Write(text);
}
public string readPipe()
{
if(re.Peek()==-1)
System.Threading.Thread.Sleep(2000);
if (re.Peek() > -1)
{
string s;
s = re.ReadToEnd();
return s;
}
else
return "fail";
}
}
Form1.cs中:
public partial class Form1 : Form
{
pipeHandler pipePointer;
public Form1(pipeHandler pipe)
{
pipePointer=pipe;
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
pipePointer.writePipe(textBox1.Text);
textBox2.Text = pipePointer.readPipe();
}
}
c ++客户端
#define chrSize 16
int main()
{
TCHAR chr[chrSize];
DWORD bytesRead;
HANDLE pipeHandler;
LPTSTR pipeName = TEXT("\\\\.\\pipe\\myNamedPipe1");
pipeHandler = CreateFile(
pipeName, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
bool flag=false;
while (!flag)
{
flag = ConnectNamedPipe(pipeHandler, NULL);
cout << "trying";
}
ReadFile(
pipeHandler, // pipe handle
chr, // buffer to receive reply
chrSize * sizeof(TCHAR), // size of buffer
&bytesRead, // number of bytes read
NULL); // not overlapped
cout << chr;
LPTSTR pipeMessage = TEXT("message receive");
DWORD bytesToWrite= (lstrlen(pipeMessage) + 1) * sizeof(TCHAR);
DWORD cbWritten;
WriteFile(
pipeHandler, // pipe handle
pipeMessage, // message
bytesToWrite, // message length
&cbWritten, // bytes written
NULL); // not overlapped
CloseHandle(pipeHandler);
}
运行程序只是在C#中提供了这个例外
**************例外文字************** System.InvalidOperationException:管道尚未连接。 .... .... ....
并且在c ++中只是在控制台中继续打印“尝试”
答案 0 :(得分:1)
当您调用CreateFile
时,CreateFile如何知道字符串myNamedPipe1
表示的对象是管道?它知道,因为名称前缀为\\ServerName\pipe\
。
在您的情况下,ServerName
只能是.
,因为这是“此计算机”的快捷方式,如果您将代码切换为LPTSTR pipeName = TEXT("\\\\.\\pipe\\myNamedPipe1");
,如果没有其他代码,它应该开始工作的问题。
您不需要将其放在C#代码中,因为NamedPipeServerStream
类puts it there for you。
编辑:查看代码,您可能希望将pipeServer = new NamedPipeServerStream("myNamedPipe1");
移动到pipeHandler
的构造函数,此时您的C ++程序可能会在服务器运行之前启动开始了,即使你有正确的名字,你仍然可能会收到错误。
EDIT2: ConnectNamedPipe
是pipeServer.WaitForConnection();
的C ++等价物,如果C ++程序是客户端,则不应该这样做。一旦你有CreateFile
EDIT3:以下是在启动C ++应用程序之前如何重写C#app以启动服务器的示例
static class Program
{
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//The server now gets created here.
pipeHandler pipe = new pipeHandler();
var proc = new Process();
proc.StartInfo.FileName = "cplpltestpipes.exe";
proc.Start();
//The server used to be created here.
pipe.EstablishConnection();
Application.Run(new Form1(pipe));
}
}
public class pipeHandler
{
private StreamReader re;
private StreamWriter wr;
private NamedPipeServerStream pipeServer;
public pipeHandler()
{
//We now create the server in the constructor.
pipeServer = new NamedPipeServerStream("myNamedPipe1");
}
public void establishConnection()
{
pipeServer.WaitForConnection();
re = new StreamReader(pipeServer);
wr = new StreamWriter(pipeServer);
}
...
}
然后在你的C ++代码中删除
while (!flag)
{
flag = ConnectNamedPipe(pipeHandler, NULL);
cout << "trying";
}