Nasıl C # başka bir işlem tarafından kilitli bir dosyayı silerim?

oy
51

C # kullanarak başka bir işlem tarafından kilitli bir dosyayı silmek için bir yol arıyorum. Ben yöntemi (C # bunu nasıl emin değilim rağmen belki kolları takip ederek) dosyası kilitleme hangi işlem bulmak mümkün ardından kullanarak silmek dosyayı tamamlamak için önce bu süreci kapatmalısınız şüpheli File.Delete().

Oluştur 04/08/2008 saat 06:45
kaynak kullanıcı
Diğer dillerde...                            


8 cevaplar

oy
34

Diğer işlemleri Killing yapmak için sağlıklı bir şey değildir. Senin senaryo kaldırma gibi bir şey içeriyorsa, kullanabilirsiniz MoveFileExAPI işlevi sonraki yeniden başlatma üzerinde silinmek üzere dosyayı işaretleyin.

Eğer gerçekten başka bir işlem tarafından kullanılıyor bir dosyayı silmek gerektiğini görünürse, ben yeniden-göz önünde bulundurarak herhangi çözümleri düşünmeden önce gerçek sorunu öneriyoruz.

Cevap 04/08/2008 saat 07:01
kaynak kullanıcı

oy
14

aşağıdaki gibi tipik bir yöntemdir. Sen bunu burada gider C # bunu yapmak istiyor söyledim ...

  1. Eğer kilitli dosyayı hangi işlemin bilmiyorsanız, her sürecin sap listesini incelemek gerekir ve kilitli dosyayı tanımlayan olmadığını belirlemek için her kolu sorgulamak gerekir. C # Bunu yapmak ihtimalle gerekir yerli API'leri çağırmaya P / ınvoke veya bir aracı C ++ / CLI gerektirecektir.
  2. Eğer karar verdikten sonra hangi işlem (ler) daha sonra başlamak zorunda gibi dosya kilitlemiş, sen de yönetilen bir DLL enjekte edebilir, ancak bu kötü olması (güvenle sürecine küçük yerli DLL enjekte etmek gerekir ya) .NET çalışma zamanı eklemek.
  3. Bu önyükleme DLL sonra vb CloseHandle kullanarak tanıtıcı kapatır

Esasen: "kilitli" bir dosyayı açmak için bir yol kusurlu sürecin adres uzaya bir DLL dosyasını enjekte ve kendiniz kapatmaktır. Bunu kullanarak yerel veya yönetilen kod yapabilirsiniz. Ne olursa olsun, sen / küçük yerli kod miktarını ya da en azından P ihtiyaç aynı içine Çağır gidiyoruz.

Faydalı Bağlantılar:

İyi şanslar!

Cevap 04/08/2008 saat 07:15
kaynak kullanıcı

oy
7

Programlama yoluyla bunu yapmak istiyorum. Emin değilim ... ve gerçekten buna karşı öneriyoruz. Eğer sadece kendi makinede şeyler giderme ediyorsanız, SysInternals Process Explorer size yardımcı olabilir

Koştur, Kulp bul komutunu (Ben ya düşünüyorum bulmak veya sap menüsünde) kullanın ve dosyanızın adını arayın. sap (ler) bulunursa sonra, zorla onları kapatabilirsiniz.

Daha sonra böyle devam dosyayı ve silebilir.

Dikkat sadece bunun altından meşhur halı çekti ettik, garip davranmaya kolları sahibi olan programı neden olabilir Bunu yaparken, ama kendi yanlış kod hata ayıklama veya ne zaman visual studio / windows gezgini zaman iyi çalışıyor olan bok olmak ve dosyayı serbest değil :-) nefes ... sen önce dosya yaş kapatmak için onlara rağmen kolları

Cevap 04/08/2008 saat 07:12
kaynak kullanıcı

oy
4

