Windows:执行后删除EXE
Windows: Delete EXE after execution
我正在使用 C# 开发一个应用程序,它执行以下操作:
- 将 EXE 写入磁盘
- 通过
Process.Start()
执行EXE
我现在正在努力确保EXE一旦关闭就会被删除。
最简单的方法是在使用 File.Create
.
创建 EXE 时设置 FileOptions.DeleteOnClose
参数
但是,这意味着EXE在使用时无法执行。一旦文件句柄关闭,EXE在执行前立即被删除。
有没有什么方法可以在我的应用程序中为 EXE 保留一个 "weak reference",它不会锁定文件并允许它执行?或者,有什么方法可以解锁 EXE 以在文件句柄仍然打开的情况下执行?我还缺少其他明显的解决方案吗?
澄清答:我知道其他删除正在使用的文件的方法最终会删除文件(例如在重新启动时)。但是,我正在寻找一种方法,一旦文件开始执行就立即删除文件,该方法由 OS 处理(例如,当 运行 批处理首先执行文件然后删除它时,文件将保留如果批处理作业终止,则在磁盘上)。
澄清 B: 解释大局:应用程序接收并解密可执行文件。解密后,应执行该文件。但是,我想确保 EXE 的解密版本不会保留在磁盘上。理想情况下,我还想防止用户复制解密后的 EXE。但是,由于解密应用程序以同一用户身份运行,因此不可能以真正安全的方式实现,因为两者在系统上具有相同的权限。
你可以使用 Process.WaitForExit:
var process = Process.Start(processPath);
process.WaitForExit();
// File.Delete(processPath); // Not strong enough (thanks to Binary Worrier)
DeleteOrDie(processPath); // Will attempts anything to delete the file.
但它提供了从您编写它的地方复制 exe 的可能性。
一个好的解决方案是 运行 从记忆中。
如果你的目标 exe 是一个 CLR 程序,你可以使用 Assembly.Load 函数:
// read the file and put data in bin
...
Assembly a = Assembly.Load(bin);
MethodInfo method = a.EntryPoint;
if (method == null) throw new NoEntryPointException();
object o = a.CreateInstance(method.Name);
method.Invoke(o, null);
更多详情here。
如果您想 load/execute 内存中的任何 exe,您可以使用 Nebbett’s Shuttle approach but you will need to code it in C/C++ 并从 C# 调用它。
另外,Microsoft 似乎不喜欢它(安全问题),我认为您不能仅从 C# 实现它。好的防病毒软件可能会检测到它。
以一种不是很好但可以给你想要的方式,我建议这个解决方案:
(我使用 Console Application
和此解决方案的一些输入参数)
[1: ] 编写一个函数来检查打开的进程:
/// <summary>
/// Check application is running by the name of its process ("processName").
/// </summary>
static bool IsProcessOpen(string processName)
{
foreach (Processing.Process clsProcess in Processing.Process.GetProcesses())
{
if (clsProcess.ProcessName.ToUpper().Contains(processName.ToUpper()))
return true;
}
return false;
}
[2:]定义一些变量:
static bool IamRunning = true;
static int checkDuration = 1; // in seconds
[3: ] 使用线程进行 运行 循环检查:
Thread t = new Thread(delegate() {
DateTime lastCheck = DateTime.MinValue;
while (IamRunning)
{
var now = DateTime.Now;
int dd = (now.Hour - lastCheck.Hour) * 3600 + (now.Minute - lastCheck.Minute) * 60 + now.Second - lastCheck.Second;
if (dd >= checkDuration)
if (!IsProcessOpen("ProcessName"))
{
delApplication(); // You have a function to delete ...
break;
}
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
[4:]在程序末尾使用循环:
while (t.ThreadState == ThreadState.Running)
{
// just wait.
}
Note: This solution by Console Application
in my low computer have 50% usage of CPU.
我正在使用 C# 开发一个应用程序,它执行以下操作:
- 将 EXE 写入磁盘
- 通过
Process.Start()
执行EXE
我现在正在努力确保EXE一旦关闭就会被删除。
最简单的方法是在使用 File.Create
.
FileOptions.DeleteOnClose
参数
但是,这意味着EXE在使用时无法执行。一旦文件句柄关闭,EXE在执行前立即被删除。
有没有什么方法可以在我的应用程序中为 EXE 保留一个 "weak reference",它不会锁定文件并允许它执行?或者,有什么方法可以解锁 EXE 以在文件句柄仍然打开的情况下执行?我还缺少其他明显的解决方案吗?
澄清答:我知道其他删除正在使用的文件的方法最终会删除文件(例如在重新启动时)。但是,我正在寻找一种方法,一旦文件开始执行就立即删除文件,该方法由 OS 处理(例如,当 运行 批处理首先执行文件然后删除它时,文件将保留如果批处理作业终止,则在磁盘上)。
澄清 B: 解释大局:应用程序接收并解密可执行文件。解密后,应执行该文件。但是,我想确保 EXE 的解密版本不会保留在磁盘上。理想情况下,我还想防止用户复制解密后的 EXE。但是,由于解密应用程序以同一用户身份运行,因此不可能以真正安全的方式实现,因为两者在系统上具有相同的权限。
你可以使用 Process.WaitForExit:
var process = Process.Start(processPath);
process.WaitForExit();
// File.Delete(processPath); // Not strong enough (thanks to Binary Worrier)
DeleteOrDie(processPath); // Will attempts anything to delete the file.
但它提供了从您编写它的地方复制 exe 的可能性。
一个好的解决方案是 运行 从记忆中。
如果你的目标 exe 是一个 CLR 程序,你可以使用 Assembly.Load 函数:
// read the file and put data in bin
...
Assembly a = Assembly.Load(bin);
MethodInfo method = a.EntryPoint;
if (method == null) throw new NoEntryPointException();
object o = a.CreateInstance(method.Name);
method.Invoke(o, null);
更多详情here。
如果您想 load/execute 内存中的任何 exe,您可以使用 Nebbett’s Shuttle approach but you will need to code it in C/C++ 并从 C# 调用它。
另外,Microsoft 似乎不喜欢它(安全问题),我认为您不能仅从 C# 实现它。好的防病毒软件可能会检测到它。
以一种不是很好但可以给你想要的方式,我建议这个解决方案:
(我使用 Console Application
和此解决方案的一些输入参数)
[1: ] 编写一个函数来检查打开的进程:
/// <summary>
/// Check application is running by the name of its process ("processName").
/// </summary>
static bool IsProcessOpen(string processName)
{
foreach (Processing.Process clsProcess in Processing.Process.GetProcesses())
{
if (clsProcess.ProcessName.ToUpper().Contains(processName.ToUpper()))
return true;
}
return false;
}
[2:]定义一些变量:
static bool IamRunning = true;
static int checkDuration = 1; // in seconds
[3: ] 使用线程进行 运行 循环检查:
Thread t = new Thread(delegate() {
DateTime lastCheck = DateTime.MinValue;
while (IamRunning)
{
var now = DateTime.Now;
int dd = (now.Hour - lastCheck.Hour) * 3600 + (now.Minute - lastCheck.Minute) * 60 + now.Second - lastCheck.Second;
if (dd >= checkDuration)
if (!IsProcessOpen("ProcessName"))
{
delApplication(); // You have a function to delete ...
break;
}
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
[4:]在程序末尾使用循环:
while (t.ThreadState == ThreadState.Running)
{
// just wait.
}
Note: This solution by
Console Application
in my low computer have 50% usage of CPU.