WindowForm implements download function for automatic software updates

WindowForm implements download function for automatic software updates

Introduction

First picture:
Insert image description here
Insert image description here
After the download is completed, delete the previous application,
Insert image description here
and then unzip the downloaded package and keep the names in it unchanged (there are shortcuts, otherwise the name has changed and you will not be able to find it)
Insert image description here
. This completes the purpose of the update,** Note: **This is not a hot update solution. Hot update refers to replacing resources and logic within the program.

Analyze requirements

People who have done Unity should be familiar with the Window package. It usually consists of three files as shown below (there may be more parts, but it doesn’t matter).
Insert image description here
Just put the WindowForm tool in the exe directory we packaged.
Insert image description here

Double-click to open Debug
Insert image description here

The picture below is our customized configuration file (according to requirements)
Version is used to compare whether there is a new version for download.
Version is the server download resource name (there is only one rar compression method here)
DeleteOriginal is the original package file (delete all after downloading. That is, the Window package I mentioned at the beginning)
The program will find the upper-level directory of Debug to delete the resource.

The blue rar file in the picture above is the new package downloaded by the server (just manually compress these three files into RAR format).
Insert image description here
After double-clicking Update.exe, my initial introduction section will appear.

The picture below is the configuration file and new package file I uploaded to the server. Don’t worry about the third file, it is what I used for testing before.Insert image description here

Implementation

AppConst.CS

using System.Windows.Forms;
	namespace Update
	{
    
    
    public static class AppConst
    {
    
    

        /// <summary>
        /// 压缩后缀名
        /// </summary>
        public static string CondenseEndName = ".rar";

        /// <summary>
        /// 本地配置文件存放地址
        /// </summary>
        public static string LocalConfigFilePath = Application.StartupPath + "\\config.ini";

        /// <summary>
        /// 服务器配置文件路径
        /// </summary>
        public static string HttpConfigPath = "http://47.101.204.7/Component/FindWord/";
    }
    }

CondenseHelper.cs