Orion Edwards tavsiye kullanarak ben ANNELER indirilen Process Explorer sırayla bana dosya ı tarafından değil tutuluyor aslında oldu silme zorlanan olduğunu keşfetmek için izin Excel.Applicationsdüşündüm nesne değil, benim C # kodu posta kodu göndermek gerçeği yaratmıştı açık bu dosya için bir tanıtıcı bıraktı bir Ek nesnesi.

Bunu görene keresinde oldukça basit Eklenti nesnenin dispose yöntemine denir ve sap serbest bırakıldı.

ANNELER kaşif bana bu Visual Studio 2005 hata ayıklayıcı ile birlikte kullanıldığında keşfetmeye izin verdi.

Çok bu aracı tavsiye!

Cevap 04/03/2009 saat 14:43
kaynak kullanıcı

oy
4

Sen, bu programı kullanabilirsiniz Kulp dosyanızın kilidi olan süreç bulmak için. Ben programlı onu bulma konusunda emin değilim ... Bu bir komut satırı aracı, bu yüzden seni ondan çıkış kullanmak sanırım.

dosya silme bekleyebilirseniz bilgisayarınızın yanındaki başladığında, sen silinmek üzere bunu belirtebilirsiniz:

  1. Başlangıç REGEDT32 (W2K)veya REGEDIT (WXP)ve gidin:

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager
    
  2. W2K ve WXP

    • W2K:
      düzenleyin
      Değer Katan ...
      Veri Türü: REG_MULTI_SZ
      Değer Adı:PendingFileRenameOperations
      OK

    • WXP:
      Düzen
      Yeni
      Çok dizeli değer
      enter
      PendingFileRenameOperations

  3. Veri alanında, girmek "\??\" + filenamesilinecek. LFN tırnak içinde gömülü olmadan girilebilir. Silmek için C:\Long Directory Name\Long File Name.exe, aşağıdaki verileri girin:

    \??\C:\Long Directory Name\Long File Name.exe
    

    Sonra basın OK.

  4. "Hedef dosya adı" boş (sıfır) dizedir. Aşağıdaki gibi girilir:

    • W2K:
      Düzenleme
      İkili
      seçme Veri Formatı: Hex
      onaltılık dize sonundaki tıklama
      girmek 0000 (dört sıfır)
      OK

    • WXP:
      sağ tıklayın değeri
      seçin "Değiştir İkili Veri"
      onaltılık dize sonundaki tıklayın
      0000 (dört sıfır) girin
      OK

  5. Yakın REGEDT32/REGEDITve yeniden başlatma dosyasını silmek.

(Utanmadan çalınan bazı rasgele forumda posterity aşkına.)

Cevap 04/08/2008 saat 06:59
kaynak kullanıcı

oy
3

Bu umut verici görünüyor. dosya tanıtıcısı öldürme bir yolu ....

http://www.timstall.com/2009/02/killing-file-handles-but-not-process.html

Cevap 25/02/2009 saat 18:41
kaynak kullanıcı

oy
3

Oh, yıllar önce kullanılan bir büyük kesmek, Windows izin vermez olmasıdır silme dosyaları, ancak bu izin vermez hareket onları.

Sözde sort-of-kodu:

mv %WINDIR%\System32\mfc42.dll %WINDIR\System32\mfc42.dll.old
Install new mfc42.dll
Tell user to save work and restart applications

Uygulamaları yeniden ne zaman (biz makineyi yeniden gerek yoktu unutmayın), bunlar yeni yüklenen mfc42.dllve tüm iyi oldu. Ile birleştiğinde Yani, PendingFileOperationsbütün sistem yeniden dahaki sefere oldukça iyi çalıştı eskisini silin.

Cevap 04/08/2008 saat 07:14
kaynak kullanıcı

oy
2

Sen tam dosya yolunu tedarik kodu kullanabilirsiniz ve bir döner List<Processes>bu dosyayı kilitleme şey:

