本文适用于 Window,CentOS(Linux) 系统请移步:http://xoyozo.net/Blog/Details/inotify-tools
FileSystemWatcher
关于监视文件系统事件的介绍
https://docs.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2008/ch2s8yd7(v=vs.90)
以控制台应用程序为例:
using System;
using System.IO;
using System.Security.Permissions;
public class Watcher
{
public static void Main()
{
Run();
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
private static void Run()
{
string[] args = Environment.GetCommandLineArgs();
// If a directory is not specified, exit program.
if (args.Length != 2)
{
// Display the proper way to call the program.
Console.WriteLine("Usage: Watcher.exe (directory)");
return;
}
// Create a new FileSystemWatcher and set its properties.
using (FileSystemWatcher watcher = new FileSystemWatcher())
{
watcher.Path = args[1];
// Watch for changes in LastAccess and LastWrite times, and
// the renaming of files or directories.
watcher.NotifyFilter = NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.FileName
| NotifyFilters.DirectoryName;
// Only watch text files.
watcher.Filter = "*.txt";
// Add event handlers.
watcher.Changed += OnChanged;
watcher.Created += OnChanged;
watcher.Deleted += OnChanged;
watcher.Renamed += OnRenamed;
// Begin watching.
watcher.EnableRaisingEvents = true;
// Wait for the user to quit the program.
Console.WriteLine("Press 'q' to quit the sample.");
while (Console.Read() != 'q') ;
}
}
// Define the event handlers.
private static void OnChanged(object source, FileSystemEventArgs e) =>
// Specify what is done when a file is changed, created, or deleted.
Console.WriteLine($"File: {e.FullPath} {e.ChangeType}");
private static void OnRenamed(object source, RenamedEventArgs e) =>
// Specify what is done when a file is renamed.
Console.WriteLine($"File: {e.OldFullPath} renamed to {e.FullPath}");
}

不支持当前所选音轨的文件格式,因此无法播放视频。请尝试播放其它音轨,确认其是否支持。
打开“套件中心”,打开右上角“设置”,添加“套件来源”:http://packages.synocommunity.com/
,名称如:SynoCommunity
,确定。
切换到“常规”选项卡,将“信任层级”改为至少“Synology Inc. 和信任的发行者”。否则会提示以下错误:
安装 [ffmpeg] 失败。此套件并非由 Synology Inc. 发布。
在“套件中心”左侧会出现“社群”,找到“ffmpeg”安装。
如遇下载失败,多尝试几次。
或直接从官方网站下载 .spk 包:https://synocommunity.com/package/ffmpeg
在“套件中心”“手动安装”即可。

首先在项目根目录中创建目录 Areas。
在 Areas 中添加区域,以“Admin”、“Console”两个区域为例:
VS 提醒在 Startup.cs 的 Configure() 方法中添加 app.UseMvc,此与 app.UseEndpoints 冲突,我们改为在 app.UseEndpoints 中添加 MapControllerRoute(放在 default 之前):
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "MyArea",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
给区域的控制器添加属性,如:
[Area("Admin")]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}

安装最新的:MySQL for Visual Studio
安装版本一致的:MySQL Connector Net、MySql.Data 和 MySql.Data.Entity
若仍闪退,在 MySQL Application Configuration 中勾选 Entity Framework 的 Use MySQL with Entity Framework
或直接升级 MySql.Data 到 8.x

在编程或生成时,我们可能会遇到如下错误:
推断出元组元素名称“category”。请使用语言版本 7.1 或更高版本按推断名称访问元素。
那么打开项目属性,切换到“生成”选项卡,“配置”选择“所有配置”。
页面往下拉,打开“高级”窗口,默认是“C# 最新主要版本(默认)”,我们选择“C# 最新次要版本(最新)”,确定。

无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同。如果服务器位于远程计算机上,请检查 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\AllowRemoteConnection 的值,确保服务器接受远程请求。如果服务器位于本地计算机上,并且上面提到的注册表值不存在或者设置为 0,则状态服务器连接字符串必须使用“localhost”或“127.0.0.1”作为服务器名称。
无法连接 StateService 的原因有很多种,我遇到的情况是:
VS 中使用 IISExpress 调试项目,系统没有安装 IIS,
ASP.NET 状态服务是开启状态,
没有对系统作任何修改,无缘无故无法连接。
修改注册表、配置防火墙无效(我没有用到远程连接),
执行 aspnet_regiis -i -enables 无效,
重装 .NET Framework 4.8 Developer Pack 无效,
差点就重装系统了。
最终的解决方法是:
在“启用或关闭 Windows 功能”中勾选安装:Internet Information Services -> 万维网服务 -> 应用程序开发功能 -> ASP.NET 4.8
重启系统。

