1

私は C# .NET を使用しており、対 2008 では .net 3.5

私にとっては難しいですが、これには C# のサンプル コードが必要です。

  1. ファイルまたはフォルダーが使用中かどうかを確認する

  2. ファイルまたはフォルダーが使用中の場合、それを使用するプロセスの名前

たとえば、私の問題では。

ファイルを削除しようとすると、「別のプロセスで使用されているため、プロセスはファイル 'XYZ' にアクセスできません。」というメッセージが表示されます。例外。

File.Delete(infoFichero.Ruta);

ファイルが使用されているかどうかと、それを使用しているプロセスの名前を確認したい。

サンプルコード、ソースコードが必要です。私は c++ を使いたくありません。c、c++、アンマネージ コード、または WinApi を知りません。C# コード (マネージド コード .net) のみを使用したい。

私はいくつかの参考文献を読みましたが、サンプル コード ソースを入手できませんでした。

ファイルが使用中かどうかを確認する方法は?

ファイルがロックされているときに C# で File.Open の待機をエミュレートする

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

ファイルが使用中かどうかを確認する方法は?

別のアプリケーションによってロックされているテキスト ファイルを読み取る最も簡単な方法

C# を使用して、ファイルがロックされているかどうかをテストできますか?

編集: Yan Jun から - 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. 別のマシン、PC、サーバーなどの共有フォルダーの問題:

File.Delete(@\desiis\TEmporal\Project\script.targets);

どんなサンプルコードでも、教祖、MVP、誰にでも助けを求めます。

更新:フォルダーの同じ問題

4

3 に答える 3

3

WinApi に足を踏み入れることなく、ファイルが開かれているプロセスを見つける方法はないと思います。そして、それが使用されているかどうかを確認する限り、実際にできる唯一のことは、リンクした SO の質問のように、ファイル アクセスの試行を try/catch ブロックでラップすることです。

どのファイルが開いているかを見つけるためのコードは醜い可能性がありますが、これをうまくまとめる API が世の中にあるかもしれません。これを教えてくれるサードパーティのユーティリティがあります ( Unlockerが最もよく知られている例です)。ProcessExplorerを使用して、開いているファイル ハンドルをファイル名で検索することもできます。しかし、それらは実際には役に立ちません。

私がここで理解しようとしていることの簡単な答えは、すでにリンクされている SO の質問で質問の最初の部分に対する答えがあり、2 番目の部分ではおそらく回避したい WIN32 呼び出しが必要になるということですが、おそらく、Win32 で手を汚さなければならないでしょう... それでも助けが必要ですか?

編集:sysinternalsハンドルユーティリティにシェルアウトできます。そのコマンドの出力を取得して、自分で解析する必要があります。実行されたプロセスの出力を次のように読み取ることができます

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();
        }
    }
}
于 2010-07-15T18:41:07.950 に答える
1

これを行うための純粋に管理された方法はありません。P/invoke などを介していくつかの低レベル API を使用する必要があります。

それを行う方法についての良い情報がここにありますが、それは C++ コードです。移植は自分でやる必要があります。

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

これにはいくつかの複雑な問題があることに注意してください。つまり、カーネルとユーザー空間のメモリに関する問題です。これは、あなたが解決しようとしている単純な問題ではありません。

于 2010-07-15T18:42:44.763 に答える
0

Windows Process Explorer を試してください。

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

コードから実行することはできませんが、少なくともロックの原因を突き止めることはできます。

于 2010-07-15T18:52:13.883 に答える