Windows 版微信降级到 3.9 之后,接管到的文件都变成了只读属性,对须要常常批改微信接管文件进行交换的人来说极为不变。尽管从业务性能上来说,须要频繁交换的文档还是用在线协同(比方腾讯文档)比拟好一些,但从技术的角度来看,应该如何解决这个问题呢?

其实很多技术栈都提供了监听系统文件变动的 API,比方 .NET 就在其 System.IO 命名空间下提供了 FileSystemWatcher 类用于监听文件的变动,包含创立文件、删除文件、文件改名/挪动、文件属性变动等。所以能够应用 C# 和 .NET 疾速的写一个程序用来监听指定文件夹下的新建文件,如果新创建的文件属性是只读,则去掉其只读属性。

第一步,找到微信接管文件的目录。

在微信的「设置→文件治理」中就能够找到,比方 C:\Users\James\Documents\WeChat Files。而后须要辨认这个目录下的用户目录,个别是微信号。点击微信窗口上本人的头像就能够看到。用户目录下的 FileStorage\File 目录就是咱们的目标目录了。

为了帮忙用户疾速定位到这个目录,在假如用户没有手工扭转微信文件目录的状况下,能够这样来查找

  • 通过 Environment.GetFolderPath() 获取到以后用户的“文档”目录;
  • 拼接失去 WeChat Files 目录的门路;
  • 遍历 WeChat Files 目录下的子目录,去掉非凡命名的 All UsersApplet 等,在剩下的子目录中进一步猜想
  • 个别最近拜访过的就是本人的微信账号目录

那么整个猜想目录的过程代码示例如下:

string? GuessReceivePath() {    var docDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);    var wxDir = Path.Combine(docDir, "WeChat Files");    if (!Directory.Exists(wxDir)) { return null; }    HashSet<string> excludes = new(StringComparer.InvariantCulture) {        "All Users",        "Applet"    };    var userDir = Directory.EnumerateDirectories(wxDir)        .Select(it => new FileInfo(it))         // 对每个目录产生 FileInfo 对象(小性能损耗能够疏忽)        .ExceptBy(excludes, fi => fi.Name)      // 去掉特定名称的目录        .OrderByDescending(it => it.LastAccessTime)    // 按最近拜访工夫排序        .FirstOrDefault()                       // 取最最初拜访的那一个,留神有可能是 null        ?.FullName;                             // 获得残缺门路    if (userDir == null) { return null; }    return Path.Combine(userDir, "FileStorage", "File");}

当然,猜想的目录不肯定精确,所以写程序的时候最好能提供给用户一个能够手工批改/设置目录的伎俩,当然别忘了目录的有效性查看(查看目录存在)。

第二步,监听文件创建

监听文件变动只须要新建一个 FileSystemWatcher 对象,设置一些属性即可。

  • 设置 Path 到要监听的目录
  • 设置 .IncludeSubdirectories = true 示意须要监听其子目录
  • 增加 Created 事件在监听到有文件创建时进行解决

示例代码:

var watcher = new FileSystemWatcher() {    IncludeSubdirectories = true,};watcher.Created += (_, e) => { ... };

第三步,对监听到的新建文件进行解决

如果目录下有新创建的文件,下面 Created 事件的 e 参数(FileSystemEventArgs 类型)会携带文件的信息,通过 e.FullPath 能够拿文件的残缺门路。而后应用 FileInfo 判断其是否只读,并解除其只读属性即可:

(_, e) => {    var info = new FileInfo(e.FullPath);    if (info.IsReadOnly) {        info.IsReadOnly = false;        Log($"[去掉只读] {e.Name}");    }};

第四步,监听文件属性变更

理论应用中发现,只有在发送文件的时候,会在微信文件目录创立只读文件。接管文件的时候少数是收到的非只读文件,而后再改成只读属性的。所以还须要监听文件属性的变动。

这样就须要设置 FileSystemWatcher 对象的 NotifyFilter 属性,把 NotifyFilters.Attributes 标记加上。NotifyFilter 的默认值是 LastWriteFileNameDirectoryName,所以批改之后(不须要解决目录)是:

var watcher = new FileSystemWatcher() {    IncludeSubdirectories = true,    NotifyFilter = NotifyFilters.LastWrite        | NotifyFilters.Attributes        | NotifyFilters.FileName,};

此外还须要为 wathcer 增加 Changed 事件的处理函数,在这里查看并批改文件属性:

watcher.Changed += (_, e) => {    new FileInfo(e.FullPath).Also(info => {        if (info.IsReadOnly) {            info.IsReadOnly = false;            Log($"[改为可写] {e.Name}");        }    });};
注:Also 是 Viyi.Util 提供的扩大。

第五步,界面和用户体验

麻雀虽小,但也应该是五脏俱全。外围性能实现之后就须要思考用户操作界面和应用体验上的一些问题。不必思考得太简单,但至多也应该思考:

  • 这是一个常驻类利用,尽管不必注册成零碎服务,但也应该思考应用零碎任务栏图标形式常驻;
  • 容许用户批改门路,开始/进行监听操作;
  • 提供简略的日志性能,让用户晓得它解决了哪些文件。


相干资源

  • 下载编译好的(可能须要自行装置环境)
  • 学习源代码
    留神:间接克隆指定分支:

      git clone -b WxFilesWritable https://gitee.com/jamesfancy/code-for-articles.git