我用管道在两个进程之间通信,但客户端总发生异常说拒绝访问指定管道.这是不是因为NT的安全机制引起的?
服务器端.
procedure TForm1.Button1Click(Sender: TObject);
const
  pipename:string='\\.\pipe\zwpipe';
var
  SPipeHandle:THandle;
  Se:TSecurityAttributes;
  WriteBuffer:DWORD;
  Buffer:pchar;
begin
  Se.nLength:=Sizeof(TSecurityAttributes);
  Se.lpSecurityDescriptor:=nil;
  Se.bInheritHandle:=True;
  SPipeHandle:=CreateNamedPipe(pchar(pipename),PIPE_ACCESS_OUTBOUND OR FILE_FLAG_WRITE_THROUGH,
                               PIPE_TYPE_BYTE or PIPE_WAIT,2,512,0,1000,@Se);
  if SPipeHandle=-1 then
    raise Exception.Create('Create pipe Failed');
  try
    if not ConnectNamedPipe(SPipeHandle,nil) then begin
      CloseHandle(SPipeHandle);
      Raise Exception.Create(IntToStr(GetLastError)+'fail con');end;
    Buffer:=StrAlloc(512);
    Buffer:=Pchar(Memo1.Text);
    WriteFile(SPipeHandle,Buffer,512,WriteBuffer,nil);
  finally
    DisConnectNamedPipe(SPipeHandle);
    CloseHandle(SPipeHandle);
  end;
end;客户端.
 procedure TForm1.Button1Click(Sender: TObject);
const
  PipeName:string='\\ZHOUWEI\pipe\zwpipe';
var
  Buffer:pchar;
  ReadSize:DWORD;
begin
  if not WaitNamedPipe(pchar(PipeName),NMPWAIT_WAIT_FOREVER) then
    raise Exception.Create('failed wait');
    Buffer:=StrAlloc(512);
    if not CallnamedPipe(Pchar(PipeName),nil,0,Buffer,512,ReadSize,NMPWAIT_NOWAIT) then
      Raise Exception.Create(IntToStr(GetLastError)+'faid call');
    Memo1.Text:=StrPas(Buffer);
end;

