24

如何让我的 C# 应用程序自行擦除(自毁)?以下是我认为可能有效的两种方法:

  • 提供另一个删除主程序的程序。那么,这个删除程序是如何删除的呢?
  • 为 CMD 创建一个进程,等待几秒钟然后删除您的文件。在这几秒钟内,您关闭了您的应用程序。

这两种方法似乎效率低下。我有一种感觉,Windows 中有一些内置标志或其他东西允许这些东西。我该怎么做?另外,你能提供一些示例代码吗?

更新:感谢您的所有回答!我要试一试,看看能把我带到哪里。

首先,有些人问我为什么要让我的应用程序这样做。答案如下:几天前,我阅读了 Joel Spolsky 在他的博客上发布的 Aardvark 项目规范,其中提到客户端应用程序将在远程会话后自行删除。我想知道这是如何工作的,以及如果我需要这样做,我如何才能完成这样的壮举。

以下是对建议内容的简要概述:

  • 创建一个注册表项,告诉 Windows 在重新启动时删除文件
  • 使用 ping 命令启动 CMD 等待几秒钟,然后删除文件

当然,正如评论中所述,这两者都有其缺点。

但是,下面概述的这种方法会起作用吗?

有两个可执行文件:Program.exe 和 Cleaner.exe。前者是程序本身,后者是删除 Program.exe 及其本身的应用程序(如果它被加载到内存中,正如我即将解释的那样)。Program.exe(具有依赖项)是否可以将所有没有任何依赖项的 Cleaner.exe加载到内存中并运行它?

如果可以的话,是否可以将 Cleaner.exe 打包到 Program.exe 中,加载到内存中并运行?

4

11 回答 11

20

有一个MoveFileEx API,当给定一个MOVEFILE_DELAY_UNTIL_REBOOT标志时,它将在下次系统启动时删除指定的文件。

于 2010-02-11T14:52:46.633 回答
10

关于这个主题有一篇很棒的CodeProject 文章。

编辑:基本上这是一个简单的 cmd 调用,它将在几秒钟后删除指定的文件。

Process.Start("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del " + Application.ExecutablePath); 
Application.Exit();
于 2010-02-11T14:52:06.883 回答
7

只要您需要在机器上实际存在,您将永远无法保证这将起作用。例如:

  • 如果应用程序在您尝试删除资源时未能及时释放资源怎么办?发生错误,应用程序仍然存在。
  • 从 AV 的角度来看,一个应用程序启动另一个应用程序然后删除第一个应用程序的行为非常可疑。您可能会在用户的机器上触发防御,这可能会杀死试图杀死您的原始应用程序的进程。
  • 如果您在重新启动时执行诸如删除文件之类的操作,那么如果用户在两者之间移动您的文件或制作副本怎么办?它不再在原来的位置,应用程序仍然存在。

如果您的应用程序需要这种级别的安全性,请考虑将其托管在您控制的机器上(例如,通过提供 Web 服务并让存根客户端以这种方式访问​​它)。

在某种程度上相关的说明中,人们也很想推测某人的动机:(1) 需要在某人的机器上实际存在并且 (2) 想要删除应用程序存在的证据。

于 2010-02-11T14:55:42.570 回答
4

对@Bobby 答案的更正,以防人们发现它有用 - 需要引用可执行路径。此外,下面将 cmd.exe 窗口设置为隐藏(否则它会闪烁为黑色控制台窗口)并在不依赖 System.Windows.Forms 程序集(Application 类)的情况下转换为运行。

 
var exepath = Assembly.GetEntryAssembly().Location;              
var info = new ProcessStartInfo("cmd.exe", "/C ping 1.1.1.1 -n 1 -w 3000 > Nul & Del \"" + exepath + "\"");
info.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(info).Dispose();
Environment.Exit(0);
于 2011-04-06T02:22:20.287 回答
1

按 NJ c# 排序,其他代码不起作用,所以如果您创建循环到 del 应用程序的浴文件和批处理文件本身,那么它很简单,如果您不想使用 application.close 方法,您可以使用 takkill 命令杀死进程

        `string delname = "test.cmd";
        string fileurl = Application.ExecutablePath;
        System.IO.StreamWriter file = new System.IO.StreamWriter(delname);
        file.WriteLine(":Repeat");
        file.WriteLine("del \"" + fileurl + "\"");
        file.WriteLine("if exist \"" + fileurl + "\" goto Repeat");
        file.WriteLine("del \"" + delname + "\"");
        file.Close();
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.CreateNoWindow = true;
        startInfo.UseShellExecute = false;
        startInfo.FileName = delname;
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        Process.Start(startInfo);`