using System.Runtime.InteropServices;
using System.Diagnostics;

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

    /// <summary>
    /// Find out what process(es) have a lock on the specified file.
    /// </summary>
    /// <param name="path">Path of the file.</param>
    /// <returns>Processes locking the file</returns>
    /// <remarks>See also:
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373661(v=vs.85).aspx
    /// http://wyupdate.googlecode.com/svn-history/r401/trunk/frmFilesInUse.cs (no copyright in code at time of viewing)
    /// 
    /// </remarks>
    static public List<Process> WhoIsLocking(string path)
    {
        uint handle;
        string key = Guid.NewGuid().ToString();
        List<Process> processes = new List<Process>();

        int res = RmStartSession(out handle, 0, key);
        if (res != 0) throw new Exception("Could not begin restart session.  Unable to determine file locker.");

        try
        {
            const int ERROR_MORE_DATA = 234;
            uint pnProcInfoNeeded = 0,
                 pnProcInfo = 0,
                 lpdwRebootReasons = RmRebootReasonNone;

            string[] resources = new string[] { path }; // Just checking on one resource.

            res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null);

            if (res != 0) throw new Exception("Could not register resource.");                                    

            //Note: there's a race condition here -- the first call to RmGetList() returns
            //      the total number of process. However, when we call RmGetList() again to get
            //      the actual processes this number may have increased.
            res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons);

            if (res == ERROR_MORE_DATA)
            {
                // Create an array to store the process results
                RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
                pnProcInfo = pnProcInfoNeeded;

                // Get the list
                res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
                if (res == 0)
                {
                    processes = new List<Process>((int)pnProcInfo);

                    // Enumerate all of the results and add them to the 
                    // list to be returned
                    for (int i = 0; i < pnProcInfo; i++)
                    {
                        try
                        {
                            processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId));
                        }
                        // catch the error -- in case the process is no longer running
                        catch (ArgumentException) { }
                    }
                }
                else throw new Exception("Could not list processes locking resource.");                    
            }
            else if (res != 0) throw new Exception("Could not list processes locking resource. Failed to get size of result.");                    
        }
        finally
        {
            RmEndSession(handle);
        }

        return processes;
    }
}

Daha sonra dosyaları işlemlerin listesini yineleme ve onları kapatın ve silin:

    string[] files = Directory.GetFiles(target_dir);
    List<Process> lstProcs = new List<Process>();

    foreach (string file in files)
    {
        lstProcs = ProcessHandler.WhoIsLocking(file);
        if (lstProcs.Count > 0) // deal with the file lock
        {
            foreach (Process p in lstProcs)
            {
                if (p.MachineName == ".")
                    ProcessHandler.localProcessKill(p.ProcessName);
                else
                    ProcessHandler.remoteProcessKill(p.MachineName, txtUserName.Text, txtPassword.Password, p.ProcessName);
            }
            File.Delete(file);
        }
        else
            File.Delete(file);
    }

Ve dosya yerel bilgisayarda ise bağlı olarak:

public static void localProcessKill(string processName)
{
    foreach (Process p in Process.GetProcessesByName(processName))
    {
        p.Kill();
    }
}

veya bir ağ bilgisayarı:

public static void remoteProcessKill(string computerName, string fullUserName, string pword, string processName)
{
    var connectoptions = new ConnectionOptions();
    connectoptions.Username = fullUserName;  // @"YourDomainName\UserName";
    connectoptions.Password = pword;

    ManagementScope scope = new ManagementScope(@"\\" + computerName + @"\root\cimv2", connectoptions);

    // WMI query
    var query = new SelectQuery("select * from Win32_process where name = '" + processName + "'");

    using (var searcher = new ManagementObjectSearcher(scope, query))
    {
        foreach (ManagementObject process in searcher.Get()) 
        {
            process.InvokeMethod("Terminate", null);
            process.Dispose();
        }
    }
}

Kaynaklar:
nasıl .NET kullanarak bir dosya kilitleme hangi işlem öğrenebilirim?

Birisi bir dosyayı açtı bir dizin silme

Cevap 27/01/2017 saat 20:45
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more