试用期校验必须在程序启动最前端执行:WinForms 在 Program.cs 的 Main() 开头、WPF 在 App.xaml.cs 的 OnStartup 第一行调用,用 Environment.Exit(1) 强制终止;采用注册表 HKEY_CURRENT_USER\Software\YourApp\InstallTime 与可执行文件最后写入时间双校验,取较晚者为安装起点;按 DateTime.Today 计算自然日,满7天即过期;调试绕过须物理隔离,推荐检查 trial.bypass 文件或 APP_SKIP_TRIAL 环境变量。

试用期校验必须放在程序启动最前端
不拦在入口,用户随便改系统时间就能绕过。Windows 服务、WinForms、WPF 都得在 Main() 或 Application.Startup 里立刻执行校验,不能等窗体加载完、不能等用户点按钮才检查。
常见错误是把校验逻辑塞进主窗体的 Form_Load 事件——此时进程已运行,资源已分配,用户甚至能截取内存绕过判断。
- WinForms:在
Program.cs的Main()函数开头调用CheckTrialPeriod() - WPF:在
App.xaml.cs的OnStartup方法第一行执行 - 务必用
Environment.Exit(1)强制终止,别只弹窗+return
用注册表 + 文件时间戳双保险防篡改
单靠本地文件存安装时间太容易被删或改。注册表路径 HKEY_CURRENT_USER\Software\YourApp\InstallTime 加上可执行文件自身的最后写入时间(File.GetLastWriteTimeUtc(Assembly.GetExecutingAssembly().Location)),两个时间取较晚者作为“可信安装起点”。
为什么这么做?用户重装软件时,.exe 文件时间会更新;而手动改注册表需要管理员权限且易被安全软件拦截;两者同时被改的概率极低。
- 注册表项必须用
Registry.CurrentUser,避免需要提权 - 读取
File.GetLastWriteTimeUtc前先检查文件是否存在,防止路径被替换为空文件 - 不要用
DateTime.Now直接比对——用户调快系统时间会导致提前过期
“7天试用”不是硬写死 7 * 24 * 60 * 60
直接算秒数会出问题:用户安装后关机三天,开机再用,实际只用了 4 天,但按秒数计算可能已超限。应该按“自然日”计数,即从安装当天起,连续日历日满 7 天即截止(含安装日)。
实现上用 DateTime.Today 对比,而不是 DateTime.UtcNow 加 TimeSpan。否则跨时区或夏令时切换会导致误差。
- 存储安装日期用
DateTime.Date(去掉时分秒),比如new DateTime(2024, 5, 20) - 每次启动计算:
(DateTime.Today - installDate).Days >= 7 - 注意:
installDate必须是首次运行时写入并固定,后续绝不更新
调试阶段绕过机制要物理隔离
开发时总不能天天重装系统来测试过期逻辑。但把 #if DEBUG 直接包住整个校验,发布时忘了删,就等于没加授权——这种事故真发生过。
正确做法是让绕过开关完全脱离代码:用独立配置文件、环境变量,或者检查调试器是否附加(仅限临时验证)。
- 推荐方案:检查是否存在
trial.bypass空文件,路径固定如AppContext.BaseDirectory + "trial.bypass" - 次选方案:读取环境变量
APP_SKIP_TRIAL,值为"1"时跳过 - 绝对不用
Debugger.IsAttached做正式绕过——发布版也能被调试器 attach
绕过机制本身要藏得深一点:文件名别叫 bypass.txt,环境变量别叫 DEBUG_MODE;否则打包发给客户前,很容易漏删。











