Nullkooland/GBCLV3

Self update failed because the file is in used and being occupied (version after 3.0.10)

Closed this issue · 6 comments

The self update failed on replacing the file because the origin executive is still running and being protected by Windows.
Strange problem: this failure only happened when the file name doesn't have a space. File name like GBCL.exe, GBCL123.exe will get this problem while GBCL -.exe, GBCL 1.exe won't.
It also means 3.11 still have to be download manually or manually replacing the file and rename it.
Maybe you can write a tip on the next release on the release note XD.

Exception trace:

System.IO.IOException: The process cannot access the file because it is being used by another process.
   at System.IO.FileSystem.MoveFile(String sourceFullPath, String destFullPath, Boolean overwrite)
   at System.IO.File.Move(String sourceFileName, String destFileName, Boolean overwrite)
   at System.IO.File.Move(String sourceFileName, String destFileName)
   at GBCLV3.Services.Download.UpdateService.Update()
   at GBCLV3.ViewModels.Windows.UpdateViewModel.Update()
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__139_0(Object state)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
[Launcher Version: 3.0.10.133]

Oh man...This is gonna haunt me for a while...

🤕IDK…… it works fine on my computer.... I admit I am using some sort of “magic code” to do this self replacement trick, and maybe there could be undefined behaviors lurking👾.

Oh man...This is gonna haunt me for a while...

That's a bit sad... Maybe we need more information to solve it...
I don't know it would help but I provide my environment information here:

OS      :Windows 10 Pro 10.0.19041.153, x64, en-CA
Runtime : from .NET Core SDK 3.1.200
EXE Path: C:\Programz\Minecraft\GBCL.exe

Problem signature from reliability monitor:

Problem Event Name:	CLR20r3
Problem Signature 01:	C:\Programz\Minecraft\GBCL.exe
Problem Signature 02:	3.0.10.133
Problem Signature 03:	5e222541
Problem Signature 04:	System.IO.FileSystem
Problem Signature 05:	4.700.20.6702
Problem Signature 06:	e7838d9b
Problem Signature 07:	1a6
Problem Signature 08:	15
Problem Signature 09:	System.IO.IOException
OS Version:	10.0.19041.2.0.0.256.48
Locale ID:	4105
Additional Information 1:	442b
Additional Information 2:	442b26075653361de256bf7ac264eb4b
Additional Information 3:	f542
Additional Information 4:	f542e93d5c29a502e50bd86dce03e428

Maybe using start-up parameters on updating would avoid the undefined behaviours, I think. (Or to say, let's play it safe?)

  1. The update module downloads the update;
  2. The launcher starts the temp file with an argument like -update, if it starts successfully, ends the launcher;
  3. The temp executive does the replacement, and starts the new launcher if everything goes as expected (and can send an argument to tell it "update performed successfully 😁" to do the final cleaning); else if something goes wrong can restore it to the origin status (and tells it "failed ☹");
  4. The new launcher starts and reads the argument, then does the final cleaning.

This maybe safe enough, and it needs a parameter processing - maybe troublesome.

如果不使用单独的update程序的话最简单的方法是使用脚本(cmd/vbs)

CMD示例:

rem gbcl_update.cmd
@echo off
if not exist GBCL.update goto :eof
rem kill all processes (if exist).
taskkill /f /im GBCL.exe
rem delay.
timeout -t 3
rem delete old files.
del /f /q GBCL.exe
rem Replace new file.
ren GBCL.update GBCL.exe
rem run new version.
start GBCL.exe
del /f /q gbcl_update.cmd
rem pause

至于楼上说的利用临时文件传参数的方法也可以(甚至不需要传参,检查自身后缀名即可)
只不过还得主程序启动后再去删除临时文件😂

再贴一个直接创建进程的

        public void Update()
        {
            try
            {
                Process cmd = new Process();
                cmd.StartInfo.FileName = "cmd.exe";
                cmd.StartInfo.Arguments = "/c taskkill /f /im GBCL.exe & timeout -t 3 & del /f /q GBCL.exe & ren GBCL.update GBCL.exe & start GBCL.exe";
                cmd.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
                cmd.StartInfo.UseShellExecute = false;
                cmd.StartInfo.RedirectStandardInput = true;
                cmd.StartInfo.RedirectStandardOutput = true;
                cmd.StartInfo.CreateNoWindow = true;
                cmd.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                cmd.Start();
                Application.Exit();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }