【原创】 c#单文件绿色资源自更新

先引用dnlib.dll 更新程序先fody成一个文件

放置主程序资源文件 更新程序.exe

  1 #region
  2 
  3 using System;
  4 using System.Diagnostics;
  5 using System.IO;
  6 using System.Linq;
  7 using System.Runtime.InteropServices;
  8 using System.Text;
  9 using dnlib.DotNet;
 10 using dnlib.DotNet.Resources;
 11 using dnlib.DotNet.Writer;
 12 using dnlib.IO;
 13 
 14 #endregion
 15 
 16 namespace 更新程序
 17 {
 18     internal class Program
 19     {
 20         private static string FileExt { get; set; }
 21         private static string Filename { get; set; }
 22         private static void Main()
 23         {
 24             FileExt = Path.GetExtension(Properties.Resources.FileName);
 25             Filename = Path.GetFileNameWithoutExtension(Properties.Resources.FileName);
 26             UpDateResx();
 27             DeleteItself();
 28         }
 29 
 30         public static void UpDateResx()
 31         {
 32             string  path = Properties.Resources.FileName;
 33             string resxName = Properties.Resources.Name;
 34             string resxValue = Properties.Resources.Value;
 35             var processes = Process.GetProcesses();
 36             Stopwatch st = new Stopwatch();
 37             st.Start();
 38 
 39             while (processes.FirstOrDefault(s => Filename == s.ProcessName) != null)
 40             {
 41                 if (st.Elapsed > TimeSpan.FromSeconds(10))
 42                 {
 43                     return;
 44                 }
 45             }
 46 
 47 
 48             ModuleDefMD module = ModuleDefMD.Load(path);
 49 
 50             EmbeddedResource resx =
 51                 (EmbeddedResource) module.Resources.Find(module.Assembly.Name + ".Properties.Resources.resources");
 52 
 53             ResourceElementSet elementSet = ResourceReader.Read(module, resx.Data);
 54             try
 55             {
 56                 ResourceElement element = elementSet.ResourceElements.First(s => s.Name == resxName);
 57                 element.ResourceData = new BuiltInResourceData(ResourceTypeCode.String, resxValue);
 58                 elementSet.Add(element);
 59 
 60                 MemoryStream ms = new MemoryStream();
 61                 ResourceWriter.Write(module, ms, elementSet);
 62                 resx.Data = new MemoryImageStream(0, ms.GetBuffer(), 0, ms.GetBuffer().Length);
 63 
 64                 if (module.IsILOnly)
 65                     module.Write(Filename+"_tmp"+FileExt, new ModuleWriterOptions(module));
 66                 else
 67                     module.NativeWrite(Filename + "_tmp" + FileExt);
 68             }
 69             catch (Exception e)
 70             {
 71                 Console.WriteLine(e);
 72                 return;
 73             }
 74             module.Dispose();
 75 
 76 
 77         }
 78 
 79 
 80         /// <summary>
 81         ///     删除程序自身(本文地址:http://www.cnblogs.com/Interkey/p/DeleteItself.html)【推荐】
 82         /// </summary>
 83         private static void DeleteItself()
 84         {
 85             string selfName = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
 86             string vBatFile = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName) + "\\DeleteItself.bat";
 87             using (StreamWriter vStreamWriter = new StreamWriter(vBatFile, false, Encoding.Default))
 88             {
 89                 vStreamWriter.Write(":move\r\n" +
 90                                     $" move /Y {Filename}_tmp{FileExt} {Filename}{FileExt}  \r\n" +
 91                                     $"if exist {Filename}_tmp{FileExt} goto move\r\n" +
 92                                     ":del\r\n" +
 93                                     $" del {selfName}\r\n" +
 94                                     $"if exist {selfName} goto del\r\n" +
 95                                     "del %0\r\n");
 96             }
 97 
 98             //************ 执行批处理
 99             WinExec(vBatFile, 0);    
100             //************ 结束退出
101             Environment.Exit(0);
102         }
103 
104 
105         [DllImport("kernel32.dll")]
106         public static extern uint WinExec(string lpCmdLine, uint uCmdShow);
107     }
108 }

主程序结束时中使用下列方法自更新资源

 1  public static void WriteUpdate(string name,string value)
 2         {
 3             string selfName =Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
 4 
 5             ModuleDefMD module = ModuleDefMD.Load(Properties.Resources.更新程序);
 6 
 7             EmbeddedResource resx =
 8                 (EmbeddedResource)module.Resources.Find(module.Assembly.Name + ".Properties.Resources.resources");
 9 
10             ResourceElementSet elementSet = dnlib.DotNet.Resources.ResourceReader.Read(module, resx.Data);
11             try
12             {
13                 ResourceElement element = elementSet.ResourceElements.First(s => s.Name == "FileName");
14                 element.ResourceData = new BuiltInResourceData(ResourceTypeCode.String, selfName);
15                 elementSet.Add(element);
16 
17                 ResourceElement element1 = elementSet.ResourceElements.First(s => s.Name == "Name");
18                 element1.ResourceData = new BuiltInResourceData(ResourceTypeCode.String, name);
19                 elementSet.Add(element1);
20 
21                 ResourceElement element2 = elementSet.ResourceElements.First(s => s.Name == "Value");
22                 element2.ResourceData = new BuiltInResourceData(ResourceTypeCode.String, value);
23                 elementSet.Add(element2);
24 
25 
26                 MemoryStream ms = new MemoryStream();
27                 dnlib.DotNet.Resources.ResourceWriter.Write(module, ms, elementSet);
28                 resx.Data = new MemoryImageStream(0, ms.GetBuffer(), 0, ms.GetBuffer().Length);
29 
30                 if (module.IsILOnly)
31                     module.Write("更新程序.exe", new ModuleWriterOptions(module));
32                 else
33                     module.NativeWrite("更新程序.exe");
34             }
35             catch (Exception e)
36             {
37                 Console.WriteLine(e);
38                 return;
39             }
40             module.Dispose();
41             ProcessStartInfo psi = new ProcessStartInfo("更新程序.exe");
42             psi.WindowStyle = ProcessWindowStyle.Hidden;
43             psi.CreateNoWindow = true;
44             Process.Start(psi);
45             Environment.Exit(0);
46         }