Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
进程间通信——C#和C++;。对路径的访问被拒绝 我有一个C客户端应用程序,它使用管道连接到C++服务器应用程序。尝试连接时出现错误:System.UnauthorizedAccessException:对路径的访问被拒绝_C#_C++_.net_Ipc_Named Pipes - Fatal编程技术网

进程间通信——C#和C++;。对路径的访问被拒绝 我有一个C客户端应用程序,它使用管道连接到C++服务器应用程序。尝试连接时出现错误:System.UnauthorizedAccessException:对路径的访问被拒绝

进程间通信——C#和C++;。对路径的访问被拒绝 我有一个C客户端应用程序,它使用管道连接到C++服务器应用程序。尝试连接时出现错误:System.UnauthorizedAccessException:对路径的访问被拒绝,c#,c++,.net,ipc,named-pipes,C#,C++,.net,Ipc,Named Pipes,在查找这个之后,我发现我可以通过创建一个PipeSecurity对象并添加一个PipeAccessRule来修复它。但这只有在服务器也是C#应用程序的情况下才有效 如果我把服务器作为C++应用程序,那么如何解决这个访问问题? 我已经搜索过了,但找不到解决方案 C#: int timeOut = 500; NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", pipeName, PipeDirec

在查找这个之后,我发现我可以通过创建一个PipeSecurity对象并添加一个PipeAccessRule来修复它。但这只有在服务器也是C#应用程序的情况下才有效

如果我把服务器作为C++应用程序,那么如何解决这个访问问题? 我已经搜索过了,但找不到解决方案

