1

ゲームの mod のランチャーであるプログラムがあります。ランチャーは、私自身を含め、ほとんどの人にとって機能しますが、一部の人にとっては奇妙なバグがあり、それを修正するのに本当に苦労し、さらに私を完全に精神的に駆り立てます!

基本的な考え方は、私の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()、ファイルを移動しようとした後に実際に移動されたことを確認するための使用が含まれていました。ロギングには、移動の試行と、ファイルが実際に移動されたかどうかを確認するためのこのチェックの結果が記録されていました。ゲームを起動する前に、特定のファイルが実際に必要な場所にあることを具体的にチェックする特定の if ステートメントを Process.Start 関数に追加しました。最後に、起動する前に、mod ファイルがあるはずのフォルダー内のすべてのファイルがログに書き込まれます。

ランチャーが機能しなかったユーザーからのすべてのログには、プログラムがファイルを移動しようとしたときにエラーがスローされず、ファイルが実際に移動されたことを確認すると、ファイルがそこにあるように見えるという共通点が 1 つあります。しかし、必要なディレクトリ内のすべてのファイルがログに書き込まれるポイントに到達すると、必要な 30 以上の mod ファイルのうちの 1 つだけがディレクトリにあるように見えます。

出力ログの例は次のようになります。

ファイルの移動: modfile1.txt

ファイルが移動しようとした場所かどうかを確認しています:はい

ファイルの移動: modfile2.txt

ファイルが移動しようとした場所かどうかを確認しています:はい

ファイルの移動: modfile3.txt

ファイルが移動しようとした場所かどうかを確認しています:はい

ディレクトリ内のすべてのファイルを書き出す:

normalgamefile1.txt

normalgamefile2.txt

normalgamefile3.txt

modfile1.txt

これを見て、移動したのは常に 1 つのファイルのみであり、他のファイルは移動していないことに気付いた後、プログラムはファイルが本来あるべき場所にあると認識していたことに気づき、混乱が始まりました。

これは、ファイルを読み取ってファイルの種類を確認するメソッドです。

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 ステートメントを使用していることに注意してください。ただし、この修正をしばらくテストすることはできません)。

SO、ここまで読んでくれてありがとう、私の質問は..

まず、何が問題なのか分かりますか?まだファイルが開いていて閉じていないため、ファイルを移動できreaderない可能性があります.IF SOの場合、なぜ私と他のほとんどの人にとっては完全に機能するのに、一部の人にとっては機能しないのですか? ファイルがまだ別の場所で使用されている場合、エラーがスローされるのでしょうか?

プログラムが管理者権限で実行されていることを確認するなど、すべての簡単なことを確認しました。

助けてくれてありがとう!


編集

コメントで尋ねられたように、これは私のチェックとログが追加されたバージョンのコードです。簡単なことなので省略しました。ログは単純に文字列に追加され、すべてが完了すると文字列がファイルに出力されます。

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