2013-07-02 3 views
4

я перечисляю мои именованные каналы, используя этот код:Удалить именованный канал .NET

private IEnumerable<string> GetNamedPipesList() 
    { 
     string[] listOfAllPipes = Directory.GetFiles(@"\\.\pipe\"); 
     return listOfAllPipes.Where(pipe => pipe.Contains("FST")); 
    } 

Он отлично работает. Я могу показать их:

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

Примеры:

FST-MT4_Miroslav-130 
FST-MT4_Miroslav-150 
FST-MT4_Miroslav-120 

После того, что я хочу, чтобы закрыть их, удалив как файлы:

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

Но он возвращает неправильный параметр. Я не уверен, что могу это сделать, но мне пришлось попробовать, так как я загружал их в файлы.

Как я могу закрыть эти именованные трубы?

+2

[Экземпляр именованного канала всегда удаляется, когда последняя дескриптор экземпляра именованного канала закрывается] (http://msdn.microsoft.com/en-us/library/windows/desktop/aa365150 (v = vs.85) .aspx). Вам действительно нужно вручную закрыть его? Что, кроме 'File.Delete()', пытались ли вы это сделать? – CodeCaster

+0

Я использую трубы для связи с сторонним программным обеспечением. Он оставил эти трубы открытыми после закрытия. Оба приложения закрыты, но каналы все еще открыты. Такое поведение было сообщено моими пользователями, но это случается со мной в первый раз. Я пытаюсь разработать инструмент для их сброса. –

+1

После вашего комментария я проверил диспетчер задач и заметил, что стороннее приложение не закрыто. Там были два экземпляра, работающих на фоне. Когда я их вручную закрыл. Остальные именованные каналы были закрыты. Это устраняет мою проблему и делает мой вопрос неуместным. –

ответ

3

Согласно MSDN, существует набор классов, предназначенных для работы с именованными каналами, но они применяются только тогда, когда вы фактически владеете ими в своем приложении.

Что вы здесь делаете, это фактически перечисление именованных каналов через нижний API, файловую систему. Тем не менее, namedpipes действительно не похожи на файлы: они совместно используются многими процессами, и есть механизм garbagecollection-like, который автоматически удаляет их, когда он больше не используется (см., Например, http://social.msdn.microsoft.com/Forums/vstudio/en-US/66f747a0-22c9-4e7d-bb5a-e4e63197318a/deleting-named-pipe). Строго говоря: когда все заинтересованные процессы закрывают свои ручки к трубе, они будут уничтожены.

Посмотрите на API нижнего уровня для обработки труб: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365150(v=vs.85).aspx Не упоминается об уничтожении. Только Create Connect Disconnect.

Если я правильно помню, даже в файловых системах * nix, «rm» на именованном канале не уничтожает его. Он отделяет inode файла от каталога и эффективно «скрывает» специальный файл, но тот, у кого этот файл открыт, удерживает его и выталкивает, а специальный файл все еще существует и используется до тех пор, пока последний дескриптор файла не будет закрыт, только тогда фактический файл действительно освобожден.

Итак, возможно, вам стоит попытаться перефразировать вашу проблему и найти, кто держит трубку, а затем «поговорить» с ними, чтобы закрыть ручку обычным способом? То есть подключиться к трубе и отправить вежливое сообщение «пожалуйста, выходите» в правильном протоколе приложения?

Хорошо, написав все это, теперь до фактического решения.

Поскольку вы знаете трубку, если у вас есть права доступа достаточно высоко, вы можете делать что угодно. Вы можете перечислить все процессы, вы можете проверить их на свои Ручки, вы можете проверить каждый дескриптор и проверить, на что он указывает. Если он указывает на трубку, вы можете извлечь имя этого канала. Если имя совпадает с вашим трубой, вы можете вставить поток в этот процесс, и из этого потока вы можете закрыть дескриптор и сразу же ПОДОЗРЕВАТЬ этот процесс, если он обнаружит сломанный дескриптор и начнет повторное подключение к этому каналу. Петля вокруг всех процессов, и вы можете быть уверены, что ваша труба будет закрыта. Затем вы можете делать свои вещи с помощью своего ныне несуществующего канала и возобновлять все эти процессы.

Я думаю, что все это вполне возможно, так как некоторые инструменты, такие как ProcessHacker2, могут отображать многие детали ручек других процессов, а также позволяют закрывать эти ручки по требованию. Итак, просто дублируйте, фильтруйте и автоматизируйте эту задачу и ее выполнение. Но, действительно, это опасно и вряд ли стабильное/надежное решение.

3

Благодаря @CodeCaster и @quetzalcoatl я узнал, что мы не можем удалить именованные каналы, но вместо этого мы должны убить их держателей.

Самый простой способ сделать это, если мы знаем имя владельца, - использовать диспетчер задач.

Я сделал небольшой инструмент, который перечисляет именованные трубы. Он поддерживает фильтрацию.

Ссылка для скачивания: ListNamedPipes.exe

No filter

Filter Chrome pipes

Код здесь:

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)); 
    } 
Смежные вопросы