尝试在Windows NT6+上免驱实现FUSE

作者:V君 发布于:2017-9-22 20:18 Friday 分类:折腾手记

■前言  (这次不是解决问题,因此没有TLDR(´∀((☆ミつ)


首先简单解释一下 FUSE 的定义:

在用户空间实现的虚拟文件系统, 能够让标准文件系统API访问,

只是某个路径在应用程序的控制之下, 还没到达虚拟块设备的级别.


FUSE 能够实现许多有趣的功能, 比如挂载压缩包, FTP, MTP, 甚至 Ramdisk 都能实现.

在 linux 实现 FUSE 可以说是相当容易,

由于 linux 可以把 FUSE 功能集成到内核, 随便 mount 就可以了.

然而 Windows 内核并没有这样的功能,

只能以虚拟设备来创建虚拟盘符或挂载到 NTFS 装入点亦或者建立目录符号链接.

 

现状


在 Windows 实现 FUSE 通常需要虚拟驱动器来实现, 这需要驱动程序来支持.

现成的软件有

1)免费的 WinMount(生死未卜)

2)收费的 NetDrive.

它们都是封装好的产品, 用户不能定制自己的功能.

可以自己实现接口的驱动组件有

1)开源的 Dokan(貌似不太稳定)

2)开源的 WinFsp(没用过,无法评论)

3)死贵死贵的 CBFS.

早些年把玩过Dokan, 虽然提供了.NET的接口, 且实现难度还不算高.

假如接口实现得不稳定, 没妥善处理好异常就可能会引发蓝屏, 这也就是本文的初衷.

-- 不使用驱动来实现 FUSE , 就算接口实现得再糟糕也不会把系统搞崩溃.

 

摸索


稍稍有点经验的 Windows 用户都知道,

资源管理器可以直接访问FTP或多媒体设备存储(MTP/PTP)

可以把路径以文件夹的形式图形化呈现, 

然而这些路径并不能够使用标准文件系统 API 来放访问,

不能用 WindirStat 来统计 MTP 上的文件夹占用情况.

尽管资源管理器双击能打开这些路径中的文件,

其实背地里还是先复制到临时文件再调用关联的应用程序去打开.

 

其实 Windows 还是可以不依赖驱动就能实现 FUSE 的.

目前发现了两种方法, 尽管都是利用网络共享绕一圈, 还蛮折腾的:

1)基于 HTTP 的WebDAV 协议

 在一次折腾如何在安桌手机 USB 的 MTP 模式使用 WinDirstat 的过程中

 发现了 WebDAV 共享 APP.

 安装并启动之后, 按照步骤创建映射盘符, 能被 WinDirstat 访问了.

 咕狗了解到是基于 HTTP 的共享协议.

 (这是WebDAV over WIFI, 这已经和 MTP 没关系了, 不过下文还是会和MTP有关系)

 这才发现 Windows 还有这种共享方式, 支持标准文件系统 API, 

 只是实现机制略坑, 性能略糟糕.

