1

我正在创建一个 C# 程序来帮助我测试我开发的网站并且遇到了一些问题。目标是让程序为我的网站存储不同的帐户及其关联的 cookie,以便它可以自动登录以进行测试。现在我正在使用 Playwright 进行浏览器自动化以及 cookie 存储(这些都没有问题)。但是,我的问题似乎源于我保存 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

2

尝试将 FileSystemWatcher 创建为程序级变量,而不是方法中的局部变量,看看是否可以解决问题。

即将 FileSystemWatcher 移至私有局部变量。

于 2021-12-12T18:51:48.090 回答