C#:

      int timeOut = 500;
      NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", pipeName, PipeDirection.Out, PipeOptions.Asynchronous);
      pipeStream.Connect(timeOut);  

      byte[] buffer = Encoding.UTF8.GetBytes(sendStr);
      pipeStream.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(AsyncSend), pipeStream);
   _hPipe = ::CreateNamedPipe(configurePipeName(getPipeName()).c_str(),
                            PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
                            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
                            1,
                            bufferSize,
                            bufferSize,
                            NMPWAIT_USE_DEFAULT_WAIT,
                            NULL);

  if (_hPipe == INVALID_HANDLE_VALUE)
  {
    logStream << "CreateNamedPipe failed for " << sys::OperatingSystem::getLastErrorMessage() << blog::over;
    return;
  }

  HANDLE ioEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  overlapped.hEvent = ioEvent;

  assert(overlapped.hEvent);
  if (ioEvent == INVALID_HANDLE_VALUE)
  {
    logStream << "CreateEvent failed for " << sys::OperatingSystem::getLastErrorMessage() << blog::over;
    return;
  }

  while (!terminating())
  {
    BOOL connected = false;
    DWORD waitMessage;
    DWORD timeOut = 700;

    if (!::ConnectNamedPipe(_hPipe, &overlapped))
    {
      switch (::GetLastError()) 
      {
        case ERROR_PIPE_CONNECTED:
          connected = true;
          break;

        case ERROR_IO_PENDING:
          waitMessage = ::WaitForSingleObject(overlapped.hEvent, timeOut);
          if (waitMessage == WAIT_OBJECT_0)
          {
            DWORD dwIgnore;
            BOOL conn = (::GetOverlappedResult(_hPipe, &overlapped, &dwIgnore, TRUE));
            if (conn)
              connected = true;
            else
              logStream << "ConnectedNamedPipe reported an error: " << sys::OperatingSystem::getLastErrorMessage() << blog::over;
          }
          else
            ::CancelIo(_hPipe);
          break;

        default:
          logStream << "ConnectedNamedPipe reported an error: " << sys::OperatingSystem::getLastErrorMessage() << blog::over;
      }
    }

    if(connected)
    {
      if (::ReadFile(_hPipe, buffer, sizeof(buffer) - 1, &size, NULL))
      {
        buffer[size] = '\0';
        std::string receivedMessage(buffer);
        // if message is received from client, setdirty to call detectDisplay.
        if (clientUniqueMessage.compare(receivedMessage) == 0)
          setDirty();
        else
          logStream << "Incoming message from client does not match with the expected message." << blog::over;
      }
      else
        logStream << "ReadFile failed. " << sys::OperatingSystem::getLastErrorMessage() << blog::over;

    }
    ::DisconnectNamedPipe(_hPipe);
  }
}
C++:

      int timeOut = 500;
      NamedPipeClientStream pipeStream = new NamedPipeClientStream(".", pipeName, PipeDirection.Out, PipeOptions.Asynchronous);
      pipeStream.Connect(timeOut);  

      byte[] buffer = Encoding.UTF8.GetBytes(sendStr);
      pipeStream.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(AsyncSend), pipeStream);
   _hPipe = ::CreateNamedPipe(configurePipeName(getPipeName()).c_str(),
                            PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
                            PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
                            1,
                            bufferSize,
                            bufferSize,
                            NMPWAIT_USE_DEFAULT_WAIT,
                            NULL);

  if (_hPipe == INVALID_HANDLE_VALUE)
  {
    logStream << "CreateNamedPipe failed for " << sys::OperatingSystem::getLastErrorMessage() << blog::over;
    return;
  }

  HANDLE ioEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  overlapped.hEvent = ioEvent;

  assert(overlapped.hEvent);
  if (ioEvent == INVALID_HANDLE_VALUE)
  {
    logStream << "CreateEvent failed for " << sys::OperatingSystem::getLastErrorMessage() << blog::over;
    return;
  }

  while (!terminating())
  {
    BOOL connected = false;
    DWORD waitMessage;
    DWORD timeOut = 700;

    if (!::ConnectNamedPipe(_hPipe, &overlapped))
    {
      switch (::GetLastError()) 
      {
        case ERROR_PIPE_CONNECTED:
          connected = true;
          break;

        case ERROR_IO_PENDING:
          waitMessage = ::WaitForSingleObject(overlapped.hEvent, timeOut);
          if (waitMessage == WAIT_OBJECT_0)
          {
            DWORD dwIgnore;
            BOOL conn = (::GetOverlappedResult(_hPipe, &overlapped, &dwIgnore, TRUE));
            if (conn)
              connected = true;
            else
              logStream << "ConnectedNamedPipe reported an error: " << sys::OperatingSystem::getLastErrorMessage() << blog::over;
          }
          else
            ::CancelIo(_hPipe);
          break;

        default:
          logStream << "ConnectedNamedPipe reported an error: " << sys::OperatingSystem::getLastErrorMessage() << blog::over;
      }
    }

    if(connected)
    {
      if (::ReadFile(_hPipe, buffer, sizeof(buffer) - 1, &size, NULL))
      {
        buffer[size] = '\0';
        std::string receivedMessage(buffer);
        // if message is received from client, setdirty to call detectDisplay.
        if (clientUniqueMessage.compare(receivedMessage) == 0)
          setDirty();
        else
          logStream << "Incoming message from client does not match with the expected message." << blog::over;
      }
      else
        logStream << "ReadFile failed. " << sys::OperatingSystem::getLastErrorMessage() << blog::over;

    }
    ::DisconnectNamedPipe(_hPipe);
  }
}
\u hPipe=::CreateNamedPipe(configurePipeName(getPipeName()).c_str(),
管道|访问|双工|文件|标志|第一个|管道|实例|文件|标志|重叠,
管道|类型|字节|管道|读取模式|字节|管道|等待|管道|拒绝|远程|客户端,
1.
缓冲区大小,
缓冲区大小,
NMP等待使用默认等待,
无效);
if(_hPipe==无效的\u句柄\u值)
{
logStream的最后一个参数指定:

lpSecurityAttributes[in,可选]
指向 指定安全描述符的安全属性结构 用于新命名管道,并确定子进程是否可以 继承返回的句柄。如果lpSecurityAttributes为NULL,则 命名管道获取默认的安全描述符,句柄不能为空 已继承。已命名数据库的默认安全描述符中的ACL 管道将完全控制权授予LocalSystem帐户、管理员、, 和创建者所有者。它们还授予 每个人组和匿名帐户

C++命名管道服务器应用程序在本地系统帐户下运行为Windows服务,具有管理员权限。作为标准用户运行的C客户端应用程序不具有管理员权限。默认情况下(<代码> LpSturyTysAs/<代码>是<代码> null < /代码>)C客户端应用程序只对由运行服务器的C++服务器创建的命名管道进行读访问。

作为一个快速测试,如果您将C++客户端应用程序作为管理员运行,它就能够成功地与C++服务器应用程序通信。

修复此问题时,C++服务器应用程序需要为命名管道对象创建安全描述符,并为每个人授予对它的访问权限。请参阅创建安全描述符。

我在我的C++服务器应用程序中运行了一个<代码>类名称PiPiServer流<代码>。这里是创建命名管道的代码的一部分,供参考。

NamedPipeServerStream::NamedPipeServerStream(const std::string & pipeName, const unsigned pipeBufferSize /*= PIPE_BUFFER_SIZE*/)
    : m_hPipe(INVALID_HANDLE_VALUE)
    , m_pipeName(PIPE_NAME_ROOT + pipeName)
    , m_bConnected(false)
{
    PSID pEveryoneSID = NULL;
    PSID pAdminSID = NULL;
    PACL pACL = NULL;
    EXPLICIT_ACCESS ea[2];
    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
    SECURITY_ATTRIBUTES sa;
    SCOPE_GUARD{
        if (pEveryoneSID) { FreeSid(pEveryoneSID); }
        if (pAdminSID) { FreeSid(pAdminSID); }
        if (pACL) { LocalFree(pACL); }
    };

    // Create a well-known SID for the Everyone group.
    if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
    {
        throw std::runtime_error("AllocateAndInitializeSid failed, GLE=" + std::to_string(GetLastError()));
    }
    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    SecureZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));
    // The ACE will allow Everyone full access to the key.
    ea[0].grfAccessPermissions = FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ;  
    ea[0].grfAccessMode = SET_ACCESS;
    ea[0].grfInheritance = NO_INHERITANCE;
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea[0].Trustee.ptstrName = (LPTSTR)pEveryoneSID;

    // Create a SID for the BUILTIN\Administrators group.
    if (!AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pAdminSID))
    {
        throw std::runtime_error("AllocateAndInitializeSid failed, GLE=" + std::to_string(GetLastError()));
    }
    // The ACE will allow the Administrators group full access to the key.
    ea[1].grfAccessPermissions = FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ;   
    ea[1].grfAccessMode = SET_ACCESS;
    ea[1].grfInheritance = NO_INHERITANCE;
    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[1].Trustee.ptstrName = (LPTSTR)pAdminSID;

    // Create a new ACL that contains the new ACEs.
    DWORD dwRes = SetEntriesInAclW(2, ea, NULL, &pACL);
    if (ERROR_SUCCESS != dwRes)
    {
        throw std::runtime_error("SetEntriesInAcl failed, GLE=" + std::to_string(GetLastError()));
    }
    // Initialize a security descriptor.  
    auto secDesc = std::vector<unsigned char>(SECURITY_DESCRIPTOR_MIN_LENGTH);
    PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)(&secDesc[0]);
    if (nullptr == pSD)
    {
        throw std::runtime_error("LocalAlloc failed, GLE=" + std::to_string(GetLastError()));
    }
    if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION))
    {
        throw std::runtime_error("InitializeSecurityDescriptor failed, GLE=" + std::to_string(GetLastError()));
    }
    // Add the ACL to the security descriptor. 
    if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE))   // not a default DACL 
    {
        throw std::runtime_error("SetSecurityDescriptorDacl failed, GLE=" + std::to_string(GetLastError()));
    }
    // Initialize a security attributes structure.
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = pSD;
    sa.bInheritHandle = FALSE;

    // Finally to create the pipe.
    m_hPipe = CreateNamedPipeA(
        m_pipeName.c_str(),             // pipe name 
        PIPE_ACCESS_DUPLEX,       // read/write access 
        PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE |        // Byte Stream type pipe 
        PIPE_WAIT,                // blocking mode 
        PIPE_UNLIMITED_INSTANCES, // max. instances  
        pipeBufferSize,                  // output buffer size 
        pipeBufferSize,                  // input buffer size 
        0,                        // client time-out 
        &sa);                    // default security attribute 

    if (!IsPipeCreated())
    {
        throw std::runtime_error("CreateNamedPipe failed, GLE=" + std::to_string(GetLastError()));
    }
}

