以编程方式获取命名管道的系统名称
Programically get the system name of named pipe
我正在使用 WCF NetNamedPipeBinding 编写进程间通信。
我的目标是在 "net.pipe://localhost/service" 提供服务 运行,所以我 运行 最简单的主机:
host = new ServiceHost(contract, new Uri[] { "net.pipe://localhost" });
host.AddServiceEndpoint(typeof (IContract),
new NetNamedPipeBinding(), "service");
host.Open();
根据http://blogs.msdn.com/b/rodneyviana/archive/2011/03/22/named-pipes-in-wcf-are-named-but-not-by-you-and-how-to-find-the-actual-windows-object-name.aspx
该名称隐藏在系统生成的 guid 后面。
问题来了。
有什么方法可以在我的程序中获取系统 (guid) 生成的名称,这样我就可以像在 procexp 中一样获取类似“\Device\NamedPipe\GUID”的路径,这样更容易嗅探它?
(除了 运行 sys 内部可执行文件在单独的进程中并解析其输出?)
如您 link 的文章所示,WCF 将命名管道名称存储在内存映射文件中。要访问它,您需要执行以下操作:
- Endpoint: net.pipe://localhost/TradeService/Service1
- Normalized Endpoint: net.pipe://+/TRADESERVICE/SERVICE1/
- Base 64 representation: bmV0LnBpcGU6Ly8rL1RSQURFU0VSVklDRS9TRVJWSUNFMS8=
- Final memory mapped file: net.pipe:EbmV0LnBpcGU6Ly8rL1RSQURFU0VSVklDRS9TRVJWSUNFMS8=
现在你得到最终的 MMF 名称并打开它。这是 MSDN 上关于使用 MMF 的文章:https://msdn.microsoft.com/en-us/library/dd267590(v=vs.110).aspx
// Open the MMF.
using (var mmf = MemoryMappedFile.OpenExisting(namedPipeMMFName))
{
// Create an accessor for 16 bytes (Size of GUID) starting at
// offset 5 (as the article states)
using (var accessor = mmf.CreateViewAccessor(5, 16))
{
Guid pipeGuid;
accessor.Read<Guid>(0, out pipeGuid);
Console.WriteLine("This should be the pipe name: " + pipeGuid);
}
}
经过大量摆弄和用头撞墙,我终于开始工作了:
Guid pipeGuid;
if (PipeName.Equals("*", StringComparison.InvariantCultureIgnoreCase) || PipeName.Equals("localhost", StringComparison.InvariantCultureIgnoreCase))
PipeName = "*";
string s = string.Format(@"net.pipe://{0}/", PipeName.ToUpper());
if(!string.IsNullOrWhiteSpace(ServiceName))
s = string.Format(@"net.pipe://*/{0}/", ServiceName.ToUpper());
var bytes = Encoding.UTF8.GetBytes(s);
var base64 = Convert.ToBase64String(bytes);
string namedPipeMMFName = string.Format(@"Global\net.pipe:E{0}", base64);
MemoryMappedFileSecurity mSec = new MemoryMappedFileSecurity();
mSec.AddAccessRule(new AccessRule<MemoryMappedFileRights>(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MemoryMappedFileRights.FullControl, AccessControlType.Allow));
using (var mmf = MemoryMappedFile.OpenExisting(namedPipeMMFName, MemoryMappedFileRights.Read))
{
using (var accessor = mmf.CreateViewAccessor(4, 45, MemoryMappedFileAccess.Read))
{
accessor.Read<Guid>(0, out pipeGuid);
}
}
using (NamedPipeClientStream client = new NamedPipeClientStream(GetResolvedText(ServerName), pipeGuid, PipeDirection.InOut,
PipeOptions.None, TokenImpersonationLevel.Impersonation))
{
client.Connect(10000);
}
我必须感谢 Rodney Viana his article 和@Avner Shahar-Kashtan 的回答以及我阅读的许多其他文章。希望我的回答能对以后的人有所帮助。
我正在使用 WCF NetNamedPipeBinding 编写进程间通信。
我的目标是在 "net.pipe://localhost/service" 提供服务 运行,所以我 运行 最简单的主机:
host = new ServiceHost(contract, new Uri[] { "net.pipe://localhost" });
host.AddServiceEndpoint(typeof (IContract),
new NetNamedPipeBinding(), "service");
host.Open();
根据http://blogs.msdn.com/b/rodneyviana/archive/2011/03/22/named-pipes-in-wcf-are-named-but-not-by-you-and-how-to-find-the-actual-windows-object-name.aspx 该名称隐藏在系统生成的 guid 后面。
问题来了。
有什么方法可以在我的程序中获取系统 (guid) 生成的名称,这样我就可以像在 procexp 中一样获取类似“\Device\NamedPipe\GUID”的路径,这样更容易嗅探它? (除了 运行 sys 内部可执行文件在单独的进程中并解析其输出?)
如您 link 的文章所示,WCF 将命名管道名称存储在内存映射文件中。要访问它,您需要执行以下操作:
- Endpoint: net.pipe://localhost/TradeService/Service1
- Normalized Endpoint: net.pipe://+/TRADESERVICE/SERVICE1/
- Base 64 representation: bmV0LnBpcGU6Ly8rL1RSQURFU0VSVklDRS9TRVJWSUNFMS8=
- Final memory mapped file: net.pipe:EbmV0LnBpcGU6Ly8rL1RSQURFU0VSVklDRS9TRVJWSUNFMS8=
现在你得到最终的 MMF 名称并打开它。这是 MSDN 上关于使用 MMF 的文章:https://msdn.microsoft.com/en-us/library/dd267590(v=vs.110).aspx
// Open the MMF.
using (var mmf = MemoryMappedFile.OpenExisting(namedPipeMMFName))
{
// Create an accessor for 16 bytes (Size of GUID) starting at
// offset 5 (as the article states)
using (var accessor = mmf.CreateViewAccessor(5, 16))
{
Guid pipeGuid;
accessor.Read<Guid>(0, out pipeGuid);
Console.WriteLine("This should be the pipe name: " + pipeGuid);
}
}
经过大量摆弄和用头撞墙,我终于开始工作了:
Guid pipeGuid;
if (PipeName.Equals("*", StringComparison.InvariantCultureIgnoreCase) || PipeName.Equals("localhost", StringComparison.InvariantCultureIgnoreCase))
PipeName = "*";
string s = string.Format(@"net.pipe://{0}/", PipeName.ToUpper());
if(!string.IsNullOrWhiteSpace(ServiceName))
s = string.Format(@"net.pipe://*/{0}/", ServiceName.ToUpper());
var bytes = Encoding.UTF8.GetBytes(s);
var base64 = Convert.ToBase64String(bytes);
string namedPipeMMFName = string.Format(@"Global\net.pipe:E{0}", base64);
MemoryMappedFileSecurity mSec = new MemoryMappedFileSecurity();
mSec.AddAccessRule(new AccessRule<MemoryMappedFileRights>(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MemoryMappedFileRights.FullControl, AccessControlType.Allow));
using (var mmf = MemoryMappedFile.OpenExisting(namedPipeMMFName, MemoryMappedFileRights.Read))
{
using (var accessor = mmf.CreateViewAccessor(4, 45, MemoryMappedFileAccess.Read))
{
accessor.Read<Guid>(0, out pipeGuid);
}
}
using (NamedPipeClientStream client = new NamedPipeClientStream(GetResolvedText(ServerName), pipeGuid, PipeDirection.InOut,
PipeOptions.None, TokenImpersonationLevel.Impersonation))
{
client.Connect(10000);
}
我必须感谢 Rodney Viana his article 和@Avner Shahar-Kashtan 的回答以及我阅读的许多其他文章。希望我的回答能对以后的人有所帮助。