Windows:执行后删除EXE



我正在C#中开发一个应用程序,它可以做以下事情:

  1. 将EXE写入磁盘
  2. 通过Process.Start()执行EXE

我现在正在努力确保EXE一旦关闭就会被删除。最简单的方法是在使用File.Create创建EXE时设置FileOptions.DeleteOnClose参数。

但是,这意味着EXE在使用中无法执行。关闭文件句柄后,EXE将立即被删除,然后才能执行。

有没有办法在我的应用程序中保留对EXE的"弱引用",它不会锁定文件并允许执行它?或者,有没有办法在文件句柄仍然打开的情况下解锁EXE执行?我还缺少其他明显的解决方案吗?

澄清A:我知道其他删除正在使用的文件的方法,这些方法最终会删除文件(例如,在重新启动时)。然而,我正在寻找一种方法,在文件开始执行后立即删除文件,这是由操作系统处理的(例如,当运行一个首先执行文件然后删除它的批处理时,如果批处理作业终止,文件将保留在磁盘上)。

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

更多详细信息请点击此处。

如果你想在内存中加载/执行任何exe,你可以使用Nebbett的Shuttle方法,但你需要用C/C++编写代码,并从C#调用它。

此外,微软似乎不喜欢它(安全问题),我认为你不能只从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.
}

注意:Console Application在我的低端计算机中的此解决方案占用了50%的CPU。

最新更新