using Microsoft.Win32;
	using System;
	using System.Diagnostics;
	using System.IO;

	namespace Update
	{
    
    
    	public class CondenseHelper
    	{
    
    
        /// <summary>
        /// 解压RAR和ZIP文件(需存在Winrar.exe(只要自己电脑上可以解压或压缩文件就存在Winrar.exe))
        /// </summary>
        /// <param name="UnPath">解压后文件保存目录</param>
        /// <param name="rarPathName">待解压文件存放绝对路径(包括文件名称)</param>
        /// <param name="IsCover">所解压的文件是否会覆盖已存在的文件(如果不覆盖,所解压出的文件和已存在的相同名称文件不会共同存在,只保留原已存在文件)</param>
        /// <param name="PassWord">解压密码(如果不需要密码则为空)</param>
        /// <returns>true(解压成功);false(解压失败)</returns>
        public static bool UnRarOrZip(string UnPath, string rarPathName, bool IsCover, string PassWord)
        {
    
    
            if (!Directory.Exists(UnPath))
                Directory.CreateDirectory(UnPath);
            Process Process1 = new Process();
            Process1.StartInfo.FileName = "WinRAR.exe";
            Process1.StartInfo.CreateNoWindow = true;
            string cmd = "";
            if (!string.IsNullOrEmpty(PassWord) && IsCover)
                //解压加密文件且覆盖已存在文件( -p密码 )
                cmd = string.Format(" x -p{0} -o+ {1} {2} -y", PassWord, rarPathName, UnPath);
            else if (!string.IsNullOrEmpty(PassWord) && !IsCover)
                //解压加密文件且不覆盖已存在文件( -p密码 )
                cmd = string.Format(" x -p{0} -o- {1} {2} -y", PassWord, rarPathName, UnPath);
            else if (IsCover)
                //覆盖命令( x -o+ 代表覆盖已存在的文件)
                cmd = string.Format(" x -o+ {0} {1} -y", rarPathName, UnPath);
            else
                //不覆盖命令( x -o- 代表不覆盖已存在的文件)
                cmd = string.Format(" x -o- {0} {1} -y", rarPathName, UnPath);
            //命令
            Process1.StartInfo.Arguments = cmd;
            Process1.Start();
            Process1.WaitForExit();//无限期等待进程 winrar.exe 退出
                                   //Process1.ExitCode==0指正常执行,Process1.ExitCode==1则指不正常执行
            if (Process1.ExitCode == 0)
            {
    
    
                Process1.Close();
                return true;
            }
            else
            {
    
    
                Process1.Close();
                return false;
            }

        }

        /// <summary>
        /// 压缩文件成RAR或ZIP文件(需存在Winrar.exe(只要自己电脑上可以解压或压缩文件就存在Winrar.exe))
        /// </summary>
        /// <param name="filesPath">将要压缩的文件夹或文件的绝对路径</param>
        /// <param name="rarPathName">压缩后的压缩文件保存绝对路径(包括文件名称)</param>
        /// <param name="IsCover">所压缩文件是否会覆盖已有的压缩文件(如果不覆盖,所压缩文件和已存在的相同名称的压缩文件不会共同存在,只保留原已存在压缩文件)</param>
        /// <param name="PassWord">压缩密码(如果不需要密码则为空)</param>
        /// <returns>true(压缩成功);false(压缩失败)</returns>
        public static bool CondenseRarOrZip(string filesPath, string rarPathName, bool IsCover, string PassWord)
        {
    
    
            string rarPath = Path.GetDirectoryName(rarPathName);
            if (!Directory.Exists(rarPath))
                Directory.CreateDirectory(rarPath);
            Process Process1 = new Process();
            Process1.StartInfo.FileName = "WinRAR.exe";
            Process1.StartInfo.CreateNoWindow = true;
            string cmd = "";
            if (!string.IsNullOrEmpty(PassWord) && IsCover)
                //压缩加密文件且覆盖已存在压缩文件( -p密码 -o+覆盖 )
                cmd = string.Format(" a -ep1 -p{0} -o+ {1} {2} -r", PassWord, rarPathName, filesPath);
            else if (!string.IsNullOrEmpty(PassWord) && !IsCover)
                //压缩加密文件且不覆盖已存在压缩文件( -p密码 -o-不覆盖 )
                cmd = string.Format(" a -ep1 -p{0} -o- {1} {2} -r", PassWord, rarPathName, filesPath);
            else if (string.IsNullOrEmpty(PassWord) && IsCover)
                //压缩且覆盖已存在压缩文件( -o+覆盖 )
                cmd = string.Format(" a -ep1 -o+ {0} {1} -r", rarPathName, filesPath);
            else
                //压缩且不覆盖已存在压缩文件( -o-不覆盖 )
                cmd = string.Format(" a -ep1 -o- {0} {1} -r", rarPathName, filesPath);
            //命令
            Process1.StartInfo.Arguments = cmd;
            Process1.Start();
            Process1.WaitForExit();//无限期等待进程 winrar.exe 退出
                                   //Process1.ExitCode==0指正常执行,Process1.ExitCode==1则指不正常执行
            if (Process1.ExitCode == 0)
            {
    
    
                Process1.Close();
                return true;
            }
            else
            {
    
    
                Process1.Close();
                return false;
            }
        }    
    }
    }

ConnectHelper.cs

using System;

	namespace Update
	{
    
    
    public static class ConnectHelper
    {
    
    
        private const int INTERNET_CONNECTION_MODEM = 1;
        private const int INTERNET_CONNECTION_LAN = 2;

        [System.Runtime.InteropServices.DllImport("winInet.dll")]
        private static extern bool InternetGetConnectedState(ref int dwFlag, int dwReserved);

        /// <summary>
        /// 判断本地的连接状态
        /// </summary>
        /// <returns></returns>
        public static bool LocalConnectionStatus()
        {
    
    
            System.Int32 dwFlag = new Int32();
            if (!InternetGetConnectedState(ref dwFlag, 0))
            {
    
    
                //MessageBox.Show("LocalConnectionStatus--未连网!");
                return false;
            }
            else
            {
    
    
                if ((dwFlag & INTERNET_CONNECTION_MODEM) != 0)
                {
    
    
                    //MessageBox.Show("LocalConnectionStatus--采用调制解调器上网。");
                    return true;
                }
                else if ((dwFlag & INTERNET_CONNECTION_LAN) != 0)
                {
    
    
                    //MessageBox.Show("LocalConnectionStatus--采用网卡上网。");
                    return true;
                }
            }
            return false;
        }
    }
    }

DelegateConst.cs

using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text;
	using System.Threading.Tasks;

	namespace Update
	{
    
    
    #region 委托

    /// <summary>
    /// 用于指示文件信息(文件大小,当前下载的数量,当前下载的百分比)
    /// </summary>
    /// <param name="totalNum"></param>
    /// <param name="num"></param>
    /// <param name="proc"></param>
    public delegate void delDownFileHandler(int totalNum, int num, int proc);

    /// <summary>
    /// 文件下载完成之后
    /// </summary>
    /// <param name="isCompleted"></param>
    public delegate void DelComDownFileHandler(bool isCompleted);

    #endregion

}

