Unity 程序升级(PC版非热更新)

使用C# Winform做升级程序,在winform启动程序中进行升级信息的检测,最后启动unity程序。

Winform升级程序项目介绍

在博客园找到一个比较合适的升级程序 WINFORM自动更新程序 文章中有源码放在码云上可以下载。按照文章进行配置即可,这里我遇到一些坑,大家可以注意一下。
目录结构
程序目录结构
AutoUpdate与AutoUpdateGUI这两个都是自动升级程序,AutoUpdate是静默升级没有升级界面,AutoUpdateGUI有程序的升级界面可以看到升级程序的下载进度及下载文件的信息,如图
AutoUpdateGUI程序升级界面

  • AutoUpdateLib是升级程序的类库。默认编译生成.exe的可执行文件,可以将输出类型改为类库。
  • 每个项目里都会有一个说明文件,介绍每个项目如何配置与使用。
  • 项目编译生成目录 AutoUpdate-master\AutoUpdate\bin下 将编译成 AutoUpdate.exe,AutoUpdateLib.dll,并与你的主程序放在同一个目录。
  • 本地配置文件updatelist.xml,userconfig.xml 必须存在。服务器配置文件limit.xml,updatelist.xml 必须存在。
  • 限制的做法:服务端配置文件 limit.xml LimitKey,本地配置文件 UserConfig.xml UPDATE_KEY这一点要注意,key不一致不会升级。
  • 升级autoupdate.exe的做法:下载服务端的limit.xml文件看本在的updatelist.xml Autoupdate.exe的版本
    是否与limit.xml中AutoupdateVersion的值一致,不一致就下载autoupdate.exe文件
  • updatelist.xml这里的配置属性要重点弄明白。
  • 如何启动主程序参照 WINFORM自动更新程序 文章。

Window升级程序本地与服务器配置

使用IIS建立服务器升级站点,存放升级文件及配置信息。

所使用的配置文件信息

  • limit.xml
<?xml version="1.0" encoding="utf-8" ?>
<Config>
	<LimitKey>AGD</LimitKey>
  <AutoupdateVersion>2.01.001</AutoupdateVersion>
</Config>
  • UserConfig.xml
<?xml version="1.0" standalone="yes"?>
<Config>
  <UPDATE_KEY>AGD</UPDATE_KEY>
  <IS_UPDATE_AGENT>NO</IS_UPDATE_AGENT>
  <FIXXED_UPDATE_URL>http://193.168.1.88/UnityUpdate</FIXXED_UPDATE_URL>
  <SHARE_FOLDER>http://193.168.1.88/UnityUpdate</SHARE_FOLDER>
  <ONLY_KEEP_ME>YES</ONLY_KEEP_ME>
  <USE_BAT UseBat="NO" StopBat="stop.bat" StartBat="start.bat" AlwaysExecStartBat="Yes" />
</Config>

说明:limit.xml中的LimitKey与UserConfig.xml中的UPDATE_KEY一致。UserConfig.xml中的 USE_BAT为NO。

  • 本地updatelist.xml
<?xml version="1.0" encoding="gb2312"?>
<AutoUpdater>
  <description>iPOS AutoUpdate</description>
  <Updater>
    <Url>http://193.168.1.88/UnityUpdate</Url>
    <NeedUpdate>YES</NeedUpdate>
    <RequiredVersion>9.5.0</RequiredVersion>
    <LastUpdateTime>2016-10-20</LastUpdateTime>
    <Continue>YES</Continue>
    <CheckMd5>NO</CheckMd5>
    <SilentMode>NO</SilentMode>
    <DownloadTimeout>5000</DownloadTimeout>
  </Updater>
  <Application applicationId="CoalStart">
    <EntryPoint>CoalStart.exe</EntryPoint>
    <Location>.</Location>
    <Version>2.06.029</Version>
    <VersionSort>Professional</VersionSort>
    <KillPrograms>CoalStart.exe</KillPrograms>
  </Application>
  <Files>
    <File IsKeyUpt="1" Ver="1.01.002" Name="CoalStart.exe" />
	<File IsKeyUpt="1" Ver="2.01.001" Name="BTLFAutoUpdate.exe" />
	<File IsKeyUpt="1" Ver="1.01.000" Name="build.rar" />
  </Files>
</AutoUpdater>

说明:limit.xml中AutoupdateVersion与本地updatelist.xml中BTLFAutoUpdate的版本一致不需要进行更新。(这里我修改了源码中的升级程序的名称)。升级文件build.rar的版本为1.01.000。

  • 服务器端updatelist.xml的配置信息
