在打包的UWP应用程序和Desktop.Net 6.0程序之间带有管道的IPC



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

我正在尝试在我的两个项目之间使用IPC,其中一个是UWP打包的应用程序,另一个是C#.net6应用程序。我已经成功地在.net6程序中创建了一个NamedPipeServerStream。最初,我的UWP侧管道客户端(NamedPipeClientStream(将在创建期间由于";对路径的访问被拒绝";错误

在进行研究时,我推断我需要添加一些与UWP包SID相关的访问规则,以便我的UWP应用程序能够成功地与外部应用程序通信。net NamedPipeServerStream似乎不允许通过构造函数添加访问规则,但我可以使用nuget包NamedPipeServer Stream.NetFrameworkVersion来解决这个问题。我可以使用文档中描述的函数来获取SID,尽管这是错误的SID。使用来自powershell命令"的硬编码SID;CheckNetIsolation.exe LoopbackExempt-s";,我能够在我的UWP应用程序中成功创建NamedPipeClientStream对象,克服了拒绝访问的错误。

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

无法加载文件或程序集"System.Security.Principal.Windows,版本=5.0.0.0,区域性=中性,PublicKeyToken=b03f5f7f11d50a3a'。找到的程序集的清单定义与程序集不匹配参考(HRESULT异常:0x80131040(

几个问题:

  1. 在这两个项目之间建立管道真的这么难吗?我离隧道尽头的灯光近吗?

  2. 为什么我的两种接收打包应用程序SID的方法会导致不同的SIDS?C#中有没有一种很好的编程方法可以做到这一点?

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

服务器:

//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

客户:

pipeClient = new NamedPipeClientStream(".", "testpipe", PipeDirection.InOut, PipeOptions.Asynchronous);
pipeClient.Connect(5000); // fails here

我能够通过独立研究获得某种可行的解决方案。几个答案:

  1. NamedPipeServerStreamConstructors.New via NamedPipeServer Stream.NetFrameworkVersion是一种不推荐使用的策略。Net 6.0提供了我试图通过NamedPipeServerStreamACL实现的功能。我选择使用这个,而不是目前在我的样本中。

  2. 我无法用";System.Security.Principal.Windows";当我尝试使用NamedPipeClientStream进行连接时,在我的UWP应用程序中发生了这种情况。我觉得可能是个bug什么的。如果有人知道那里发生了什么,我们将不胜感激。

  3. 为了解决#2问题,我使用CreateFileW实现了一个较低级别的版本。这是一个较低级别的c++函数,而上一个是c#的等价函数。看起来C#版本在"方面具有一些智能;。\管道";前缀,因此在创建管道服务器时不需要它。然而,UWP的客户端代码中的C++函数将需要包括这一点(不需要使用LOCAL前缀(。有了这个设置,我就可以从.Net 6.0管道服务器向UWP管道客户端发送请求,并得到响应。最后是一些代码片段:

  4. 仍然不知道为什么我通过DeriveAppContainerSidFromAppContainerName得到了不正确的SID。我查看了我的注册表,甚至找不到它试图指向我的SID。超级困惑。

客户端代码:

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);

服务器构造代码:

NamedPipeServerStream pipeServer = NamedPipeServerStreamAcl.Create("testpipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous, 512, 512, access);

相关内容

最新更新