Visual Studio 2019 已于本月早些时候正式发布,但 MySQL for Visual Studio 却迟迟未更新,目前的 1.2.8 版本只支持到 VS2017。表现在 VS2019 上会发生:
在“服务器资源管理器”中添加连接时,或在新建“ADO.NET 实体数据模型”时,无法看到数据源“MySQL Database (MySQL Data Provider)”
在实体数据模型设计器(Entity Data Model Designer)中执行“从数据库更新数据模型”时出现错误:尝试从数据库进行更新时,遇到类型为“System.ArgumentException”的异常。异常消息为:“无法将运行时连接字符串转换为设计时等效项。没有为提供程序“MySql.Data.MySqlClient”安装为设计目的(DDEX 提供程序)启用 Visual Studio 以便与数据库进行通信所需的库。
幸运的是 VS2019 可以与低版本 VS 共存,使用 ASP.NET 连接 MySQL 的开发者们要再等一等才能用上 VS2019 了。
这几天 MySQL 不断有产品更新,相信 MySQL for Visual Studio 2019 也会在不久的将来面世,本站将第一时间更新下载地址。
2019.8.30 Jose Ramirez(来自 MySQL 的 Windows 团队):MySQL for Visual Studio 的当前版本不支持 Visual Studio 2019。正在努力提供支持,但根据公司政策,我无法披露日期或对何时可用提供任何承诺。查看
2019.9.26 MySQL for Visual Studio 迟迟未更新,但是 VS2019 更新到最新版本(v16.3)已经一切正常了。
MySQL for Visual Studio 的 Repair 功能是鸡肋,有问题的话,Remove 后重新安装才能解决。