<?xml version="1.0" encoding="gb2312"?>
<AutoUpdater>
  <description>iPOS AutoUpdate</description>
  <Updater>
    <Url>http://193.168.1.88/UnityUpdate</Url>
    <!-- ftp://yishion:yishion@localhost/test/ -->
    <NeedUpdate>YES</NeedUpdate>
    <RequiredVersion>9.5.0</RequiredVersion>
    <LastUpdateTime>2016-10-20</LastUpdateTime>
    <Continue>YES</Continue>
    <CheckMd5>NO</CheckMd5>
	<SilentMode>NO</SilentMode>
    <DownloadTimeout>5000</DownloadTimeout>
  </Updater>
  <Application applicationId="CoalStart">
    <EntryPoint>CoalStart.exe</EntryPoint>
    <Location>.</Location>
    <Version>2.06.029</Version>
    <VersionSort>Professional</VersionSort>
    <KillPrograms>CoalStart.exe</KillPrograms>
  </Application>
  <Files>
    <File IsKeyUpt="1" Ver="1.01.002" Name="CoalStart.exe" />
	<File IsKeyUpt="1" Ver="2.01.001" Name="BTLFAutoUpdate.exe" />
	<File IsKeyUpt="1" Ver="1.01.001" Name="build.rar" />
  </Files>
</AutoUpdater>

说明:服务器端的升级文件build.rar的版本号为1.01.001比本地文件的版本号高,在打开主程序就会检测需要更新文件。

升级程序文件目录
  • 服务器目录结构
    在这里插入图片描述
  • 本地目录结构
    在这里插入图片描述

Window升级程序改写

  • 修改启动的主程序
    新建项目CoalStart,在Program.cs类中主程序启动改写为AutoUpdate.InvokeUpdate("CoalStart.exe", "CoalStart", StartMain, args);
  • 修改升级程序的名称为BTLFAutoUpdate。
  1. 修改项目程序集名称
    在这里插入图片描述
  2. 修改AutoUpdateLib类库中InvokeUpdate.cs的InvokeUpdate方法,改为Common.ProgramRunned(Common.CombineDir(Common.AppDir, “BTLFAutoUpdate.exe”), true, false);
  3. 修改AutoUpdateLib类库中的Autoupdating.cs的启动类的名称。
    在这里插入图片描述
    说道这,感觉源码有个小bug ,Autoupdate.exe大小写不一致。这个坑我蹲了好久。
    在这里插入图片描述
  4. 修改AutoUpdateGUI项目的FrmUpdate文件中的CopyFile方法将AUTOUPDATE改为BTLFAUTOUPDATE。
  5. 最后就是配置文件中有关AutoUpdate.exe改为BTLFAutoUpdate.exe就可以了。
  • 加入解压缩功能
    由于我的升级文件是一个unity的构建之后自己压缩的一个压缩包,在升级下载后需要进行自动的文件解压。改写源码,我使用的更新模式非静默更新,因此找到AutoUpdateGUI项目中的FrmUpdate的类文件中DownUpdateFilePart方法加入如下代码。