` Th3 3e3 一个不是 3d 部分 ov 一个 I5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

于 2011-09-17T20:26:19.823 回答
1

还有FileOptions.DeleteOnClose, 但这需要打开文件以进行写入。您可能可以使用这样的序列(未经测试)来做到这一点:

  • 程序启动为Original.exe,并检测(从它自己的名称)它需要触发自毁功能。
  • Original.exe创建一个新文件Temp.exe并将FileOptions.DeleteOnClose其自己的内容复制到其中,但尚未关闭它
  • Original.exe打开第二个只读句柄Temp.exe并关闭第一个写句柄。只读句柄可以与执行句柄共存,同时保持文件打开以延迟自动删除。
  • Original.exe发射Temp.exe. Temp.exe检测到它已从 temp 目录启动并绕过自毁序列并继续正常操作。
  • Original.exe退出(使用它的只读句柄Temp.exe。)
  • Temp.exe继续运行。当它退出时,该文件Temp.exe将不再被使用,因此它将被自动删除。

编辑#2:实际上我认为这是不可能的,因为它依赖于内核打开带有FILE_SHARE_DELETE标志的文件,这不太可能。

于 2010-02-11T15:02:24.120 回答
1

想想 CMD

int sectosleep = 5000;
string exename = "yourexe.exe";
string location = @"c:\yourexe.exe"
Process.Start("cmd.exe", "/C taskkill /f /im " + exename + " & ping 1.1.1.1 -n 1 -w " + sectosleep + " > Nul & Del /F /Q \"" + location + "\"");

;>

于 2012-10-09T16:17:40.557 回答
0

我知道如果您使用旧版本并选择不更新,reflector 会自行删除。您可能会尝试弄清楚它的作用。我将从 FileMon 开始,看看它是否会产生任何进程来实现这一点。

于 2010-02-11T22:47:39.513 回答
0

适用于 Windows 7 和 8,**确保您以管理员权限运行您的应用程序,否则您将收到错误消息。

这段代码存在于其他地方,所以我不能完全相信我发现我通过添加“Application.Exit();”让它为我工作。

static void autodelete()
{
    string batchCommands = string.Empty;
    string exeFileName = Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", string.Empty).Replace("/", "\\");

    batchCommands += "@ECHO OFF\n";                         // Do not show any output
    batchCommands += "ping 127.0.0.1 > nul\n";              // Wait approximately 4 seconds (so that the process is already terminated)
    batchCommands += "echo j | del /F ";                    // Delete the executeable
    batchCommands += exeFileName + "\n";
    batchCommands += "echo j | del deleteMyProgram.bat";    // Delete this bat file

    File.WriteAllText("deleteMyProgram.bat", batchCommands);

    Process.Start("deleteMyProgram.bat");
    Application.Exit();
}
于 2016-01-16T15:37:09.077 回答
0

这是卸载.exe:

  1. 关闭。

  2. 等待 3 秒。

  3. 如果该任务仍在运行,请尝试终止该任务。

  4. 等待 3 秒。

  5. 删除其中包含 Uninstall.exe 的应用程序目录。

     public void Uninstall()
     {
         var delPath = AppDomain.CurrentDomain.BaseDirectory;
    
         var procId = Process.GetCurrentProcess().Id;
    
         var psi = new ProcessStartInfo
         {
             FileName = "cmd.exe",
             Arguments = $"/C timeout 3 & Taskkill /F /PID {procId} & timeout 3 & rd /s /q \"{delPath}\"",
             CreateNoWindow = true,
             WindowStyle = ProcessWindowStyle.Hidden
         };
         Process.Start(psi);
         Application.Current.Shutdown();
     }
    
于 2020-11-28T04:11:08.107 回答
0

由于我的应用程序(Windows 服务)是通过 Windows Installer 安装的,因此我使用以下方法自行删除:

Dim uninstall_params As String = "/x {MY-PRODUCTS-GUID} /qn /norestart REBOOT=ReallySuppress"
proc.StartInfo = New ProcessStartInfo("msiexec.exe", uninstall_params)
proc.Start()
Environment.Exit(-1)

抱歉——它在 VB 中,但应该很容易转换为 C#。

于 2015-10-17T06:34:27.477 回答