WCF NetNamedPipeBinding确定客户端的进程ID
本文关键字:进程 ID 客户端 NetNamedPipeBinding WCF | 更新日期: 2023-09-27 18:21:06
是否可以使用NetNamedPipeBinding作为绑定来确定连接到ServiceHost的客户端进程ID?
Bryan,
只是花了几个小时研究这个问题,我相对肯定这是不可能的。使用注释中引用的GetNamedPipeClientProcessId
似乎总是返回主机PID,无论您离管道有多近。
为了稍微扩展一点——当使用GetNamedPipeClientProcessId
时,我们首先需要一个命名管道的句柄。由于WCF并没有使其特别容易找到(请参阅此处),因此我们需要对内存映射文件进行处理,以确定命名管道的GUID。Divi的答案是:通过程序获取命名管道的系统名称,演示如何获取该值。
一旦我们有了GUID值,我们就可以像这样实际使用GetNamedPipeClientProcessId
(请原谅垃圾代码):
// Real name of the named pipe, thanks Divi!
string pipeAccess = String.Format(@"''.'pipe'{0}", Program.pipeGuid);
// Get our handle to the named pipe
IntPtr pipe = CreateFile(pipeAccess, FileAccess.ReadWrite,
0, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);
uint pid = 0;
GetNamedPipeClientProcessId(pipe, out pid);
Console.WriteLine("Real client PID: {0}", pid);
我的第一个想法是直接在OperationContract
函数中运行上面的内容——不幸的是,这返回了主机的PID,而不是客户端的PID。接下来,我试图找到更多关于GetNamedPipeClientProcessId
的信息,但只能确定它返回存储在与命名管道相关的内核结构中的信息——我无法找到更多关于如何/在哪里/为什么设置该值的信息。
由于WCF将字节直接封送至Message
对象,我认为在返回正确的客户端PID之前,我们可能需要更接近管道。实现一个非常简单的自定义消息编码器,并尝试像这样拉动PID:
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
string pipeAccess = String.Format(@"''.'pipe'{0}", Program.pipeGuid);
IntPtr pipe = CreateFile(pipeAccess, FileAccess.ReadWrite,
0, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);
uint pid = 0;
GetNamedPipeClientProcessId(pipe, out pid);
Console.WriteLine("Real client PID: {0}", pid);
return _encoder.ReadMessage(buffer, bufferManager, contentType);
}
也没有成功,再次返回主机的PID。总的来说,我不确定是否有一种方法可以在使用WCF时实际提取这些信息。如果其他人能找到这样做的方法,我也很想知道。也许基于NetNamedPipeBinding的自定义绑定会起作用。
原始答案-2015年6月11日
我不确定你是否能够直接从管道中获得PID。我相信最简单的方法是如下。。。
服务器:
namespace WCFServer
{
[ServiceContract]
public interface IUtils
{
[OperationContract]
void PostPID(int value);
}
public class Utils : IUtils
{
public void PostPID(int value)
{
// Do something with value here
Console.WriteLine(value);
}
}
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(
typeof(Utils),
new Uri[]{
new Uri("net.pipe://localhost")
}))
{
host.AddServiceEndpoint(typeof(IUtils),
new NetNamedPipeBinding(),
"Pipepipe");
host.Open();
Console.WriteLine("Service is available. " +
"Press <ENTER> to exit.");
Console.ReadLine();
host.Close();
}
}
}
}
客户:
namespace WCFClient
{
[ServiceContract]
public interface IUtils
{
[OperationContract]
void PostPID(int value);
}
class Program
{
static void Main(string[] args)
{
ChannelFactory<IUtils> pipeFactory =
new ChannelFactory<IUtils>(
new NetNamedPipeBinding(),
new EndpointAddress(
"net.pipe://localhost/Pipepipe"));
IUtils pipeProxy =
pipeFactory.CreateChannel();
pipeProxy.PostPID(Process.GetCurrentProcess().Id);
}
}
}