解决方案 »

  1.   

    就是在调用callnamedpipe()时触发拒绝访问的异常.
    高手们,没有人知道原因吗?
      

  2.   

    奇怪,你能写出这样的代码,说明你已经熟悉管道操作了,怎么还会有问题呢?
    用overlapped结构。
      

  3.   

    to westfly(西翔) 
    我对管道一点都不熟悉.
    overlapped结构是什么?有什么用?
      

  4.   

    参看
    http://www.codeguru.com/network/p2p_namedpipes.shtml
      

  5.   

    两个进程之间通信使用DDE或Shared Mem技术的多,基本很少人用Pipe了
      

  6.   

    http://www.torry.net/appscommunications.htm
    现成下载使用了,
    http://www.torry.net/vcl/system/appscommunications/pipe.zip
      

  7.   

    刚看到你的贴,帮你try 测试ok
    ////server:const
      pipename:string='\\.\pipe\zwpipe';
    var
      SPipeHandle:THandle;
      Se:TSecurityAttributes;
      WriteBuffer:DWORD;
      Buffer:pchar;
    begin
      Se.nLength:=Sizeof(TSecurityAttributes);
      Se.lpSecurityDescriptor:=nil;
      Se.bInheritHandle:=True;
      SPipeHandle:=CreateNamedPipe(pchar(pipename),PIPE_ACCESS_DUPLEX  OR FILE_FLAG_WRITE_THROUGH,
                                   PIPE_TYPE_BYTE or PIPE_WAIT,2,512,512,1000,@Se);
      if SPipeHandle=-1 then
        raise Exception.Create('Create pipe Failed');
      try
        if not ConnectNamedPipe(SPipeHandle,nil) then begin
          CloseHandle(SPipeHandle);
          Raise Exception.Create(IntToStr(GetLastError)+'fail con');end;
        Buffer:=StrAlloc(512);
        Buffer:=Pchar(Memo1.Text);
        WriteFile(SPipeHandle,Buffer[0],512,WriteBuffer,nil);
      finally
        DisConnectNamedPipe(SPipeHandle);
        CloseHandle(SPipeHandle);
      end;
    end;////client:
    const
      PipeName:string='\\.\pipe\zwpipe';
    var
      Buffer:array[0..511] of char;
      ReadSize:DWORD;
      hh:Thandle;
    begin
      if not WaitNamedPipe(pchar(PipeName),NMPWAIT_USE_DEFAULT_WAIT) then
        raise Exception.Create('failed wait');
       hh:=CreateFile(pchar(pipename), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or
          FILE_SHARE_WRITE,NiL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE or FILE_FLAG_WRITE_THROUGH,0);
       if hh=INVALID_HANDLE_VALUE then
         showmessage('error createfile')
       else
       begin
         readsize:=0;
         fillchar(buffer,512,0);
         readfile(hh,buffer,512,readsize,nil);
         if readsize >0  then
           Memo1.Text:=Buffer;
       end;
    end;
      

  8.   

    To  zjqyb(风清扬*任它溺水三千,我只取一瓢饮*) 
    还是不行,虽然管道连上了,可又提示内存地址出错.
    Access violation at address 0040443F in module "client.exe'.Read of address 7A7A7A7A.
    我用的WIN2000+SP4+D6.
    请再帮忙看看,感激感激.
      

  9.   

    我的buffer 定义为  Buffer:array[0..511] of char;
      应该用readfile(hh,buffer,512,readsize,nil);若buffer 定义为pchar;
    getmem(buffer,512);
    就应为readfile(hh,buffer^,512,readsize,nil);我估计你就错在此
    我的程序可是全部调试执行通过
      

  10.   

    zjqyb(风清扬*任它溺水三千,我只取一瓢饮*) 
    谢谢.问题解决了.我已经结了一贴.马上就结这一贴.
    还有些问题想问问.
    为什么一定要用CHAR数组?我PCHAR也分配了空间的,为什么会出错?
    CREATENAMED()中为什么要用PIPE_ACCESS_DUPLEX 而不用PIPE_ACCESS_OUTBOUND,还有
    FILE_SHARE_READ or FILE_SHARE_WRITE,NiL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE or FILE_FLAG_WRITE_THROUGH这几个参数值代表什么意思?客户端的管道名中不是要加上计算机名吗?
    在这里先谢过了.
      

  11.   

    还有,SERVER中的WriteFile(SPipeHandle,Buffer[0],512,WriteBuffer,nil)为什么要用
    BUFFER[0]而直接用BUFFER?是不是把字串装入了BUFFER后在客户端连结上之前不能释放分配的BUFFER的内存空间?
      

  12.   

    Client中用CallnamedPipe(Pchar                                               (PipeName),nil,0,BufferR,512,BufferSize,NMPWAIT_NOWAIT) 不管怎样也连不上管道,难道一定得用CREATEFILE()吗?
      

  13.   

    若buffer 定义为pchar;
    getmem(buffer,512);
    就应为readfile(hh,buffer^,512,readsize,nil);
    或readfile(hh,buffer[0],512,readsize,nil);
    buffer^和buffer有天壤之别
    readfile定义为
    function ReadFile(hFile: THandle; var Buffer; nNumberOfBytesToRead: DWORD;
      var lpNumberOfBytesRead: DWORD; lpOverlapped: POverlapped): BOOL; stdcall;
    buffer定义为引用,而非指针
    WriteFile(SPipeHandle,Buffer[0],512,WriteBuffer,nil)也是一样
    用PIPE_ACCESS_OUTBOUND应该也可以,客户端的管道名中不须加上计算机名
    那几个参数,我也是直接从windows sdk hlp  copy过来,自己看一下,我最讨厌打字
      

  14.   

    to zjqyb(风清扬*任它溺水三千,我只取一瓢饮*) 
    1.不能用PIPE_ACCESS_OUTBOUND,只能用PIPE_ACCESS_DUPLEX,我就是这里疑惑.明明只是单向从服务器流到客户端,为什么一定得PIPE_ACCESS_DUPLEX?
    2.在CLIENT中用CALLNAMEDPIPE()不管怎样也连不上管道,难道一定得用CREATEFILE()吗?请帮忙调试一下.
    3.如果S和C不在同一台计算机上,C中的管道名要不要加上S的名称?
    最后一个很菜的问题.....Windows SDK hlp怎么查,如果是查阅MSDN,请给出详细地址,
    因为我从未在MSDN上找到这方面的资料.哈哈.
      

  15.   

    delphi中  不是有 Windows SDK hlp如果S和C不在同一台计算机上,C中的管道名肯定要加上S的名称
    CREATEFILE是M$推荐,我想CALLNAMEDPIPE()可能是过时的用法我一般不用namepipe进行通讯,上次我只是一时性起,才帮你一试