这是一篇可能解决困扰了 .NET 程序猿多年的文章!
首先,使用 Visual Studio 2019 创建一个 ASP.NET WEB 应用程序,直接选用了 MVC 模板。
直接发布项目,默认的设置如下图:
对于小型项目,按默认设置发布基本可满足正常运行,首次运行打开第一个页面基本在 5~6 秒(视服务器配置),其它页面的首次打开也基本在 1~2 秒完成,非首次瞬间打开。
一旦项目功能变得复杂,文件增多,会导致发布后首次运行打开第一个页面 30 秒以上,其它页面的首次打开 10 秒左右,非首次瞬间打开。
这是因为项目在发布时没有进行预编译,而是在用户访问网页时动态编译,一旦应用程序池回收,或项目文件改动,都会重新编译,再次经历缓慢的“第一次”,这是不能忍的。
于是咱们来研究一下“预编译”。
在发布页面勾选“在发布期间预编译”,这时发布会在“输出”窗口显示正在执行编译命令(编译时间会比较长):
该选项对发布后的文件结构和内容影响不大,因此对首次执行效率的提升也不大,重要的在后面。
在“高级预编译设置”窗口中:
我们针对预编译选项和合并选项分别做测试。
不勾选“允许更新预编译站点”,会致 bin 目录中生成许多 .compiled 文件,而所有 .cshtml 文件的内容都是:
这是预编译工具生成的标记文件,不应删除!
如果是 Web From 网站,.aspx/.ashx 等文件内容同上。
尝试打开网站页面,你会发现,除了项目启动后的第一个页面仍然需要 1~2 秒(无 EF),其余每个页面的首次都是瞬间打开的(EF 的首次慢不在本文讨论范围)。这让我对预编译有一种相见恨晚的感觉!
这里偷偷地告诉你,把 Views 目录删掉也不影响网页正常打开哦~为什么不让删,咱也不敢问,咱也不敢删。
目的达到了,有一些后遗症需要解决,比如 bin 目录内杂乱无章。
选“不合并。为每个页面和控件创建单独的程序集”,结果是 bin 多出许多 App_Web_*.dll 文件。
选“将所有输出合并到单个程序集”,填写程序集名称。这时会发现“输出”窗口执行了命令:
如果程序集名称跟已有名称冲突,会发生错误:
合并程序集时出错: ILMerge.Merge: The target assembly '******' lists itself as an external reference.
查看 bin 目录,.compiled 文件还在,但 App_Web_*.dll 合并成了一个程序集。FTP 的“不合并”也是把所有 App_Web_*.dll 上传一遍,所以不存在相对于“合并”的增量发布优势。
是不是勾了“视为库组件删除(AppCode.compiled 文件)”.compiled 文件就会不见?意外之外,情理之中,bin 没有什么变化。
继续选择“将各个文件夹输出合并到其自己的程序集”,呃,bin 中文件数不降反增。
最后选择“将所有页和控件输出合并到单个程序集”,同样程序集名称不能冲突。结局令人失望,bin 中仍然一大堆 .compiled 和 App_Web_*.dll。
整理成表格:
1 | 允许更新预编译站点 aspnet_compiler.exe -v / -p \Source -u \TempBuildDir 重复发布后 bin 目录文件数:不会增多(页面不进行预编译) |
2 | 不允许更新预编译站点,不合并 aspnet_compiler.exe -v / -p \Source \TempBuildDir 重复发布后 bin 目录文件数:.compiled 不会增多,App_Web_*.dll 增多 |
3 | 不允许更新预编译站点,不合并。为每个页面和控件创建单独的程序集 aspnet_compiler.exe -v / -p \Source -c -fixednames \TempBuildDir 重复发布后 bin 目录文件数:不会增多(编译后的文件名固定,FTP 方式的部分 App_Web_*.dll 文件可能实现增量上传) |
4 | 不允许更新预编译站点,将所有输出合并到单个程序集,不勾选“视为库组件” aspnet_compiler.exe -v / -p \Source -c \TempBuildDir aspnet_merge.exe \TempBuildDir -o 程序集名称 -copyattrs AssemblyInfo.dll -a 重复发布后 bin 目录文件数:不会增多(.compiled 固定名称,App_Web_*.dll 合并为一个) |
5 | 不允许更新预编译站点,将所有输出合并到单个程序集,勾选“视为库组件” aspnet_compiler.exe -v / -p \Source \TempBuildDir aspnet_merge.exe \TempBuildDir -o 程序集名称 -copyattrs AssemblyInfo.dll -a -r 重复发布后 bin 目录文件数:不会增多(.compiled 固定名称,App_Web_*.dll 合并为一个) |
6 | 不允许更新预编译站点,将每个文件夹输出合并到其自己的程序集,前缀 aspnet_compiler.exe -v / -p \Source -c \TempBuildDir aspnet_merge.exe \TempBuildDir -prefix 前缀 -copyattrs AssemblyInfo.dll -a 重复发布后 bin 目录文件数:.compiled 不会增多,App_Web_*.dll 增多 |
7 | 不允许更新预编译站点,将所有页和控件输出合并到单个程序集 aspnet_compiler.exe -v / -p \Source -c \TempBuildDir aspnet_merge.exe \TempBuildDir -w 程序集名称 -copyattrs AssemblyInfo.dll -a 重复发布后 bin 目录文件数:.compiled 不会增多,App_Web_*.dll 增多 |
bin 目录下,页面的程序集文件(App_Web_*.dll)增多的原因是编译后的文件名不固定,发布到会导致残留许多无用的程序集文件。
相比较,如果第 3 种能实现 FTP 稳定的增量上传的话是比较完美的(还有一个缺点是:如果页面有删除,目标 bin 内对应该页面的 .compiled 和 .dll 不会删除,这跟“允许更新预编译站点”是一个情况),那么第 4 种 或第 5 种也是不错的选择(同样有缺点:执行合并比较慢)。
测试一个有 300 个页面的项目,compiler 用时约 2 分钟,merge 用时约 5 分钟,发布用时约 4 分钟。
这里有个槽点,执行预编译和合并是佛系的,CPU 和磁盘使用率永远保持在最低水平。
所以如果是要经常修改的项目,那么建议选择“不合并”的第 3 种发布方式:
“视为库组件(删除 AppCode.compiled 文件)”:移除主代码程序集(App_Code 文件夹中的代码)的 .compiled 文件。 如果应用程序包含对主代码程序集的显式类型引用,则不要使用此选项。
补充:
不允许更新预编译站点发布后,因为前端页面没有内容,因此无法单独修改发布(单独发布一个页面后,在访问时不会生效!),只能全站发布,耗时较长;bin 目录有变动将导致使用 InProc 方式存储的 Session 丢失。
预编译的另一个优点是可以检查 .aspx / .cshtml 页面 C# 部分的错误(特别是命名空间和路径引用)。
改为预编译发布后,可以将服务器上残留的 .master / .ascx / .asax 删除,但不能删除 .aspx / .ashx /.config 等。
VS 发布到 FTP 经常会遗漏一些页面文件,不合并时会遗漏独立文件,合并后也会遗漏合并后的 .dll 的文件,合并的好处就是方便检查是否完全上传发布。
慎选“在发布前删除所有现有文件”!一旦勾选发布,世界就清静了,所有网友上传的图片附件以及网站运行产生的其它文件,消失得无影无踪。不管发布到文件系统还是发布到 FTP 都一样。当然,如果是先发布到文件系统,再通过 FileZilla 等 FTP 软件上传到服务器的,建议勾选此项。
.NET Core 应用程序部署:https://docs.microsoft.com/zh-cn/dotnet/core/deploying/index
由于上传文件时 bin 目录文件较多,理论上 bin 目录内的文件有任何改动都会重启应用池,而且 VS 是单线程上传的,导致期间网站访问缓慢,服务器 CPU 升高,我的做法是:发布到文件系统,再使用专用 FTP 工具上传,上传用时约半分钟(如果大小不同或源文件较新则覆盖文件)。还嫌慢?那就打包上传,解压覆盖。
关于本文研究对象的官方解释:高级预编译设置对话框
出现“未能加载文件或程序集“***”或它的某一个依赖项。试图加载格式不正确的程序。”的问题时,先用改用 Debug 方式发布会报详细错误,一般是 .aspx 等客户端页面有 C# 语法问题,注意提示报错的是 /obj/ 目录下的克隆文件,应更改原文件。排除错误后关闭所有页面,再使用 Release 方式发布。
2025年9月补充:因预编译发布后生成的文件时间都是系统最新时间,通过 FTP 上传到服务器时都会覆盖文件,可能导致杀毒软件进程 MsMpEng.exe 占用 CPU 过高。尝试选择不进行预编译,即取消“发布期间预编译”前的勾,这样发布的的文件时间都是文件本身的最后修改时间,重复发布不会更新这个时间,而且 bin 目录中也不会出现大量编译后的文件。这样通过 FTP 上传时只要设置“大小不同且文件较新则覆盖”就不会重复上传文件了,杀毒软件的工作量就能大大减少。缺点就是本文开头说的,每个页面的第一次打开会比较慢,而是非常慢。所以仍然需要勾选“发布期间预编译”,同时勾上“允许更新预编译站点”,这样 bin 目录中不会发现很多文件(合并不合并都一样),打开每个页面的第一次耗时也能在接受范围内。

