首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在封装的UWP应用程序和桌面.Net 6.0程序之间安装管道的IPC

在封装的UWP应用程序和桌面.Net 6.0程序之间安装管道的IPC
EN

Stack Overflow用户
提问于 2022-03-03 13:51:14
回答 1查看 164关注 0票数 1

关于在UWP中使用管道IPC的一些复杂问题(不要告诉我要使用应用程序服务,这对于我的项目来说解决方案的延迟太低了)。

我正试图在我的两个项目之间获得工控机,其中一个是UWP打包应用程序,另一个是C# .net6应用程序。我已经在我的NamedPipeServerStream程序中成功地创建了一个.net6。最初,由于“拒绝对路径的访问”错误,我的UWP侧管道客户端(NamedPipeClientStream)在创建过程中会失败。

做研究,我已经推断,我需要添加一些与我的UWP软件包的SID相关的访问规则,这样我的UWP应用程序就可以成功地与我的外部应用程序通信。看起来普通的.net NamedPipeServerStream不允许通过构造函数添加访问规则,但是我能够使用一个nuget包,NamedPipeServerStream.NetFrameworkVersion来解决这个问题。我能够使用文档中描述的函数获得一个SID,尽管结果证明这是错误的SID。使用powershell命令"CheckNetIsolation.exe LoopbackExempt -s“中的硬编码SID,我成功地在我的UWP应用程序中创建了NamedPipeClientStream对象,通过了拒绝访问的错误。

但是,我直接调用的connect方法没有成功。我最终得到了一个错误:

无法加载文件或程序集'System.Security.Principal.Windows,Version=5.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f7f11d50a3a‘。所定位的程序集的清单定义与程序集引用不匹配。(HRESULT例外: 0x80131040)

有几个问题:

  1. 在这两个项目之间做一个管道真的这么困难吗?我靠近隧道尽头的灯了吗?
  2. 为什么我为我的打包应用程序接收SID的两种方法导致了不同的SID?在C#中有一种很好的编程方法来实现这一点吗?

下面是我的一些代码示例:

服务器:

代码语言:javascript
运行
复制
//IntPtr ptr = IntPtr.Zero;
//var result = DeriveAppContainerSidFromAppContainerName("PackageFamilyName", ref ptr);
//var appSid = new SecurityIdentifier(ptr); //results in incorrect SID
var appSid = new SecurityIdentifier("hardCodedSID");
var access = new PipeSecurity();
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
access.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.FullControl, System.Security.AccessControl.AccessControlType.Allow));
access.AddAccessRule(new PipeAccessRule(sid, PipeAccessRights.AccessSystemSecurity, System.Security.AccessControl.AccessControlType.Allow));
access.AddAccessRule(new PipeAccessRule(appSid, PipeAccessRights.FullControl, System.Security.AccessControl.AccessControlType.Allow));
access.AddAccessRule(new PipeAccessRule(appSid, PipeAccessRights.AccessSystemSecurity, System.Security.AccessControl.AccessControlType.Allow));
pipeServer = NamedPipeServerStreamConstructors.New("testpipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.None, 0, 0, access);
pipeServer.WaitForConnection(); // gets past here when client creates NamedPipeClientStream

客户端:

代码语言:javascript
运行
复制
pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut, PipeOptions.Asynchronous);
pipeClient.Connect(5000); // fails here
EN

Stack Overflow用户

发布于 2022-03-04 14:18:11

我找到了一个可行的解决方案来做独立的研究。有几个人回答:

  1. 通过NamedPipeServerStreamConstructors.New通过NamedPipeServerStream.NetFrameworkVersion是一种不推荐的策略。.Net 6.0提供了我试图通过NamedPipeServerStreamACL所做的工作。我选择使用这个,而不是目前在我的样本中。
  2. 当我试图使用System.Security.Principal.Windows连接时,我找不出在我的UWP应用程序中出现的“NamedPipeClientStream”错误。我觉得可能是虫子什么的。如果有人知道那里发生了什么,我们将不胜感激。
  3. 为了解决#2的问题,我使用CreateFileW实现了一个较低级别的版本。这是一个较低级别的c++函数,而前一个是C#等效函数。C#版本似乎具有".\pipe\“前缀的一些智能,因此在创建管道服务器时不需要它。但是,UWP的客户端代码中的C++函数需要包含这一点(不需要使用本地前缀)。通过这种设置,我能够从我的.Net 6.0管道服务器向我的UWP管道客户端发送请求并获得响应。最后是一些代码片段:
  4. 仍然不知道为什么我通过DeriveAppContainerSidFromAppContainerName得到了不正确的SID。我查看了我的注册表,甚至找不到它试图指向我的SID。莫名其妙。

客户代码:

代码语言:javascript
运行
复制
var fileName = @"\\.\pipe\\testpipe";
 IntPtr pipeHandle = CreateFileW(fileName,
  GENERIC_READ | GENERIC_WRITE,
  FILE_SHARE_READ | FILE_SHARE_WRITE,
  IntPtr.Zero,
  OPEN_EXISTING,
  FILE_FLAG_OVERLAPPED,
  IntPtr.Zero);
 if (pipeHandle.ToInt32() == INVALID_HANDLE_VALUE)
 {
  var err = $"Failed to create pipe client, win32 error: {Marshal.GetLastWin32Error()}";
  throw new Exception(err);
 }
 stream = new FileStream(new SafeFileHandle(pipeHandle, true), FileAccess.ReadWrite);

服务器构造代码:

代码语言:javascript
运行
复制
NamedPipeServerStream pipeServer = NamedPipeServerStreamAcl.Create("testpipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous, 512, 512, access);
票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71338318

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档