在这里插入图片描述

				lbState.Text = "解压文件中!";
                string path = System.IO.Directory.GetCurrentDirectory();
                if (!Exists())
                {
                    MessageBox.Show("不支持RAR解压缩");
                    return;
                }
                //解a压1
                try
                {
                    unCompressRAR(path + "\\setup", path+ "\\temp\\Downloads", "build.rar", false);
                    //MessageBox.Show("解压完成!");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }

                lbState.Text = "文件下载并解压完成!";

压缩包解压方法,需要WinRAR.exe电脑上安装一个吧,(为啥不用ICSharpCode.SharpZipLib.dll,zip解压出来少文件,头疼!!)

		/// <summary>
        /// 解压缩文件t
        /// </summary>
        /// <param name="unRarPatch">解压缩后的文件所要存放的路径?</param>
        /// <param name="rarPatch">rar文件所在的路径</param>
        /// <param name="rarName">rar文件名</param>
        /// <param name="deleteFlag"></param>
        /// <returns></returns>
        public static string unCompressRAR(string unRarPatch, string rarPatch, string rarName, bool deleteFlag)
        {
            try
            {

                RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe");
                string str = key.GetValue("").ToString();
                key.Close();
                if (!System.IO.Directory.Exists(unRarPatch))
                {
                    System.IO.Directory.CreateDirectory(unRarPatch);
                }
                string str2 = "x \"" + rarName + "\" \"" + unRarPatch + "\"" + " -y";
                ProcessStartInfo info = new ProcessStartInfo();
                info.FileName = str;
                info.Arguments = str2;
                info.WindowStyle = ProcessWindowStyle.Normal;
                info.WorkingDirectory = rarPatch;
                Process process = new Process();
                process.StartInfo = info;
                process.Start();
                process.WaitForExit();
                process.Close();
                if (deleteFlag && System.IO.File.Exists(rarPatch + @"\" + rarName))
                {
                    System.IO.File.Delete(rarPatch + @"\" + rarName);
                }
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return unRarPatch;
        }
        /// <summary>
        /// 判读是否支持RAR自动解压缩
        /// </summary>
        /// <returns></returns>
        public static bool Exists()
        {
            return !string.IsNullOrEmpty(Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe").GetValue("").ToString());
        }

Winform主程序调用unity程序

Winform升级程序负责文件的检测与unity程序的调用,这时候就需要进行逻辑判断。

  • 美化主启动程序

在这里插入图片描述

  • 改写代码

FrmMain_Shown中开启线程,延时1秒进行升级程序的检测。存在则隐藏主程序,否则开启unity可执行程序。
开启程序使用引入[DllImport("shell32.dll")] public static extern int ShellExecute(IntPtr hwnd, StringBuilder lpszOp, StringBuilder lpszFile, StringBuilder lpszParams, StringBuilder lpszDir, int FsShowCmd);
调用unity可执行程序 ShellExecute(IntPtr.Zero, new StringBuilder("Open"), new StringBuilder("Coal.exe"), new StringBuilder(""), new StringBuilder(@"" + System.IO.Directory.GetCurrentDirectory() + "\\setup\\build"), 1);

  public partial class FrmMain : Form
    {
        SynchronizationContext _syncContext = null;
        public FrmMain()
        {
            InitializeComponent();
            _syncContext = SynchronizationContext.Current;
        }
        [DllImport("shell32.dll")]
        public static extern int ShellExecute(IntPtr hwnd, StringBuilder lpszOp, StringBuilder lpszFile, StringBuilder lpszParams, StringBuilder lpszDir, int FsShowCmd);
      
        /// <summary>
        /// 取去除文件扩展名之后的文件字符串
        /// </summary>
        /// <param name="Prog"></param>
        /// <returns></returns>
        private static string GetShortExec(string Prog)
        {
            int Pos = Prog.LastIndexOf(".");
            return (Pos > 0 ? Prog.Substring(0, Pos) : Prog);
        }
        /// <summary>
        /// 取程序名(去除路径,扩展名)
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        private static string GetFileNameOnly(string fileName)
        {
            return GetShortExec(new System.IO.FileInfo(fileName).Name);
        }
        /// <summary>
        /// 返回进程id, c:\windows\system32\Notepad.exe,notepad.exe
        /// </summary>
        /// <param name="ProgFullName"></param>
        /// <param name="Kill"></param>
        /// <returns></returns>
        public static int ProgramRunned(string ProgName, bool isFullName = false, bool Kill = false)
        {
            string Prog = isFullName ?
                GetFileNameOnly(ProgName)
                : GetShortExec(ProgName);
            System.Diagnostics.Process[] mProcs =
                System.Diagnostics.Process.GetProcessesByName(Prog);
            if (0 == (mProcs?.Length ?? 0)) return 0;
            int pid = 0;
            for (int i = 0, Count = mProcs.Length; i < Count; i++)
            {
                System.Diagnostics.Process proc = mProcs[i];
                bool exists = false;
                if (isFullName)
                    exists = ProgName.Equals(proc.MainModule.FileName, StringComparison.OrdinalIgnoreCase);
                else
                    exists = proc.ProcessName.Equals(ProgName, StringComparison.OrdinalIgnoreCase);
                if (exists)
                {
                    pid = proc.Id;
                    if (Kill)
                    {
                        proc.Kill();
                    }
                }
            }
            return pid;
        }

        public static void Delay(int milliSecond)
        {
            int start = Environment.TickCount;
            while (Math.Abs(Environment.TickCount - start) < milliSecond)//毫秒
            {
                continue;
            }
        }

        void checkOpenForm() {
            Delay(1000);
            int updatecount = ProgramRunned("BTLFAutoUpdate");
         
            if (updatecount > 0)
            {
               
                Thread demoThread = new Thread(new ThreadStart(threadMethod));
                demoThread.IsBackground = true;
                demoThread.Start();//启动线程
            }
            else
            {
                ShellExecute(IntPtr.Zero, new StringBuilder("Open"), new StringBuilder("Coal.exe"), new StringBuilder(""), new StringBuilder(@"" + System.IO.Directory.GetCurrentDirectory() + "\\setup\\build"), 1);
                ProgramRunned("CoalStart", false, true);
            }
        }


        private void threadMethod()
        {
            _syncContext.Post(SetFormHide, "");//子线程中通过UI线程上下文更新UI 
        }

        private void SetFormHide(object obj)
        {
            this.Hide();
        }

        private void FrmMain_Shown(object sender, EventArgs e)
        {
            Thread tOpenForm;
            tOpenForm = new Thread(checkOpenForm);
            tOpenForm.Start();
        }
    }

最终效果

unity PC端启动升级程序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yxlalm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值