bool NamedPipeServerStream::IsPipeCreated() const
{
    return (INVALID_HANDLE_VALUE != m_hPipe);
}
NamedPipeServerStream::NamedPipeServerStream(常量std::string&pipeName,常量unsigned pipeBufferSize/*=PIPE\u BUFFER\u SIZE*/)
:m_hPipe(无效的\u句柄\u值)
,m_pipeName(管道名称\u根+管道名称)
,m_b已连接(错误)
{
PSID pEveryoneSID=NULL;
PSID pAdminSID=NULL;
PACL PACL=NULL;
显式访问ea[2];
SID\u IDENTIFIER\u AUTHORITY SIDAuthWorld=SECURITY\u WORLD\u SID\u AUTHORITY;
SID\u IDENTIFIER\u AUTHORITY SIDAuthNT=安全\u NT\u AUTHORITY;
安全(a);
保护罩{
if(pEveryoneSID){FreeSid(pEveryoneSID);}
if(pAdminSID){FreeSid(pAdminSID);}
if(pACL){LocalFree(pACL);}
};
//为Everyone组创建一个已知的SID。
if(!AllocateAndInitializeSid(&SIDAuthWorld,1,SECURITY\u WORLD\u RID,0,0,0,0,0,0,&peveryoneId))
{
抛出std::runtime_错误(“AllocateAndInitializeSid失败,GLE=“+std::to_字符串(GetLastError()));
}
//初始化ACE的显式访问结构。
SecureZeroMemory(&ea,2*sizeof(显式访问));
//ACE将允许每个人完全访问密钥。
ea[0].grfAccessPermissions=FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ;
ea[0].grfAccessMode=SET\u ACCESS;
ea[0]。grfInheritance=NO_继承;
ea[0].Trustee.TrusteeForm=Trustee\u是\u SID;
ea[0].Trustee.TrusteeType=Trustee\u是\u众所周知的\u组;
ea[0].Trustee.ptstrName=(LPTSTR)pEveryoneSID;
//为BUILTIN\Administrators组创建SID。
if(!AllocateAndInitializeSid(&SIDAuthNT,2,安全性\内置\域\ RID,域\别名\ RID\管理员,0,0,0,0,0,0,&pAdminSID))
{
抛出std::runtime_错误(“AllocateAndInitializeSid失败,GLE=“+std::to_字符串(GetLastError()));
}
//ACE将允许管理员组完全访问密钥。
ea[1].grfAccessPermissions=FILE_ALL_ACCESS | GENERIC_WRITE | GENERIC_READ;
ea[1].grfAccessMode=SET\u ACCESS;
ea[1]。grfInheritance=NO_继承;
ea[1].Trustee.TrusteeForm=Trustee\u是\u SID;
ea[1].Trustee.TrusteeType=Trustee\u是\u组;
ea[1].Trustee.ptstrName=(LPTSTR)pAdminSID;
//创建包含新ACE的新ACL。
DWORD dwRes=SetEntriesInAclW(2,ea,NULL和pACL);
如果(错误\u成功!=dwRes)
{
抛出std::runtime_错误(“setEntriesAcl失败,GLE=“+std::to_字符串(GetLastError()));
}
//初始化安全描述符。
auto secDesc=std::vector(安全描述符最小长度);
PSECURITY_描述符pSD=(PSECURITY_描述符)(&secDesc[0]);
if(nullptr==pSD)
{
抛出std::runtime_错误(“LocalAlloc失败,GLE=“+std::to_字符串(GetLastError()));
}
if(!InitializeSecurityDescriptor(pSD,安全描述符修订版))
{
抛出std::runtime_错误(“InitializeSecurityDescriptor失败,GLE=“+std::to_字符串(GetLastError()));
}
//将ACL添加到安全描述符。
如果(!SetSecurityDescriptorDacl(pSD、TRUE、pACL、FALSE))//不是默认DACL
{
抛出std::runtime_错误(“SetSecurityDescriptorDacl失败,GLE=“+std::to_字符串(获取