1

我有一个程序是游戏模组的启动器。启动器适用于大多数使用它的人,包括我自己,但对于一些人来说,有一个奇怪的错误让我很难修复它,而且更让我精神崩溃!

基本思想是我的mod文件包含在一个文件夹中,启动器遍历这些文件,读取文件的某个字节并根据结果移动文件,或者移动文件并将一些文本写入某个文件,然后启动游戏。看似简单。

主启动函数如下所示:

private void Launch()
    {
        using (StreamWriter writer = new StreamWriter(userScriptPath, false, Encoding.Unicode))
        {
            foreach (string file in Directory.GetFiles(modFolderPath + "\\Files\\", "*.pack"))
            {
                int p = GetPackType(file);

                if (p == 3)
                {
                    if (File.Exists(modFolderPath + "\\Files\\" + Path.GetFileName(file)))
                    {
                        File.Move(modFolderPath + "\\Files\\" + Path.GetFileName(file), dataPath + "\\" + Path.GetFileName(file));
                    }

                    writer.WriteLine("mod \"" + Path.GetFileName(file) + "\";");
                }
                else if (p == 4)
                {
                    if (File.Exists(modFolderPath + "\\Files\\" + Path.GetFileName(file)))
                    {
                        File.Move(modFolderPath + "\\Files\\" + Path.GetFileName(file), dataPath + "\\" + Path.GetFileName(file));
                    }
                }
            }
        }

        Process game = Process.Start(gamePath);

        // There is code here that waits for a minute until the game process is actually found, incase its slow starting up

        game.WaitForExit();
        RestorePacks(); // <- Method to put back the files after finishing
    }

一些用户遇到的问题是,在启动 mod 时游戏会启动,但由于游戏仍处于正常状态,启动器似乎没有移动文件,很难确定发生这种情况的确切原因我无法在他们的计算机上调试它,并且该程序对我和我的所有测试用户都运行良好。

为了尝试找出发生了什么,我在启动器中添加了一些检查和一些日志记录,这样如果启动器不起作用,我至少知道原因。(请注意,即使它不起作用,也不会为用户抛出错误)

我添加的检查包括File.Exists()在尝试移动文件以确保它被实际移动之后使用,日志记录了移动尝试以及此检查的结果以查看文件是否实际移动。我什至在 Process.Start 函数中添加了一个特定的 if 语句,特别是在启动游戏之前检查某个文件确实位于所需的位置。最后,在启动现在应该将 mod 文件所在的文件夹中的所有文件写入日志之前。

来自启动器不起作用的用户的所有日志共享一个共同点,程序试图移动文件,没有抛出错误,然后在检查文件确实被移动时,文件似乎在那里。但是,当所需目录中的所有文件都写入日志时,目录中似乎只有所需的 30 多个 mod 文件之一。

示例输出日志如下所示:

文件移动:modfile1.txt

检查文件是否是我们试图将其移动到的位置:

文件移动:modfile2.txt

检查文件是否是我们试图将其移动到的位置:

文件移动:modfile3.txt

检查文件是否是我们试图将其移动到的位置:

写出目录中的所有文件:

正常游戏文件1.txt

normalgamefile2.txt

normalgamefile3.txt

modfile1.txt

在看到这一点并注意到它总是只有一个文件移动而没有其他文件之后,而且程序确实认为文件在它们应该在的地方,混乱真的开始了。

这是读取文件以确定它是什么类型的文件的方法:

private int GetPackType(string path)
    {
        FileStream fs = File.OpenRead(path);
        BinaryReader reader = new BinaryReader(fs);
        reader.ReadChars(4);
        int packType = reader.ReadInt32();
        fs.Close();
        fs.Dispose();

        return packType;
    }

正如您可能看到的,我刚刚注意到的是我未能关闭/处置reader,我猜测并且有点希望这可能是我的问题的原因。(请注意,我现在在此方法中使用 Using 语句,但有一段时间无法测试此修复程序)

所以,如果你读到这里,谢谢,我的问题是..

首先你知道问题是什么吗?是否reader仍然可能打开文件并且尚未关闭,因此文件无法移动,如果是这样,那么为什么它对我和大多数其他人完美工作,但对某些人却不行?当然,仍在其他地方使用的文件会引发错误吗?

我已经完成了所有简单的事情,比如确保程序以管理员权限运行等。

非常感谢您的帮助!


编辑

正如评论中所问的,这是添加了我的检查和日志记录的代码版本。简单的东西,这就是我省略它的原因,日志只是添加到一个字符串,然后在所有完成后将字符串打印到文件中。

private void Launch()
    {
        using (StreamWriter writer = new StreamWriter(userScriptPath, false, Encoding.Unicode))
        {
            foreach (string file in Directory.GetFiles(modFolderPath + "\\Files\\", "*.pack"))
            {
                int p = GetPackType(file);

                if (p == 3)
                {
                    if (File.Exists(modFolderPath + "\\Files\\" + Path.GetFileName(file)))
                    {
                        File.Move(modFolderPath + "\\Files\\" + Path.GetFileName(file), dataPath + "\\" + Path.GetFileName(file));
                    }

                    log += "Move File: " + Path.GetFileName(file) + "\r\n";

                    writer.WriteLine("mod \"" + Path.GetFileName(file) + "\";");

                    log += "Write mod line: " + Path.GetFileName(file) + "\r\n";
                }
                else if (p == 4)
                {
                    if (File.Exists(modFolderPath + "\\Files\\" + Path.GetFileName(file)))
                    {
                        File.Move(modFolderPath + "\\Files\\" + Path.GetFileName(file), dataPath + "\\" + Path.GetFileName(file));
                    }

                    log += "Move File: " + Path.GetFileName(file) + "\r\n";
                }

                // Check the file did actually move
                if (File.Exists(dataPath + "\\" + Path.GetFileName(file)) == false)
                {
                    MessageBox.Show("The mod could not launch successfully!\n\nError: Packs failed to move", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                else
                {
                    log += "File Found\r\n";
                }
            }
        }

        if (File.Exists(dataPath + "\\_GreatWar5_DB.pack")) // This pack should always be there if things have worked
        {
            Process game = Process.Start(gamePath);
        }
        else
        {
            MessageBox.Show("The mod could not launch successfully!\n\nError: Data pack missing", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }

        // There is code here waits for a minute until the game process is actually found, incase its slow starting up

        game.WaitForExit();
        RestorePacks(); // <- Method to put back the files after finishing
    }
4

0 回答 0