Вопросы об используемых файлах или папках: получите имя другого Процесса, который использует файл или папку - PullRequest
1 голос
/ 15 июля 2010

Я использую C # .NET, против 2008, .net 3.5

Для меня это сложно, но мне нужен пример кода на C # для этого:

  1. Проверьте, используется ли файл или папка

  2. Если файл или папка используется, имя процесса, который их использует

Например, в моем номере.

Я пытаюсь удалить файл и получаю «Процесс не может получить доступ к файлу« XYZ », потому что он используется другим процессом». Исключение.

File.Delete(infoFichero.Ruta);

Я хочу проверить, используется ли файл, и имя процесса, который его использует.

Мне нужен пример кода, исходный код, пожалуйста. Я не хочу использовать c ++, я не знаю c, c ++, неуправляемый код или WinApi. Я хочу использовать только код C # (управляемый код .net).

Я прочитал несколько ссылок, но не смог получить исходный код,

Как проверить, используется ли файл?

Эмулировать ожидание на File.Open в C #, когда файл заблокирован

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/9dabc172-237a-42db-850e-ada08885a5d5

Как проверить, используется ли файл?

Самый простой способ прочитать текстовый файл, заблокированный другим приложением

С помощью C # можно проверить, удерживается ли блокировка для файла

EDIT: От Яна Джуна - MSFT

  string path = "D:\\temp2.xlsx";
            foreach (Process c in Process.GetProcesses()) {

                if (c.MainWindowTitle.Contains(Path.GetFileName(path))){
                    MessageBox.Show(c.ProcessName);
                    return;
                }
            }

            try{
                FileInfo f = new FileInfo(path);

                f.Delete();
            }
            catch (Exception ex){

                MessageBox.Show(ex.Message);
            }

... Но трудно решить все 100% вопросов.

  1. Проблема, если c.MainWindowTitle == null или не содержит имя файла.

  2. Проблема с общей папкой на другом компьютере, компьютере, сервере, например:

File.Delete (@ \ desiis \ височной \ Project \ script.targets);

любой пример кода, я прошу помощи гуру, MVP, кто угодно.

ОБНОВЛЕНИЕ: та же проблема для папки

Ответы [ 3 ]

3 голосов
/ 15 июля 2010

Не будет способа найти процесс, который открыл файл, не заходя в WinApi, я не думаю.А что касается проверки того, используется ли он, единственное, что вы действительно можете сделать, так как вопросы SO, которые вы связали с состоянием, - это обернуть попытки доступа к файлу в блок try / catch.

Код, позволяющий определить, какой файл был открыт, вероятно, будет уродливым, но, возможно, существует API-интерфейс, который хорошо оборачивает это.Есть сторонние утилиты, которые скажут вам об этом ( Unlocker является наиболее известным примером).Вы также можете использовать ProcessExplorer для поиска открытых дескрипторов файлов по имени файла.Это не очень помогает вам, хотя.

Короткий ответ на то, что я пытаюсь донести до вас, состоит в том, что у вас есть ответ на первую часть вашего вопроса в SO-вопросах, которые вы уже связали, а вторая часть, вероятно, потребует вызовов WIN32, которыевы хотите избежать, но вам, вероятно, придется испачкать руки в Win32 ... Все еще хотите помочь?

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

string result = proc.StandardOutput.ReadToEnd();

Проблема в том, что вы получите всплывающее окно с лицензионным соглашением при первом запуске утилиты Handle.Не говоря уже о проблемах лицензирования, если вы планируете развернуть это ...

Если вы все еще заинтересованы, я могу показать вам, как вы поступите с этим.

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ProcessStartInfo si = new ProcessStartInfo();
            si.FileName = "handle.exe";     //name of the handle program from sysinternals
                                            //assumes that its in the exe directory or in your path 
                                            //environment variable

            //the following three lines are required to be able to read the output (StandardOutput)
            //and hide the exe window.
            si.RedirectStandardOutput = true;
            si.WindowStyle = ProcessWindowStyle.Hidden;
            si.UseShellExecute = false;

            si.Arguments = "test.xlsx";     //this is the file you're trying to access that is locked

            //these 4 lines create a process object, start it, then read the output to 
            //a new string variable "s"
            Process p = new Process();
            p.StartInfo = si;
            p.Start();
            string s = p.StandardOutput.ReadToEnd();

            //this will use regular expressions to search the output for process name
            //and print it out to the console window
            string regex = @"^\w*\.EXE";
            MatchCollection matches = Regex.Matches(s, regex, RegexOptions.Multiline);
            foreach (var match in matches)
            {
                Console.WriteLine(match);
            }

            //this will use regex to search the output for the process id (pid)
            //and print it to the console window.
            regex = @"pid: (?<pid>[0-9]*)";
            matches = Regex.Matches(s, regex, RegexOptions.Multiline);
            foreach (var obj in matches)
            {
                Match match = (Match)obj;   //i have to cast to a Match object
                                            //to be able to get the named group out
                Console.WriteLine(match.Groups["pid"].Value.ToString());
            }

            Console.Read();
        }
    }
}
1 голос
/ 15 июля 2010

Нет просто управляемого способа сделать это.Вы должны использовать некоторые низкоуровневые API через P / invoke или аналогичные.

Здесь есть хорошая информация о том, как это сделать, но это код C ++.Вы должны будете выполнить портирование самостоятельно.

http://www.codeproject.com/KB/shell/OpenedFileFinder.aspx

Обратите внимание, что здесь есть некоторые сложные проблемы, а именно проблемы, связанные с ядром и памятью пользовательского пространства.Это не простая проблема, которую вы пытаетесь решить.

0 голосов
/ 15 июля 2010

Попробуйте Windows Process Explorer:

http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

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

...