问题
I'm listing my named pipes using this code:
private IEnumerable<string> GetNamedPipesList()
{
string[] listOfAllPipes = Directory.GetFiles(@"\\.\pipe\");
return listOfAllPipes.Where(pipe => pipe.Contains("FST"));
}
It works fine. I can display them:
private void Scan_Click(object sender, EventArgs e)
{
IEnumerable<string> fsbPipes = GetNamedPipesList();
tbxOutput.Text = string.Empty;
foreach (string fsbPipe in fsbPipes)
{
var pipe = fsbPipe.Replace(@"\\.\pipe\", "");
tbxOutput.AppendText(pipe + Environment.NewLine);
}
}
Examples:
FST-MT4_Miroslav-130
FST-MT4_Miroslav-150
FST-MT4_Miroslav-120
After that I want to close them by deleting like files:
private void CloseAll_Click(object sender, EventArgs e)
{
IEnumerable<string> myPipes = GetNamedPipesList();
foreach (string pipe in myPipes)
{
try
{
File.Delete(pipe);
}
catch (Exception exception)
{
tbxOutput.AppendText(exception.Message + Environment.NewLine);
}
}
}
But it returns The parameter is incorrect. I'm not sure that I can do it, but I had to try since I loaded them as files.
How I can close these named pipes?
回答1:
According to MSDN, there's a set of classes dedicated to operating on named pipes - but they apply only when you are actually owning them in your application.
What you are doing here is actually listing the named pipes via lower API, filesystem. However, namedpipes are really unlike files: they are shared via many processes, and there's some garbagecollection-like mechanism that removes them automatically when it is not used anymore (see ie. http://social.msdn.microsoft.com/Forums/vstudio/en-US/66f747a0-22c9-4e7d-bb5a-e4e63197318a/deleting-named-pipe). Strictly speaking: when all interested processes close their handles to the pipe, it will be destroyed.
Look at the lower-level API for handling the pipes: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365150(v=vs.85).aspx There's not a mention about destruction. Only Create Connect Disconnect.
If I recall correctly, even on *nix filesystems, the 'rm' on a named pipe does not destroy it. It detaches the file's inodes from the directory and effectively "hides" the special file, but whoever has this file opened - holds it and pins it and the special file still exists and is in use until the last filehandle is closed, only then the actual file is really freed.
So.. maybe you should try to rephrase your problem and search who holds the pipe and then 'talk' to them to close the handle in a normal way? I.e. connect to the pipe and send a polite message "please quit" in the correct application protocol?
Ok, having written all of that, now to the actual solution.
Since you know the pipe, if you have access rights high enough, you may do anything. You may enumerate all processes, you may inspect them for their Handles, you may inspect each handle and check what does it point to. If it points to a Pipe, you may extract the name of that pipe. If the name matches with your pipe, you may inject a thread into that process and from that thread you may close the handle and immediatelly SUSPEND that process in case it detects the broken handle and start reconnecting to that pipe. Loop that over all processes and you might be quite sure that your pipe will get closed. Then, you can do your things with your now-nonexistent pipe and RESUME all those processes.
I think all of that is perfectly possible as some tools like ProcessHacker2 can display many details of handles of other processes, and also allow you to close that handles on demand. So, just duplicate, filter, and automate that task and its done. But, really, that is dangerous and hardly a stable/reliable solution.
回答2:
Thanks to @CodeCaster and @quetzalcoatl I found out that we cannot delete named pipes, but we have to kill their holders instead.
The easiest way to do so, if we know the holders name, is to use Task Manager.
I made a small tool that lists the named pipes. It supports filtering.
Download link: ListNamedPipes.exe
![](https://i0.wp.com/i.stack.imgur.com/zoBLe.png)
![](https://i0.wp.com/i.stack.imgur.com/kL4lA.png)
The code is here:
private void Scan_Click(object sender, EventArgs e)
{
IEnumerable<string> fsbPipes = GetNamedPipesList();
tbxOutput.Text = string.Empty;
foreach (string fsbPipe in fsbPipes)
{
string pipe = fsbPipe.Replace(@"\\.\pipe\", "");
tbxOutput.AppendText(pipe + Environment.NewLine);
}
}
private IEnumerable<string> GetNamedPipesList()
{
string[] listOfAllPipes = Directory.GetFiles(@"\\.\pipe\");
return listOfAllPipes.Where(pipe => pipe.Contains(tbxFilter.Text));
}
来源:https://stackoverflow.com/questions/17423689/delete-named-pipe-net