Tôi đang tìm cách xóa tệp bị khóa bởi một quy trình khác bằng C#. Tôi nghi ngờ phương pháp này phải có khả năng tìm thấy quy trình nào đang khóa tệp (có thể bằng cách theo dõi các xử lý, mặc dù tôi không chắc chắn cách thực hiện điều này trong C#) rồi đóng quá trình đó trước khi có thể hoàn thành việc xóa tệp bằng cách sử dụng File.Delete()
.Làm cách nào để xóa tệp bị khóa bởi một quy trình khác trong C#?
Trả lời
Killing quá trình khác không phải là một dấu hiệu tốt để làm. Nếu kịch bản của bạn liên quan đến việc gỡ cài đặt, bạn có thể sử dụng MoveFileEx
API function để đánh dấu tệp để xóa khi khởi động lại lần tiếp theo.
Nếu có vẻ như bạn thực sự cần xóa tệp đang được sử dụng bởi một quy trình khác, tôi khuyên bạn nên xem xét lại vấn đề thực tế trước khi xem xét bất kỳ giải pháp nào.
Xin lưu ý nhận xét MSDN này: 'MOVEFILE_DELAY_UNTIL_REBOOT' -" ... Giá trị này chỉ có thể được sử dụng nếu quá trình nằm trong ngữ cảnh của người dùng thuộc nhóm quản trị viên hoặc Tài khoản LocalSystem ... " –
Bạn có thể sử dụng chương trình này, Handle để tìm quy trình nào có khóa trên tệp của bạn. Đó là một công cụ dòng lệnh, vì vậy tôi đoán bạn sử dụng đầu ra từ đó ... Tôi không chắc chắn về việc tìm kiếm nó theo chương trình.
Nếu xóa các tập tin có thể chờ đợi, bạn có thể xác định nó để xóa khi máy tính của bạn bên cạnh khởi động:
Bắt đầu
REGEDT32 (W2K)
hoặcREGEDIT (WXP)
và điều hướng tới:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager
W2K và WXP
W2K:
Sửa
Thêm giá trị gia tăng ...
Data Type:REG_MULTI_SZ
Value Name:PendingFileRenameOperations
OKWXP:
Sửa
New
Multi-String Value
nhập
PendingFileRenameOperations
Trong khu vực Dữ liệu, nhập
"\??\" + filename
để xóa. Các số LFN có thể được nhập mà không được nhúng trong dấu ngoặc kép. Để xóaC:\Long Directory Name\Long File Name.exe
, nhập dữ liệu sau:\??\C:\Long Directory Name\Long File Name.exe
Sau đó nhấn OK .
"Tên tệp đích" là chuỗi rỗng (không).Nó được nhập như sau:
W2K:
Sửa
Binary
chọn Format dữ liệu: Hex
nhấp chuột ở phần cuối của chuỗi hex
nhập 0000 (bốn số không)
OKWXP:
Nhấp chuột phải vào giá trị
chọn "Sửa đổi dữ liệu nhị phân"
nhấp vào cuối hex vòng
nhập 0000 (bốn số không)
OK
Đóng
REGEDT32/REGEDIT
và khởi động lại để xóa các tập tin.
(shamelessly bị đánh cắp từ some random forum, vì hậu thế của.)
Nếu bạn muốn thực hiện theo chương trình. Tôi không chắc ... và tôi thực sự khuyên bạn nên chống lại nó. Nếu bạn chỉ xử lý sự cố trên máy của mình, SysInternals Process Explorer có thể giúp bạn
Chạy nó, sử dụng lệnh Tìm xử lý (tôi nghĩ rằng nó nằm trong menu tìm hoặc xử lý) và tìm kiếm tên tệp của bạn . Sau khi xử lý (s) được tìm thấy, bạn có thể buộc phải đóng chúng.
Sau đó, bạn có thể xóa tệp và v.v.
Hãy coi chừng, thực hiện điều này có thể khiến chương trình sở hữu tay cầm hoạt động lạ, vì bạn vừa kéo tấm thảm từ dưới nó ra, nhưng nó hoạt động tốt khi bạn gỡ lỗi mã riêng của mình hoặc khi visual studio/windows explorer đang được crap và không phát hành tập tin xử lý ngay cả khi bạn nói với họ để đóng các tập tin lứa tuổi trước đây ... sigh :-)
Ồ, một hack lớn tôi làm việc nhiều năm trước đây, là Windows giành được Không cho phép bạn xóa tệp nhưng nó cho phép bạn di chuyển chúng.
Pseudo-loại-of-code:
mv %WINDIR%\System32\mfc42.dll %WINDIR\System32\mfc42.dll.old
Install new mfc42.dll
Tell user to save work and restart applications
Khi các ứng dụng khởi động lại (lưu ý chúng tôi không cần phải khởi động lại máy), họ nạp mới mfc42.dll
, và tất cả là tốt. Điều đó, cùng với PendingFileOperations
để xóa cái cũ trong lần tiếp theo toàn bộ hệ thống khởi động lại, hoạt động khá tốt.
Phương pháp điển hình như sau. Bạn đã nói rằng bạn muốn làm điều này trong C# vì vậy ở đây đi ...
- Nếu bạn không biết quy trình nào đã khóa tệp, bạn sẽ cần kiểm tra danh sách xử lý của từng quy trình và truy vấn từng xử lý để xác định xem nó có nhận dạng tệp bị khóa hay không. Làm điều này trong C# có thể sẽ yêu cầu P/Invoke hoặc một trung gian C++/CLI để gọi các API gốc mà bạn sẽ cần.
- Khi bạn đã tìm ra quy trình nào bị khóa, bạn sẽ cần phải tiêm một DLL gốc nhỏ vào quy trình một cách an toàn (bạn cũng có thể tiêm một DLL được quản lý, nhưng điều này sẽ phức tạp hơn) phải bắt đầu hoặc đính kèm với thời gian chạy .NET).
- Đó bootstrap DLL sau đó đóng tay cầm sử dụng CloseHandle vv
Về cơ bản: Cách để mở khóa một "khóa" tập tin là phải tiêm một tập tin DLL vào không gian địa chỉ vi phạm quy trình và đóng nó lại chính mình. Bạn có thể thực hiện việc này bằng mã gốc hoặc mã được quản lý. Không có vấn đề gì, bạn sẽ cần một số lượng nhỏ mã gốc hoặc ít nhất là P/Gọi vào cùng một.
liên kết hữu ích:
Chúc may mắn!
Điều này có vẻ đầy hứa hẹn. Một cách giết chết các tập tin xử lý ....
http://www.timstall.com/2009/02/killing-file-handles-but-not-process.html
Sử dụng những lời khuyên Orion Edwards Tôi đã tải về Sysinternals Process Explorer do đó cho phép tôi khám phá ra rằng các tập tin tôi đã gặp khó khăn xóa được trong thực tế được tổ chức không bởi đối tượng Excel.Applications
tôi nghĩ, nhưng đúng hơn là mã C# của tôi gửi mã thư đã tạo ra một đối tượng Đính kèm để mở một tay cầm cho tệp này đang mở.
Khi tôi thấy điều này, tôi khá đơn giản được gọi là phương pháp vứt bỏ đối tượng Đính kèm và tay cầm đã được giải phóng.
Trình khám phá Sysinternals cho phép tôi khám phá điều này được sử dụng cùng với trình gỡ lỗi trực quan Studio 2005.
Tôi rất khuyên bạn nên sử dụng công cụ này!
Đây cũng chính là vấn đề của tôi. Cảm ơn bạn +1 – Fandango68
Bạn có thể sử dụng mã mà bạn cung cấp các đường dẫn tập tin đầy đủ, và nó sẽ trả về một List<Processes>
bất cứ điều gì khóa tập tin đó:
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;
}
}
Sau đó, lặp danh sách chương trình và đóng chúng lại và xóa các tập tin :
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);
}
Và tùy thuộc vào nếu tập tin trên máy tính cục bộ:
public static void localProcessKill(string processName)
{
foreach (Process p in Process.GetProcessesByName(processName))
{
p.Kill();
}
}
hoặc máy tính mạng:
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();
}
}
}
Tài liệu tham khảo:
How do I find out which process is locking a file using .NET?
- 1. Tệp được sử dụng bởi một quy trình khác
- 2. C# File.Delete, tệp đang được sử dụng bởi một quy trình khác
- 3. Đọc tệp nhật ký bị khóa bởi ứng dụng khác
- 4. Linux: Làm cách nào để tìm hiểu xem tệp đã được cập nhật bởi một quy trình khác chưa?
- 5. Tệp đang được sử dụng bởi một quy trình khác sau khi tệp File.Copy
- 6. Làm cách nào để xóa một tệp khi đóng trong C++ trên Linux?
- 7. Làm cách nào để biết quy trình nào đang sử dụng một tệp nhất định?
- 8. Cách mở khóa các tệp máy chủ TFS bị khóa bởi nhà phát triển khác trong máy khác
- 9. Bạn sẽ làm gì nếu tệp trong TFS bị khóa bởi người khác?
- 10. Đọc một tệp được sử dụng bởi một quy trình khác
- 11. ngoại lệ C#. Tệp đang được sử dụng bởi một quy trình khác
- 12. Làm cách nào để ẩn một quy trình trong Trình quản lý Tác vụ trong C#?
- 13. Cách dễ nhất để đọc tệp văn bản bị khóa bởi ứng dụng khác
- 14. Làm cách nào để xóa tệp được trỏ bởi FILE * trong C?
- 15. Làm cách nào để bắt đầu Quy trình bị ẩn?
- 16. Cách đảm bảo rằng một Cổng nhất định không bị chiếm đóng bởi bất kỳ quy trình nào khác
- 17. FileStream: được sử dụng bởi một lỗi quy trình khác
- 18. Cách tìm hiểu quy trình nào có thư mục hoặc tệp bị khóa?
- 19. Làm cách nào để có danh sách các tệp được tải bởi quy trình của tôi?
- 20. Java I/O: Đảm bảo tệp không bị khóa bởi một quy trình khác trước khi bất kỳ hoạt động r/w nào
- 21. Xóa các tệp bị ẩn đệ quy
- 22. Quá trình không thể truy cập tệp vì nó đang được sử dụng bởi một quy trình khác
- 23. Làm cách nào để mở khóa một tệp mạnh mẽ trong C#?
- 24. Lỗi 32, Python, tệp đang được sử dụng bởi một quy trình khác
- 25. Không thể truy cập tệp vì nó đang được sử dụng bởi một quy trình khác
- 26. Cơ sở dữ liệu đang được sử dụng bởi một quy trình khác ... nhưng quy trình nào?
- 27. quy trình con: xóa quy trình con trong Windows
- 28. Làm thế nào tôi có thể gửi khóa F4 đến một quy trình trong C#?
- 29. Các cách thoát khác nhau của quy trình trong C++
- 30. Quá trình không thể truy cập tệp, vì nó đang được sử dụng bởi một quy trình khác
liên quan - http://stackoverflow.com/questions/1760481/closing-open-files-using -c-sharp/41902677 # 41902677 – vapcguy