Cara cek file lock?

Apakah ada cara untuk memeriksa apakah file yang terkunci tanpa menggunakan try/catch block?

Sekarang, satu-satunya cara yang aku tahu adalah untuk hanya membuka file tersebut dan menangkap setiap Sistem.IO.IOException`.

Mengomentari pertanyaan (3)

Ketika saya dihadapkan dengan masalah yang sama, saya selesai dengan kode berikut:


public bool IsFileLocked(string filePath)
{
    try
    {
        using (File.Open(filePath, FileMode.Open)){}
    }
    catch (IOException e)
    {
        var errorCode = Marshal.GetHRForException(e) & ((1 
Komentar (9)

Satu jawaban yang lain bergantung pada informasi lama. Yang satu ini memberikan solusi yang lebih baik.

Lama yang lalu itu mustahil untuk dapat mendapatkan daftar proses penguncian file karena Windows hanya tidak melacak informasi itu. Untuk mendukung [Restart Manajer API][1], informasi yang kini dilacak. Restart Manajer API tersedia yang dimulai dengan Windows Vista dan Windows Server 2008 ([Restart Manager: Run-time Persyaratan][2]).

Saya menempatkan bersama-sama kode yang mengambil jalan berkas dan mengembalikan sebuah Daftar<Proses> dari semua proses yang mengunci file tersebut.


static public class FileUtil
{
    [StructLayout(LayoutKind.Sequential)]
    struct RM_UNIQUE_PROCESS
    {
        public int dwProcessId;
        public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
    }

    const int RmRebootReasonNone = 0;
    const int CCH_RM_MAX_APP_NAME = 255;
    const int CCH_RM_MAX_SVC_NAME = 63;

    enum RM_APP_TYPE
    {
        RmUnknownApp = 0,
        RmMainWindow = 1,
        RmOtherWindow = 2,
        RmService = 3,
        RmExplorer = 4,
        RmConsole = 5,
        RmCritical = 1000
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    struct RM_PROCESS_INFO
    {
        public RM_UNIQUE_PROCESS Process;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)]
        public string strAppName;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)]
        public string strServiceShortName;

        public RM_APP_TYPE ApplicationType;
        public uint AppStatus;
        public uint TSSessionId;
        [MarshalAs(UnmanagedType.Bool)]
        public bool bRestartable;
    }

    [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
    static extern int RmRegisterResources(uint pSessionHandle,
                                          UInt32 nFiles,
                                          string[] rgsFilenames,
                                          UInt32 nApplications,
                                          [In] RM_UNIQUE_PROCESS[] rgApplications,
                                          UInt32 nServices,
                                          string[] rgsServiceNames);

    [DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)]
    static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey);

    [DllImport("rstrtmgr.dll")]
    static extern int RmEndSession(uint pSessionHandle);

    [DllImport("rstrtmgr.dll")]
    static extern int RmGetList(uint dwSessionHandle,
                                out uint pnProcInfoNeeded,
                                ref uint pnProcInfo,
                                [In, Out] RM_PROCESS_INFO[] rgAffectedApps,
                                ref uint lpdwRebootReasons);

    /// 
    /// Find out what process(es) have a lock on the specified file.
    /// 
    /// <param name="path">Path of the file.
Komentar (16)
Larutan

Tidak, sayangnya, dan jika anda berpikir tentang hal ini, informasi yang akan berguna pula karena file bisa menjadi terkunci berikutnya kedua (baca: jangka waktu yang pendek).

Mengapa khusus yang perlu kamu ketahui jika file yang terkunci sih? Mengetahui bahwa mungkin memberi kita cara lain untuk memberikan anda nasihat yang baik.

Jika kode anda akan terlihat seperti ini:

if not locked then
    open and update file

Kemudian antara dua garis, proses lain bisa dengan mudah mengunci file, memberikan anda masalah yang sama anda mencoba untuk menghindari untuk mulai dengan: pengecualian.

Komentar (10)

Anda juga bisa memeriksa apakah ada proses yang menggunakan file ini dan menampilkan daftar program anda harus dekat terus seperti installer.

public static string GetFileProcessName(string filePath)
{
    Process[] procs = Process.GetProcesses();
    string fileName = Path.GetFileName(filePath);

    foreach (Process proc in procs)
    {
        if (proc.MainWindowHandle != new IntPtr(0) && !proc.HasExited)
        {
            ProcessModule[] arr = new ProcessModule[proc.Modules.Count];

            foreach (ProcessModule pm in proc.Modules)
            {
                if (pm.ModuleName == fileName)
                    return proc.ProcessName;
            }
        }
    }

    return null;
}
Komentar (1)

Alih-alih menggunakan interop yang dapat anda gunakan .NET FileStream kelas metode Lock dan Unlock:

FileStream.Kunci http://msdn.microsoft.com/en-us/library/system.io.filestream.lock.aspx

FileStream.Membuka http://msdn.microsoft.com/en-us/library/system.io.filestream.unlock.aspx

Komentar (2)

Anda bisa menghubungi LockFile melalui interop pada wilayah file yang anda tertarik. Ini tidak akan melempar pengecualian, jika berhasil anda akan memiliki kunci pada sebagian dari file (yang diselenggarakan oleh proses anda), bahwa kunci akan diadakan sampai anda memanggil UnlockFile atau proses meninggal.

Komentar (0)

Variasi DixonD's jawaban yang sangat baik (di atas).

public static bool TryOpen(string path,
                           FileMode fileMode,
                           FileAccess fileAccess,
                           FileShare fileShare,
                           TimeSpan timeout,
                           out Stream stream)
{
    var endTime = DateTime.Now + timeout;

    while (DateTime.Now < endTime)
    {
        if (TryOpen(path, fileMode, fileAccess, fileShare, out stream))
            return true;
    }

    stream = null;
    return false;
}

public static bool TryOpen(string path,
                           FileMode fileMode,
                           FileAccess fileAccess,
                           FileShare fileShare,
                           out Stream stream)
{
    try
    {
        stream = File.Open(path, fileMode, fileAccess, fileShare);
        return true;
    }
    catch (IOException e)
    {
        if (!FileIsLocked(e))
            throw;

        stream = null;
        return false;
    }
}

private const uint HRFileLocked = 0x80070020;
private const uint HRPortionOfFileLocked = 0x80070021;

private static bool FileIsLocked(IOException ioException)
{
    var errorCode = (uint)Marshal.GetHRForException(ioException);
    return errorCode == HRFileLocked || errorCode == HRPortionOfFileLocked;
}

Penggunaan:

private void Sample(string filePath)
{
    Stream stream = null;

    try
    {
        var timeOut = TimeSpan.FromSeconds(1);

        if (!TryOpen(filePath,
                     FileMode.Open,
                     FileAccess.ReadWrite,
                     FileShare.ReadWrite,
                     timeOut,
                     out stream))
            return;

        // Use stream...
    }
    finally
    {
        if (stream != null)
            stream.Close();
    }
}
Komentar (8)

Berikut ini's variasi DixonD's kode yang menambah jumlah detik untuk menunggu untuk file untuk membuka, dan coba lagi:


public bool IsFileLocked(string filePath, int secondsToWait)
{
    bool isLocked = true;
    int i = 0;

    while (isLocked &&  ((i < secondsToWait) || (secondsToWait == 0)))
    {
        try
        {
            using (File.Open(filePath, FileMode.Open)) { }
            return false;
        }
        catch (IOException e)
        {
            var errorCode = Marshal.GetHRForException(e) & ((1 
Komentar (1)

Anda dapat melihat jika file terkunci dengan mencoba untuk membaca atau mengunci diri anda terlebih dahulu.

Silakan lihat jawaban saya di sini untuk informasi lebih lanjut.

Komentar (0)

Maka di antara dua garis, proses lain bisa dengan mudah mengunci file, memberikan anda masalah yang sama anda mencoba untuk menghindari untuk mulai dengan: pengecualian.

Namun, cara ini, anda akan tahu bahwa masalah ini bersifat sementara, dan coba lagi nanti. (E. g., anda bisa menulis thread itu, jika menghadapi kunci ketika mencoba untuk menulis, terus mencoba sampai kunci hilang.)

Yang IOException, di sisi lain, tidak dengan sendirinya cukup spesifik bahwa penguncian penyebab IO kegagalan. Mungkin ada alasan-alasan yang tidak't sementara.

Komentar (0)

Hal yang sama tetapi dalam Powershell

function Test-FileOpen
{
    Param
    ([string]$FileToOpen)
    try
    {
        $openFile =([system.io.file]::Open($FileToOpen,[system.io.filemode]::Open))
        $open =$true
        $openFile.close()
    }
    catch
    {
        $open = $false
    }
    $open
}
Komentar (0)

Apa yang akhirnya saya lakukan adalah:

internal void LoadExternalData() {
    FileStream file;

    if (TryOpenRead("filepath/filename", 5, out file)) {
        using (file)
        using (StreamReader reader = new StreamReader(file)) {
         // do something 
        }
    }
}

internal bool TryOpenRead(string path, int timeout, out FileStream file) {
    bool isLocked = true;
    bool condition = true;

    do {
        try {
            file = File.OpenRead(path);
            return true;
        }
        catch (IOException e) {
            var errorCode = Marshal.GetHRForException(e) & ((1  0);

            if (condition) {
                // we only wait if the file is locked. If the exception is of any other type, there's no point on keep trying. just return false and null;
                timeout--;
                new System.Threading.ManualResetEvent(false).WaitOne(1000);
            }
        }
    }
    while (condition);

    file = null;
    return false;
}
Komentar (2)