确定唯一凭证:
若项目仅提供微信端访问,那么使用微信的授权(即以微信 openid / unionid 作为唯一凭证)是一种体现注重用户体验的方式。如果项目需要应用到多个平台上,那么通过微信来授权变得不那么完美(譬如未安装微信客户端或平台不支持使用微信授权等)。因手机的使用率已明显高于电脑的使用率,再加上用户帐号实名认证的要求,以手机号码为作为帐号的唯一凭证是非常合理的。
登录唤起条件:
当用户打开需要登录授权的页面或触发需要登录授权才能执行的操作时。
场景实现:
平台 | 实现 |
微信网页/小程序 | 授权获取 openid / unionid 同时若未绑定手机号码则强制绑定(发送验证码的方式) 如果允许在微信上登录不同的用户帐号,那么需要提供【“手机号码 + 密码”登录】方式 |
手机 App | 提供【“手机号码 + 密码”登录】 提供【第三方帐号登录】,登录后强制绑定手机号码 参“京东”等 |
PC 端浏览器网页 | 提供【“手机号码 + 密码”登录】 登录框可切换成【扫二维码登录】,登录后强制绑定手机号码 |
手机浏览器网页 | 提供【“手机号码 + 密码”登录】 如果提供【第三方帐号登录】,那么可能需要在网页上手动输入第三方帐号的用户名密码,而非跳转到第三方 App 上(视第三方开放平台) |
l 【“手机号码 + 密码”登录】页面显示填写手机号码和密码框的表单,提供“忘记密码”、“短信验证码登录”、“手机快速注册”等功能。如果在可长期记住登录状态的场景中(如手机 App)也可取消密码,直接使用短信验证码登录。“手机快速注册”必须通过短信验证码实现实名认证。
l 【第三方帐号登录 / 扫二维码登录】App 中提供跳转相应第三方 App(如微信)授权登录,PC 端网页中提供微信扫二维码登录。登录获得 unionid,同时判断是否已经绑定过手机号码,若未绑则强制绑定,确保数据库中的每一条用户信息都有手机号码。
注:同一个微信帐号在不同的公众号和 App 中的 openid 不同,将这些公众号和 App 通过微信开放平台绑定后,同一个微信帐号的 unionid 是相同的,可用于判断同一用户。
流程图:
各平台登录设计:
