Forcefully perform file operations by terminating processes that are using the file or directory.
Only supports windows, and not planned to support linux.
Uses LockChecker to find processes locking files, and will elevate itself if it the process is owned by another user.
See Benchmarks on github pages.
Refer also to 10.4 Example: file deletion in Windows
from "A Philosophy of Software Design", which explains why this is a windows specific problem. Linux does not prevent the user from deleting a file if it is being used, see unlink:
If the name was the last link to a file but any processes still have the file open, the file will remain in existence until the last file descriptor referring to it is closed.
❯ forceops rm .\bin\
[14:55:33 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.dll". Beginning retry 1/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [100724 - myprogram.exe].
[14:55:34 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.dll". Beginning retry 2/10 in 50ms. ForceOps process is not elevated. Found 0 processes to try to kill: [].
❯ forceops rm .\bin\Debug\net6\myprogram.exe
[15:07:39 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.exe". Beginning retry 1/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [115744 - ].
[15:07:39 WRN] Failed to kill process 115744: Access is denied.
[15:07:39 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.exe". Beginning retry 2/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [115744 - ].
[15:07:39 WRN] Failed to kill process 115744: Access is denied.
[15:07:39 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.exe". Beginning retry 3/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [115744 - ].
[15:07:39 WRN] Failed to kill process 115744: Access is denied.
[15:07:39 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.exe". Beginning retry 4/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [115744 - ].
[15:07:39 WRN] Failed to kill process 115744: Access is denied.
[15:07:39 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.exe". Beginning retry 5/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [115744 - ].
[15:07:39 WRN] Failed to kill process 115744: Access is denied.
[15:07:39 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.exe". Beginning retry 6/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [115744 - ].
[15:07:39 WRN] Failed to kill process 115744: Access is denied.
[15:07:39 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.exe". Beginning retry 7/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [115744 - ].
[15:07:39 WRN] Failed to kill process 115744: Access is denied.
[15:07:39 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.exe". Beginning retry 8/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [115744 - ].
[15:07:39 WRN] Failed to kill process 115744: Access is denied.
[15:07:39 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.exe". Beginning retry 9/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [115744 - ].
[15:07:39 WRN] Failed to kill process 115744: Access is denied.
[15:07:39 INF] Could not delete file "C:\Users\user\myprogram\bin\Debug\net6\myprogram.exe". Beginning retry 10/10 in 50ms. ForceOps process is not elevated. Found 1 process to try to kill: [115744 - ].
[15:07:39 WRN] Failed to kill process 115744: Access is denied.
[15:07:39 INF] Exceeded retry count of 10. Failed. ForceOps process is not elevated.
[15:07:39 INF] Unable to perform operation as an unelevated process. Retrying as elevated and logging to "C:\Users\user\AppData\Local\Temp\tmp9C14.tmp".
[15:07:42 INF] Successfully deleted as admin
Currently, only delete
is supported.
Operations like move
and copy
can have similar issues if they are overriding files or the source file is in use. It would be reasonable to support these operations in a similar way.
For copying, consider using Microsoft.Build.CopyOnWrite.
To install the CLI, use the latest exe from releases.
Alternatively, it can be installed as a tool, using the .NET 8 SDK.
dotnet tool install -g forceops
To delete a file:
forceops delete file.txt
See the ForceOps.Lib package.
The easier way is to have an exe target using RelaunchHelpers.RunWithRelaunchAsElevated
, which is shown in ForceOps.DeleteExample:
using ForceOps.Lib;
var fileOrDirectories = args.Select(arg => Path.Combine(Environment.CurrentDirectory, arg)).ToArray();
var forceOpsContext = new ForceOpsContext();
var fileAndDirectoryDeleter = new FileAndDirectoryDeleter(forceOpsContext);
RelaunchHelpers.RunWithRelaunchAsElevated(() =>
{
foreach (var fileOrDirectory in fileOrDirectories)
{
fileAndDirectoryDeleter.DeleteFileOrDirectory(fileOrDirectory, true);
}
}, () => args.ToList(), forceOpsContext);