FileSystemWatcher 在功能后不会触发 [重复]

Posted

技术标签:

【中文标题】FileSystemWatcher 在功能后不会触发 [重复]【英文标题】:FileSystemWatcher doesn't fire after function [duplicate] 【发布时间】:2022-01-16 10:23:55 【问题描述】:

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

我的目标是在每次添加新帐户时使用我保存的帐户更新我的程序界面。为此,我使用 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 模式重新打开它,因为我想每次都清除文件,所以如果你推荐一种更好的方法来添加新对象我很想听听我的清单。

谢谢!

【问题讨论】:

这可能是一个愚蠢的问题,但您是否检查过文件是否真正得到更新?此外,您是否尝试过查看 FileSystemWatcher 中的所有文件更改事件。 (基本上fsWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size; @NvMat 我觉得没有什么是愚蠢的问题,因为作为程序员,我们总是犯简单的错误,哈哈。但是我也尝试过所有的通知过滤器,但也没有成功。是的,我已经检查了文件,并且每次都正确更新了正确的帐户 我的另一个猜测是 FileSystemWatcher 没有在监视正确的文件,因此仅对路径进行硬编码以检查文件系统监视程序可能会有所帮助。 所以我最近尝试了类似的方法来调试。我只用所有文件的路径创建了观察者。然后我让它在每次触发时注销文件名,但由于某种原因它仍然存在同样的问题。 filesPath 的值是多少?你检查了吗?是相对的吗?如果是这样,您是否尝试在变成绝对路径时注销它? 【参考方案1】:

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

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

【讨论】:

你不知道为什么这也被否决了,我也想试试这个。你是说你建议我将FileSystemWatcher fsWatcher = new FileSystemWatcher(filesPath, "accounts.dat"); 作为私有变量移到班级顶部? 是的。如果你在这样的方法中创建它,它会在不久之后的某个时间点随机消失,只要垃圾收集器认为合适。这肯定是您的问题。 这就是解决方案,谢谢大家的帮助!

以上是关于FileSystemWatcher 在功能后不会触发 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

当从不同的计算机进行更改时,C# FileSystemWatcher 不会在 Nas 文件系统上触发

FileSystemWatcher不会使用'mv'命令检测移动到目录中的文件,也不会在ubuntu上剪切和粘贴

React 功能组件状态变化不会触发子组件重新读取其 props

用FileSystemWatcher对象监控C#目录改变

停止 FileSystemWatcher 后运行另一段代码

Filesystemwatcher 没有在看子目录