1

私が開発した Web サイトのテストを支援する C# プログラムを作成していて、問題が発生しています。目標は、プログラムが私のウェブサイトのさまざまなアカウントを関連する Cookie と共に保存して、テストのために自動的にログインできるようにすることです。現在、ブラウザーの自動化と Cookie の保存に Playwright を使用しています (これに関しては問題ありません)。ただし、私の問題は、Cookie を保存した後に FileSystemWatcher が起動しないという事実に起因しているようです。

私の目標は、新しいアカウントを追加するたびに、保存したアカウントでプログラム インターフェイスを更新することです。これを行うために、FileSystemWatcher を使用して、ファイルからすべてのユーザー アカウントをリロードする関数を呼び出しています。

FileSystemWatcher を作成するための私の関数は次のようになります。

private string filesPath = @"" + Path.GetDirectoryName(Application.ExecutablePath) + "\\inc";

private void CreateFileWatcher()
{
    FileSystemWatcher fsWatcher = new FileSystemWatcher(filesPath, "accounts.dat");
    fsWatcher.NotifyFilter = NotifyFilters.LastWrite;

    fsWatcher.Changed += new FileSystemEventHandler((object s, FileSystemEventArgs e) =>
    {
        // Load accounts
    });

    fsWatcher.EnableRaisingEvents = true;
}

その「accounts.dat」ファイルを具体的に監視したいので、コードからわかるようにフィルターとして追加しました。

新しいアカウントを追加する場合、関数は次のようになります。

private void CreateAccount() {
    Dictionary<Guid, Account> accounts;

    Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
    BinaryFormatter bf = new BinaryFormatter();

    try
    {
        accounts = (Dictionary<Guid, Account>)bf.Deserialize(stream);
        accounts.Add(account.UUID, account);
    }
    catch
    {
        accounts = new Dictionary<Guid, Account>();
        accounts.Add(account.UUID, account);
    }
    stream.Close();

    stream = new FileStream(fileName, FileMode.Truncate, FileAccess.Write);
    bf.Serialize(stream, accounts);
    stream.Close();

    // Then I call my login function that logs the account in and saves the cookies
}

ログインするための私の機能は次のとおりです。

public static Task Login(Account account, string url) {
    try
    {
        using var playwright = await Playwright.CreateAsync();
        await using var browser = await playwright.Chromium.LaunchAsync(new()
        {
            Headless = false,
        });
        await using var context = await browser.NewContextAsync(new()
        {
            ViewportSize = new ViewportSize() { Height = 450, Width = 500 }
        });

        // Create page
        var page = await context.NewPageAsync();
        await page.GotoAsync(url);

        // Sign in
        await Login(page, account);

        // Save auth state
        string cookies = await context.StorageStateAsync();

        // Write cookies
        await WriteCookies(cookies, account);
    }
    catch (Exception e)
    {
        // Log to my logfile
    }
}

最後に、Cookie を保存するための関数は次のとおりです。

public static async Task WriteCookies(string cookies, Account account) {
    // Create list of accounts
    Dictionary<Guid, string> sessions;

    Stream stream = new FileStream(sessionsFile, FileMode.Open, FileAccess.Read);
    BinaryFormatter bf = new BinaryFormatter();

    try
    {
        sessions = (Dictionary<Guid, string>)bf.Deserialize(stream);
        sessions.Add(account.UUID, cookies);
    }
    catch
    {
        sessions = new Dictionary<Guid, string>();
        sessions.Add(account.UUID, cookies);
    }
    stream.Close();

    stream = new FileStream(sessionsFile, FileMode.Truncate, FileAccess.Write);
    bf.Serialize(stream, sessions);
    stream.Close();
}

コードからわかるように、各セッションはアカウントを介してユーザー アカウントに関連付けられているGuidため、後でアカウントに関連する正しいセッションに簡単にアクセスできます。この問題は、Cookie の書き込み関数が非同期であったため、FileSystemWatcher がスローされていたため、セッションとアカウントを分離してこれを修正しようとしたが、うまくいかなかったことが原因であると考えました。何が間違っているのかわかりませんが、アカウントが最初に作成されたときにイベントが発生するようです.Cookieを書き込むと、フォームを手動でリロードするまで二度と発生しません. 助けていただければ幸いです。

Truncateまた、現在、ファイルを開いて既存のデータを取得し、閉じてから、毎回ファイルをクリアしたいモードで再度開いているので、新しいオブジェクトをリストに追加するより良い方法をお勧めする場合は、それらを聞いてください。

ありがとう!

4

1 に答える 1