2)Samba 局域网共享

 不解释太多也不会被打 (´∀((☆ミつ

 需要实现一个 SMB 服务端, 还要战 445 端口. 战? 不是占? YES, 稍后娓娓道来.

 

尝(zhe)试(teng)


□WebDAV -- 这货是真FUSE, 只是 Windows 实现机制太坑人


知道这货基于 HTTP 之后, 当然就是去找找看有没有人已经做成类库, 而不是先自己啃RFC.

放狗出去找到两个类库, 分别是 SF 上的 WebDAV.NET 服务框架 和 GitHub 上的 WebDAVSharp.

这次选择了后者, 只要按接口做实现, 就可以达到目的, 咋一看还挺完善的, 只是性能有点慢.

即使用内存来实现后端文件存储, 访问速度也和硬盘差不多,

监视性能才发现, 原来 Windows 在背后依然用临时文件的方式暂存 WebDAV 上面的文件, 

只是重定向了一下文件系统. 难怪这么慢, 这 FUSE 虽然是真货, 但却掺了水.

你可以把它的临时目录(↓)链接到 RAMDISK 以提升性能, 此目录必须存在才能正常操作文件.

C:\Windows\ServiceProfiles\LocalService\AppData\Local\Temp\TfsStore\Tfs_DAV\

只不过这样就失去了用 WebDAV 实现 RAMDISK 的意义, 只能用作简单 FUSE 玩玩.

顺便再贴一个之前还没了过背后原理, 仍未知性能坑时, 实现MTP2DAV

晚些单独写一篇详细介绍的博文. 

 

Samba -- 战445端口要不要太折磨人?


非常幸运地找到最近 TalAloni 用 .net 实现且一直在维护的 Samba 服务端的库 SMBLibrary.

看了下介绍, 确实有提到可以实现虚拟文件系统. -- 只是 445 被 Windows 锁死, 需要一战.

除非禁用 Server 服务, 否则全部适配器的 445 端口将不可用...见爆栈.

尝试了许多诸如增加虚拟适配器的 trick 做法, 然而并没有设么卯月...

停止 Server 服务之后还不行, 445 仍然会被 System 占用, 需要重启...

那就只能彻底禁用了.禁用了 Server 服务并重启之后, 445 端口总算可用.

把内置的目录共享跑起来, 效果还挺理想, 性能相当不错, 看了一下接口并不是很复杂.

就简单做了个后端用内存支撑的 RamDisk 实现, 然而并不是很理想.

-- 非常不稳定, 常规操作下会出现各种错误, 看来是接口适配的不太妥哇...

总之, 这种 Samba 的方式是可行的.

只是稍稍麻烦点, 无论是从禁用 Server 服务还是实现接口上来看...


■结论


WebDAV 可以用来实现简单的 FUSE, 无法考虑性能.可以用 RamDisk 稍稍提升一下.

Samba 性能相当好, 接口略复杂, 目前还没啃透 (´∀((☆ミつ

标签: C# Winform NAS HTTP 传输协议 FUSE VFS Windows

评论(0) 引用(0) 浏览(8)

使用程序包管理控制台批量安装/更新/修复NuGet包

作者:V君 发布于:2017-8-27 20:24 Sunday 分类:折腾手记

TL;DR

准备好你的 packages.config 配置文件,可以从以前的项目中直接拷贝或自己写。

去程序包管理控制台执行 Update-Package 就能把配文件中的所有包的更新到最新版本。

接下来执行 Update-Package -Reinstall 把配置文件中的包装上。

如果你改变了目标框架,需要重新选择依赖库,可以再次执行 Update-Package -Reinstall。

 

听我扯扯:

在过去新建项目,添加 NuGet 包时只能去包管理器界面一个个手动搜索添加。

当改变了目标框架,只好一个个手动卸载再走一遍上述步骤。 要不要这么麻烦?

依旧喂狗到爆栈,找到批量安装更新全部包的方法,从此再也不需要这么麻烦手动安装了。

标签: 软件开发 VisualStudio

评论(0) 引用(0) 浏览(46)

使用StackStrace获取属性名称的惨痛教训

作者:V君 发布于:2017-7-21 18:04 Friday 分类:折腾手记

TL;DR: 改用 CallerMemberName 的方式.


必须扯,内容再少也要扯!

 

一直以来, 封装配置访问类时, 根据同样的只读属性名称去字典值或查数据库.

尽管比较新的 nameof 关键字可用, 但还是需要重复打字, 这非常不爽.


于是自作聪明的咱就抓取上一个堆栈帧, 取出方法名的方式代替Key.

定义一个无参方法 GetValue ,里面去抓 StackTrace, 

一般情况下, 只读属性的方法名是 get_XXXX, 这种情况直接去掉头就可以吃了.

然后只读属性的 getter 就直接无参调用 GetValue(),

看到一大堆只读属性调用同一个无参方法是不是很魔法啊? 乂目

  public string ConfA => GetValue();
  public string ConfB => GetValue();
  public string ConfC => GetValue(); 


然而, 二般情况出现了... 优化编译并 IL-Repack 之后 --

 只读访问器的堆栈帧不见了!!! EXM?!

错误地取到上一个方法的名字, 导致配置读不出来 囧....

即使在 GetValue 方法加上了 NotInlining 的特性, 问题仍旧存在...

放狗出去找爆栈, 在不太相关的问题上看到有说用 CallerMemberName 可以.

用了之后才知道爽, 问题解决了!

标签: 软件开发 C#

评论(0) 引用(0) 浏览(101)

活久见:有些异常是不能被catch(Exception)捕获的,你得把catch参数去掉

作者:V君 发布于:2017-6-14 0:25 Wednesday 分类:折腾手记

TL;DR: 

当你发现本应被捕获的异常却被无视 try-catch 语句时,

你应该试着去掉 catch(Exception ex) 中高亮的部分

写成 try {....} catch{....} 这种写法将不能直接取得异常实例,

你可以将上下文对象值记录下来作为排查线索。


本例:

将 MVC 5.2.3 站点部署到装了 mono 4.2.2 的Debian@树莓派。

首先就遇到一大堆兼容性问题。去掉一系列不兼容的组件。

(ApplicationInsights系列、CodeDom系列

总算能报出些看起来有点线索的异常。

System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.
  at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (System.Reflection.Assembly,bool)
  at System.Reflection.Assembly.GetTypes () <0x721db540 + 0x00023> in <filename unknown>:0 
  at Ease.Ioc.IocManager.RegisterInterface (System.Reflection.Assembly[] assemblies, System.Type iface,
System.Func`1 lifetimeManager) <0x721db0c0 + 0x000fb> in <filename unknown>:0 
  at Ease.Ioc.IocManager..ctor () <0x721fb130 + 0x00283> in <filename unknown>:0 
  at Ease.Ioc.IocManager..cctor () <0x721faff8 + 0x00027> in <filename unknown>:0 

这是模仿 ABP 在当前应用域中的所有程序集中寻找实现了指定接口的类,然后加到 IoC 容器。

(哎……谁让 ABP 还不支持 mono 呢。。。)

在对某个程序集调用 GetType 时爆炸了……

于是在其周围加上常规异常处理 try-catch(Exception) 试图找出有问题的程序集。

然而异常依旧引发,就跟没写 try-catch(Exception) 一样……

试着调整方法结构,避免一些在首次访问方法就引发异常的状况 —— 无果……

心一横,去掉 catch 语句的参数,记下当前调用 GetTypes 的程序集。

try
{
types.AddRange(asm.GetTypes().Where(p => false == p.IsAbstract && false == p.IsInterface && iface.IsAssignableFrom(p)));
}
catch
{
throw new Exception("Asm load fail?" + asm);
}

功夫不负有心人 or 瞎猫撞上死耗子? bingo! 抓到你啦!

Asm load fail?System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35

咋办? 没办法哇! 试着把引用干掉看看吧…… 果然就没事儿了!

稍稍去了解一下那玩意儿,发现是一堆辅助类, 反正一时半会也用不上。


于是就这样,用作类似 Hello world 的站点首页就成功呈现出来啦!

 —— 尽管是乱码…… 因为偷懒直接输出 Content 嘛! 接下来可以慢慢折腾啦!

标签: 软件开发 树莓派 C# linux mono

评论(0) 引用(0) 浏览(154)

使用Adobe Premiere制作视频镂空叠加

作者:V君 发布于:2017-6-9 22:00 Friday 分类:折腾手记

首先用一张图来表示咱想说的啥,然后再到TL;DR吧 (pia~~

TL;DR: 

1) 按叠加素材层次添加到序列;

2) 从效果中选择「RGB差值键」,拖放到序列选中需要镂空处理的素材;

3) 在效果编辑器吸取要镂空的颜色;

4) 调整相似性以及圆滑程度,达到消除毛刺的镂空叠加效果


详(ting)细(wo)操(che)作(che)点进来看

阅读全文>>

标签: 多媒体 视频编缉 Premiere

评论(0) 引用(0) 浏览(138)

Powered by emlog 去你妹的备案 sitemap