FileHelper.cs

using System;
	using System.IO;
	using System.Linq;

	namespace Update
	{
    
    
    public static class FileHelper
    {
    
    

        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="oldPath"></param>
        /// <returns></returns>
        public static string GetCurrentConfigFile(string oldPath)
        {
    
    
            if (!File.Exists(oldPath))
            {
    
    
                return null;
            }
            return File.ReadAllText(oldPath);
        }

        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="path"></param>
        public static void DeleteDir(string file)
        {
    
    

            try
            {
    
    

                //去除文件夹和子文件的只读属性
                //去除文件夹的只读属性
                System.IO.DirectoryInfo fileInfo = new DirectoryInfo(file);
                fileInfo.Attributes = FileAttributes.Normal & FileAttributes.Directory;

                //去除文件的只读属性
                System.IO.File.SetAttributes(file, System.IO.FileAttributes.Normal);

                //判断文件夹是否还存在
                if (Directory.Exists(file))
                {
    
    

                    foreach (string f in Directory.GetFileSystemEntries(file))
                    {
    
    

                        if (File.Exists(f))
                        {
    
    
                            //如果有子文件删除文件
                            File.Delete(f);
                            Console.WriteLine(f);
                        }
                        else
                        {
    
    
                            //循环递归删除子文件夹
                            DeleteDir(f);
                        }

                    }

                    //删除空文件夹

                    Directory.Delete(file);

                }

            }
            catch (Exception ex) // 异常处理
            {
    
    
                Console.WriteLine(ex.Message.ToString());// 异常信息
            }

        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="file"></param>
        public static void DeleteFile(string file)
        {
    
    
            if (file != null)
            {
    
    
                File.Delete(file);
            }
        }

        /// <summary>
        /// 删除文件夹或者文件
        /// </summary>
        /// <param name="directory"></param>
        /// <param name="DeleteOriginal"></param>
        public static void DeleteFiles(string directory, string[] DeleteOriginal)
        {
    
    
            for (int i = 0; i < DeleteOriginal.Length; i++)
            {
    
    
                if (DeleteOriginal[i].Contains('.'))
                {
    
    
                    DeleteFile(directory + DeleteOriginal[i]);
                }
                else
                {
    
    
                    DeleteDir(directory + DeleteOriginal[i]);
                }
            }
        }
    }
    }

INIParser.cs

/*******************************
	Version: 1.0
	Project Boon
	*******************************/

	using System;
	using System.Collections.Generic;
	using System.Globalization;
	using System.IO;
	using System.Text;

	public class INIParser
	{
    
    
    #region "Declarations"

    // *** Error: In case there're errors, this will changed to some value other than 1 ***
    // Error codes: 
    // 1: Null TextAsset
    public int error = 0;

    // *** Lock for thread-safe access to file and local cache ***
    private object m_Lock = new object();

    // *** File name ***
    private string m_FileName = null;
    public string FileName
    {
    
    
        get
        {
    
    
            return m_FileName;
        }
    }

    // ** String represent Ini
    private string m_iniString = null;
    public string iniString
    {
    
    
        get
        {
    
    
            return m_iniString;
        }
        set
        {
    
    
            m_iniString = value;
        }
    }

    // *** Automatic flushing flag ***
    private bool m_AutoFlush = false;

    // *** Local cache ***
    private Dictionary<string, Dictionary<string, string>> m_Sections = new Dictionary<string, Dictionary<string, string>>();
    private Dictionary<string, Dictionary<string, string>> m_Modified = new Dictionary<string, Dictionary<string, string>>();

    // *** Local cache modified flag ***
    private bool m_CacheModified = false;

    #endregion

    #region "Methods"

    // *** Open ini file by path ***
    public void Open(string path)
    {
    
    
        m_FileName = path;
        if (File.Exists(m_FileName))
        {
    
    
            m_iniString = File.ReadAllText(m_FileName);
        }
        else
        {
    
    
            //If file does not exist, create one
            var temp = File.Create(m_FileName);
            temp.Close();
            m_iniString = "";
        }

        Initialize(m_iniString, false);
    }

    public void OpenAdd(string content)
    {
    
    
        m_iniString = content;
        Initialize(m_iniString, false);
    }

    // *** Open ini file from string ***
    public void OpenFromString(string str)
    {
    
    
        m_FileName = null;
        Initialize(str, false);
    }

    // *** Get the string content of ini file ***
    public override string ToString()
    {
    
    
        return m_iniString;
    }

    private void Initialize(string iniString, bool AutoFlush)
    {
    
    
        m_iniString = iniString;
        m_AutoFlush = AutoFlush;
        Refresh();
    }

    // *** Close, save all changes to ini file ***
    public void Close()
    {
    
    
        lock (m_Lock)
        {
    
    
            PerformFlush();

            //Clean up memory
            m_FileName = null;
            m_iniString = null;
        }
    }

    // *** Parse section name ***
    private string ParseSectionName(string Line)
    {
    
    
        if (!Line.StartsWith("[")) return null;
        if (!Line.EndsWith("]")) return null;
        if (Line.Length < 3) return null;
        return Line.Substring(1, Line.Length - 2);
    }

    // *** Parse key+value pair ***
    private bool ParseKeyValuePair(string Line, ref string Key, ref string Value)
    {
    
    
        // *** Check for key+value pair ***
        int i;
        if ((i = Line.IndexOf('=')) <= 0) return false;

        int j = Line.Length - i - 1;
        Key = Line.Substring(0, i).Trim();
        if (Key.Length <= 0) return false;

        Value = (j > 0) ? (Line.Substring(i + 1, j).Trim()) : ("");
        return true;
    }

    // *** If a line is neither SectionName nor key+value pair, it's a comment ***
    private bool isComment(string Line)
    {
    
    
        string tmpKey = null, tmpValue = null;
        if (ParseSectionName(Line) != null) return false;
        if (ParseKeyValuePair(Line, ref tmpKey, ref tmpValue)) return false;
        return true;
    }

    // *** Read file contents into local cache ***
    private void Refresh()
    {
    
    
        lock (m_Lock)
        {
    
    
            StringReader sr = null;
            try
            {
    
    
                // *** Clear local cache ***
                m_Sections.Clear();
                m_Modified.Clear();

                // *** String Reader ***
                sr = new StringReader(m_iniString);


                // *** Read up the file content ***
                Dictionary<string, string> CurrentSection = null;
                string s;
                string SectionName;
                string Key = null;
                string Value = null;
                while ((s = sr.ReadLine()) != null)
                {
    
    
                    s = s.Trim();

                    // *** Check for section names ***
                    SectionName = ParseSectionName(s);
                    if (SectionName != null)
                    {
    
    
                        // *** Only first occurrence of a section is loaded ***
                        if (m_Sections.ContainsKey(SectionName))
                        {
    
    
                            CurrentSection = null;
                        }
                        else
                        {
    
    
                            CurrentSection = new Dictionary<string, string>();
                            m_Sections.Add(SectionName, CurrentSection);
                        }
                    }
                    else if (CurrentSection != null)
                    {
    
    
                        // *** Check for key+value pair ***
                        if (ParseKeyValuePair(s, ref Key, ref Value))
                        {
    
    
                            // *** Only first occurrence of a key is loaded ***
                            if (!CurrentSection.ContainsKey(Key))
                            {
    
    
                                CurrentSection.Add(Key, Value);
                            }
                        }
                    }
                }
            }
            finally
            {
    
    
                // *** Cleanup: close file ***
                if (sr != null) sr.Close();
                sr = null;
            }
        }
    }

    private void PerformFlush()
    {
    
    
        // *** If local cache was not modified, exit ***
        if (!m_CacheModified) return;
        m_CacheModified = false;

        // *** Copy content of original iniString to temporary string, replace modified values ***
        StringWriter sw = new StringWriter();

        try
        {
    
    
            Dictionary<string, string> CurrentSection = null;
            Dictionary<string, string> CurrentSection2 = null;
            StringReader sr = null;
            try
            {
    
    
                // *** Open the original file ***
                sr = new StringReader(m_iniString);

                // *** Read the file original content, replace changes with local cache values ***
                string s;
                string SectionName;
                string Key = null;
                string Value = null;
                bool Unmodified;
                bool Reading = true;

                bool Deleted = false;
                string Key2 = null;
                string Value2 = null;

                StringBuilder sb_temp;

                while (Reading)
                {
    
    
                    s = sr.ReadLine();
                    Reading = (s != null);

                    // *** Check for end of iniString ***
                    if (Reading)
                    {
    
    
                        Unmodified = true;
                        s = s.Trim();
                        SectionName = ParseSectionName(s);
                    }
                    else
                    {
    
    
                        Unmodified = false;
                        SectionName = null;
                    }

                    // *** Check for section names ***
                    if ((SectionName != null) || (!Reading))
                    {
    
    
                        if (CurrentSection != null)
                        {
    
    
                            // *** Write all remaining modified values before leaving a section ****
                            if (CurrentSection.Count > 0)
                            {
    
    
                                // *** Optional: All blank lines before new values and sections are removed ****
                                sb_temp = sw.GetStringBuilder();
                                while ((sb_temp[sb_temp.Length - 1] == '\n') || (sb_temp[sb_temp.Length - 1] == '\r'))
                                {
    
    
                                    sb_temp.Length = sb_temp.Length - 1;
                                }
                                sw.WriteLine();

                                foreach (string fkey in CurrentSection.Keys)
                                {
    
    
                                    if (CurrentSection.TryGetValue(fkey, out Value))
                                    {
    
    
                                        sw.Write(fkey);
                                        sw.Write('=');
                                        sw.WriteLine(Value);
                                    }
                                }
                                sw.WriteLine();
                                CurrentSection.Clear();
                            }
                        }

                        if (Reading)
                        {
    
    
                            // *** Check if current section is in local modified cache ***
                            if (!m_Modified.TryGetValue(SectionName, out CurrentSection))
                            {
    
    
                                CurrentSection = null;
                            }
                        }
                    }
                    else if (CurrentSection != null)
                    {
    
    
                        // *** Check for key+value pair ***
                        if (ParseKeyValuePair(s, ref Key, ref Value))
                        {
    
    
                            if (CurrentSection.TryGetValue(Key, out Value))
                            {
    
    
                                // *** Write modified value to temporary file ***
                                Unmodified = false;
                                CurrentSection.Remove(Key);

                                sw.Write(Key);
                                sw.Write('=');
                                sw.WriteLine(Value);
                            }
                        }
                    }

                    // ** Check if the section/key in current line has been deleted ***
                    if (Unmodified)
                    {
    
    
                        if (SectionName != null)
                        {
    
    
                            if (!m_Sections.ContainsKey(SectionName))
                            {
    
    
                                Deleted = true;
                                CurrentSection2 = null;
                            }
                            else
                            {
    
    
                                Deleted = false;
                                m_Sections.TryGetValue(SectionName, out CurrentSection2);
                            }

                        }
                        else if (CurrentSection2 != null)
                        {
    
    
                            if (ParseKeyValuePair(s, ref Key2, ref Value2))
                            {
    
    
                                if (!CurrentSection2.ContainsKey(Key2)) Deleted = true;
                                else Deleted = false;
                            }
                        }
                    }


                    // *** Write unmodified lines from the original iniString ***
                    if (Unmodified)
                    {
    
    
                        if (isComment(s)) sw.WriteLine(s);
                        else if (!Deleted) sw.WriteLine(s);
                    }
                }

                // *** Close string reader ***
                sr.Close();
                sr = null;
            }
            finally
            {
    
    
                // *** Cleanup: close string reader ***                  
                if (sr != null) sr.Close();
                sr = null;
            }

            // *** Cycle on all remaining modified values ***
            foreach (KeyValuePair<string, Dictionary<string, string>> SectionPair in m_Modified)
            {
    
    
                CurrentSection = SectionPair.Value;
                if (CurrentSection.Count > 0)
                {
    
    
                    sw.WriteLine();

                    // *** Write the section name ***
                    sw.Write('[');
                    sw.Write(SectionPair.Key);
                    sw.WriteLine(']');

                    // *** Cycle on all key+value pairs in the section ***
                    foreach (KeyValuePair<string, string> ValuePair in CurrentSection)
                    {
    
    
                        // *** Write the key+value pair ***
                        sw.Write(ValuePair.Key);
                        sw.Write('=');
                        sw.WriteLine(ValuePair.Value);
                    }
                    CurrentSection.Clear();
                }
            }
            m_Modified.Clear();

            // *** Get result to iniString ***
            m_iniString = sw.ToString();
            sw.Close();
            sw = null;

            // ** Write iniString to file ***
            if (m_FileName != null)
            {
    
    
                File.WriteAllText(m_FileName, m_iniString);
            }
        }
        finally
        {
    
    
            // *** Cleanup: close string writer ***                  
            if (sw != null) sw.Close();
            sw = null;
        }
    }

    // *** Check if the section exists ***
    public bool IsSectionExists(string SectionName)
    {
    
    
        return m_Sections.ContainsKey(SectionName);
    }

    // *** Check if the key exists ***
    public bool IsKeyExists(string SectionName, string Key)
    {
    
    
        Dictionary<string, string> Section;

        // *** Check if the section exists ***
        if (m_Sections.ContainsKey(SectionName))
        {
    
    
            m_Sections.TryGetValue(SectionName, out Section);

            // If the key exists
            return Section.ContainsKey(Key);
        }
        else return false;
    }

    // *** Delete a section in local cache ***
    public void SectionDelete(string SectionName)
    {
    
    
        // *** Delete section if exists ***
        if (IsSectionExists(SectionName))
        {
    
    
            lock (m_Lock)
            {
    
    
                m_CacheModified = true;
                m_Sections.Remove(SectionName);

                //Also delete in modified cache if exist
                m_Modified.Remove(SectionName);

                // *** Automatic flushing : immediately write any modification to the file ***
                if (m_AutoFlush) PerformFlush();
            }
        }
    }

    // *** Delete a key in local cache ***
    public void KeyDelete(string SectionName, string Key)
    {
    
    
        Dictionary<string, string> Section;

        //Delete key if exists
        if (IsKeyExists(SectionName, Key))
        {
    
    
            lock (m_Lock)
            {
    
    
                m_CacheModified = true;
                m_Sections.TryGetValue(SectionName, out Section);
                Section.Remove(Key);

                //Also delete in modified cache if exist
                if (m_Modified.TryGetValue(SectionName, out Section)) Section.Remove(SectionName);

                // *** Automatic flushing : immediately write any modification to the file ***
                if (m_AutoFlush) PerformFlush();
            }
        }

    }

    // *** Read a value from local cache ***
    public string ReadValue(string SectionName, string Key, string DefaultValue)
    {
    
    
        lock (m_Lock)
        {
    
    
            // *** Check if the section exists ***
            Dictionary<string, string> Section;
            if (!m_Sections.TryGetValue(SectionName, out Section)) return DefaultValue;

            // *** Check if the key exists ***
            string Value;
            if (!Section.TryGetValue(Key, out Value)) return DefaultValue;

            // *** Return the found value ***
            return Value;
        }
    }

    // *** Insert or modify a value in local cache ***
    public void WriteValue(string SectionName, string Key, string Value)
    {
    
    
        lock (m_Lock)
        {
    
    
            // *** Flag local cache modification ***
            m_CacheModified = true;

            // *** Check if the section exists ***
            Dictionary<string, string> Section;
            if (!m_Sections.TryGetValue(SectionName, out Section))
            {
    
    
                // *** If it doesn't, add it ***
                Section = new Dictionary<string, string>();
                m_Sections.Add(SectionName, Section);
            }

            // *** Modify the value ***
            if (Section.ContainsKey(Key)) Section.Remove(Key);
            Section.Add(Key, Value);

            // *** Add the modified value to local modified values cache ***
            if (!m_Modified.TryGetValue(SectionName, out Section))
            {
    
    
                Section = new Dictionary<string, string>();
                m_Modified.Add(SectionName, Section);
            }

            if (Section.ContainsKey(Key)) Section.Remove(Key);
            Section.Add(Key, Value);

            // *** Automatic flushing : immediately write any modification to the file ***
            if (m_AutoFlush) PerformFlush();
        }
    }

    // *** Encode byte array ***
    private string EncodeByteArray(byte[] Value)
    {
    
    
        if (Value == null) return null;

        StringBuilder sb = new StringBuilder();
        foreach (byte b in Value)
        {
    
    
            string hex = Convert.ToString(b, 16);
            int l = hex.Length;
            if (l > 2)
            {
    
    
                sb.Append(hex.Substring(l - 2, 2));
            }
            else
            {
    
    
                if (l < 2) sb.Append("0");
                sb.Append(hex);
            }
        }
        return sb.ToString();
    }

    // *** Decode byte array ***
    private byte[] DecodeByteArray(string Value)
    {
    
    
        if (Value == null) return null;

        int l = Value.Length;
        if (l < 2) return new byte[] {
    
     };

        l /= 2;
        byte[] Result = new byte[l];
        for (int i = 0; i < l; i++) Result[i] = Convert.ToByte(Value.Substring(i * 2, 2), 16);
        return Result;
    }

    // *** Getters for various types ***
    public bool ReadValue(string SectionName, string Key, bool DefaultValue)
    {
    
    
        string StringValue = ReadValue(SectionName, Key, DefaultValue.ToString(System.Globalization.CultureInfo.InvariantCulture));
        int Value;
        if (int.TryParse(StringValue, out Value)) return (Value != 0);
        return DefaultValue;
    }

    public int ReadValue(string SectionName, string Key, int DefaultValue)
    {
    
    
        string StringValue = ReadValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
        int Value;
        if (int.TryParse(StringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Value)) return Value;
        return DefaultValue;
    }

    public long ReadValue(string SectionName, string Key, long DefaultValue)
    {
    
    
        string StringValue = ReadValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
        long Value;
        if (long.TryParse(StringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Value)) return Value;
        return DefaultValue;
    }

    public double ReadValue(string SectionName, string Key, double DefaultValue)
    {
    
    
        string StringValue = ReadValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
        double Value;
        if (double.TryParse(StringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Value)) return Value;
        return DefaultValue;
    }

    public byte[] ReadValue(string SectionName, string Key, byte[] DefaultValue)
    {
    
    
        string StringValue = ReadValue(SectionName, Key, EncodeByteArray(DefaultValue));
        try
        {
    
    
            return DecodeByteArray(StringValue);
        }
        catch (FormatException)
        {
    
    
            return DefaultValue;
        }
    }

    public DateTime ReadValue(string SectionName, string Key, DateTime DefaultValue)
    {
    
    
        string StringValue = ReadValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
        DateTime Value;
        if (DateTime.TryParse(StringValue, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.AssumeLocal, out Value)) return Value;
        return DefaultValue;
    }

    // *** Setters for various types ***
    public void WriteValue(string SectionName, string Key, bool Value)
    {
    
    
        WriteValue(SectionName, Key, (Value) ? ("1") : ("0"));
    }

    public void WriteValue(string SectionName, string Key, int Value)
    {
    
    
        WriteValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
    }

    public void WriteValue(string SectionName, string Key, long Value)
    {
    
    
        WriteValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
    }

    public void WriteValue(string SectionName, string Key, double Value)
    {
    
    
        WriteValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
    }

    public void WriteValue(string SectionName, string Key, byte[] Value)
    {
    
    
        WriteValue(SectionName, Key, EncodeByteArray(Value));
    }

    public void WriteValue(string SectionName, string Key, DateTime Value)
    {
    
    
        WriteValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
    }

    #endregion
    }

WebRequestHelper.cs

using System.IO;
	using System.Net;
	using System.Text;

	namespace Update
	{
    
    
    public static class WebRequestHelper
    {
    
    

        /// <summary>
        /// 获取服务器比对信息
        /// </summary>
        /// <returns></returns>
        public static string GetHttpConfigFile(string Url)
        {
    
    
            //Get请求中请求参数等直接拼接在url中
            WebRequest request = WebRequest.Create(Url);

            //返回对Internet请求的响应
            WebResponse resp = request.GetResponse();

            //从网络资源中返回数据流
            Stream stream = resp.GetResponseStream();

            StreamReader sr = new StreamReader(stream, Encoding.UTF8);

            string result = sr.ReadToEnd();

            sr.Dispose();
            stream.Dispose();
            resp.Dispose();

            //将数据流转换文字符串
            return result;
        }
    }
    }

Form1.cs

using System;
	using System.Collections.Generic;
	using System.ComponentModel;
	using System.Data;
	using System.Drawing;
	using System.Linq;
	using System.Net;
	using System.Text;
	using System.Threading;
	using System.Threading.Tasks;
	using System.Windows.Forms;

	namespace Update
	{
    
    
    public partial class Form1 : Form
    {
    
    
        public Form1()
        {
    
    
            InitializeComponent();
            Init();
        }


        WebClient wc = new WebClient();

        /// <summary>
        /// 下载地址
        /// </summary>
        string m_Address = "";

        /// <summary>
        /// 存储位置
        /// </summary>
        string m_SavefileName = "";
        
        /// <summary>
        /// 文件下载名
        /// </summary>
        string DownFileName = "";

        /// <summary>
        /// 所需删除资源名字
        /// </summary>
        string[] deleteFileNames = {
    
     };

        /// <summary>
        /// 初始化
        /// </summary>
        void Init()
        {
    
    
            if (!ConnectHelper.LocalConnectionStatus())
            {
    
    
                MessageBox.Show("请先连接网络!");
            }
            string newConfig = WebRequestHelper.GetHttpConfigFile(AppConst.HttpConfigPath + "config.ini");
            string oldConfig = FileHelper.GetCurrentConfigFile(AppConst.LocalConfigFilePath);
            InitINIParser(newConfig);
            SetDownLoadPath(AppConst.HttpConfigPath + "config.ini", AppConst.LocalConfigFilePath);
            if (newConfig != oldConfig)
            {
    
    
                MessageBox.Show("需要更新!");
                FileHelper.DeleteFile(AppConst.LocalConfigFilePath);
                loadFile();
            }
            else
            {
    
    
                MessageBox.Show("不需要更新!");
            }
        }

        /// <summary>
        /// 初始化数据层
        /// </summary>
        void InitINIParser(string content)
        {
    
    
            INIParser ini = new INIParser();
            ini.OpenAdd(content);
            DownFileName = ini.ReadValue("Setting","NewExeName","");
            deleteFileNames = ini.ReadValue("Setting","DeleteOriginal","").Split(',');
        }

        /// <summary>
        /// 按钮回调
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnDownLoad_Click(object sender, EventArgs e)
        {
    
    
            wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
            wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
            progressBar1.Value = 0;
            label1.Text = "";
            BtnCanel.Enabled = true;
            BtnDownLoad.Enabled = false;

            SetDownLoadPath(AppConst.HttpConfigPath + DownFileName + AppConst.CondenseEndName,Application.StartupPath + "/" + DownFileName + AppConst.CondenseEndName);

            //使用线程启动
            Thread td = new Thread(new ThreadStart(loadFile));
            td.IsBackground = true;
            td.Start();
        }

        /// <summary>
        /// 重置下载路径
        /// </summary>
        /// <param name="address"></param>
        /// <param name="savefileName"></param>
        void SetDownLoadPath(string address,string savefileName)
        {
    
    
            m_Address = address;
            m_SavefileName = savefileName;
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        private void loadFile()
        {
    
    
            if (wc.IsBusy)
            {
    
    
                wc.CancelAsync();
            }
            wc.DownloadFileAsync(new Uri(m_Address), m_SavefileName);
        }

        /// <summary>
        /// 完成更新之后触发的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
    
    
            if (e.Cancelled)
                this.Invoke(new DelComDownFileHandler(comDownFile), new object[] {
    
     false });
            else
                this.Invoke(new DelComDownFileHandler(comDownFile), new object[] {
    
     true });
        }

        /// <summary>
        /// 下载完成取消回调
        /// </summary>
        /// <param name="isCompleted"></param>
        private void comDownFile(bool isCompleted)
        {
    
    
            if (isCompleted)
            {
    
    
                int length = Application.StartupPath.LastIndexOf('\\');
                string path = Application.StartupPath.Substring(0,length);
                FileHelper.DeleteFiles(path + "\\", deleteFileNames);
                MessageBox.Show("已经删除原始资源,请点击确认进行解压!");
                bool isnew = CondenseHelper.UnRarOrZip(path + "\\", Application.StartupPath + "\\" + DownFileName, true,"");
                MessageBox.Show(isnew.ToString());
                label1.Text = "下载完成";
            }
            else
                label1.Text = "下载取消";

            progressBar1.Value = 0;
            BtnDownLoad.Enabled = true;
            BtnCanel.Enabled = false;

        }

        /// <summary>
        /// 更新过程中触发的事件(在线程中不能直接操纵控件,因此用委托执行)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
    
    
            this.Invoke(new delDownFileHandler(processShow), new object[] {
    
     (int)e.TotalBytesToReceive, (int)e.BytesReceived, e.ProgressPercentage });
        }

        /// <summary>
        /// 委托执行  (进度条和字符标识)
        /// </summary>
        /// <param name="totalNum"></param>
        /// <param name="num"></param>
        /// <param name="proc"></param>
        private void processShow(int totalNum, int num, int proc)
        {
    
    
            progressBar1.Maximum = totalNum;
            progressBar1.Value = num;
            label1.Text = "正在下载:" + (num / (1024)).ToString() + "KB/" + (totalNum / 1024).ToString() + "KB   " + proc.ToString() + "%";
        }

        /// <summary>
        /// 点击取消后
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnCanel_Click(object sender, EventArgs e)
        {
    
    
            wc.CancelAsync();
            wc.Dispose();
        }
    }
    }

Summarize

There are many tools used here, and I have encapsulated the tool classes. I will not talk about the control dragging and event processing of WindowForm. You can find cases of click events and Labels on the official website.

Guess you like

Origin blog.csdn.net/qq_42194657/article/details/135438299