news 2026/4/24 13:52:16

【项目实战】在开发全局流水号生成器过程中,需考虑自己开发环境与软件生产环境的权限差异问题!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【项目实战】在开发全局流水号生成器过程中,需考虑自己开发环境与软件生产环境的权限差异问题!

Hello,各位小伙伴们,这篇文章主要给大家分享近期开发所遇到的一个由于环境权限差异问题而引发的一个BUG。希望能给我们后续开发提前预警。

一、需求:应用程序现需要一个持久化按日递增流水号生成器(2026042100001),用这个工具所生成的流水号去调接口。

二、分析:我决定在exe根目录下新建一个txt文件来存储生成的流水号(日期+序号),然后每次生成完新的流水号就同步更新这个txt文件。

三、问题代码:

using System; using System.IO; namespace NFS.Models.Common.Custom { public static class PersistentSerialNumberGenerator { private static readonly object _lockObj = new object(); // 计数存储文件路径(可自定义) private static readonly string _configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SerialConfig.txt"); private static DateTime today; public static string Generate(DateTime? processingDate) { lock (_lockObj) { today = processingDate ?? DateTime.Today; string todayStr = today.ToString("yyyyMMdd"); // 初始化:读取文件中的历史日期和计数 var config = ReadConfig(); string lastDate = config.Item1; int count = config.Item2; // 跨天判断:重置计数 if (lastDate != todayStr) { count = 1; lastDate = todayStr; } // 生成流水号 string sn = $"{todayStr}{count:D5}"; // 计数+1并保存到文件 WriteConfig(lastDate, count + 1); return sn; } } // 读取配置:上次日期+当前计数 private static Tuple<string, int> ReadConfig() { try { if (File.Exists(_configPath)) { string[] lines = File.ReadAllLines(_configPath); return Tuple.Create(lines[0], int.Parse(lines[1])); } } catch { } return Tuple.Create(today.ToString("yyyyMMdd"), 1); } // 写入配置:保存日期和计数 private static void WriteConfig(string date, int count) { File.WriteAllLines(_configPath, new[] { date, count.ToString() }); } } }

调用:

TransNumber = PersistentSerialNumberGenerator.Generate(processDate) //需要把当前时间给这个方法

问题:这里作者就没有考虑到自己开发环境与软件生产环境的权限差异问题。作者在本地开发环境中,拥有对exe根目录文件夹完全控制(Full control)权,所以读取写入(覆盖)是完全没问题的且不会报错的,但是生产环境就只是一个只读的权限,这也就导致这个流水号生成器在开发环境是不会报错的,但是一放到只有只读权限的生产环境时,就会报错。

更可笑的是,作者拿到生产环境的备份库后,在自己开发环境调试程序的时候,由于权限足够,是不会报错的,这也就让作者很长时间定位不到问题,所以这个BUG耗费了作者小一天的时间。

解决方案:

临时解决方案:勾选完全控制(Full control),或者是写入(Write)权限

标准解决方案:

//方案一,先删除再写入,而不是直接覆盖,因为覆盖文件就需要Windows的写入权限 private static void WriteConfig(string date, int count) { string fullPath = _configPath; // 只读文件夹安全写入 if (File.Exists(fullPath)) File.Delete(fullPath); File.WriteAllLines(fullPath, new[] { date, count.ToString() }); } //方案二,再exe根目录下同级建一个文件夹来放txt文件,因为Windows新建文件夹默认不只读,一句话总结:父文件夹权限不影响子文件夹,新建的子文件夹完全自由读写 private static void WriteConfig(string date, int count) { // 依然跟着EXE走,打包复制一起走 string configDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config"); if (!Directory.Exists(configDir)) Directory.CreateDirectory(configDir); _configPath = Path.Combine(configDir, "SerialConfig.txt"); File.WriteAllLines(_configPath , new[] { date, count.ToString() }); }

今天的分享就到这了,拜拜~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/24 13:50:19

终极指南:3分钟掌握KH Coder开源文本挖掘工具

终极指南&#xff1a;3分钟掌握KH Coder开源文本挖掘工具 【免费下载链接】khcoder KH Coder: for Quantitative Content Analysis or Text Mining 项目地址: https://gitcode.com/gh_mirrors/kh/khcoder 你是否曾面对海量文本数据感到无从下手&#xff1f;想要进行专业…

作者头像 李华
网站建设 2026/4/24 13:46:18

3dsconv实战手册:三步完成3DS游戏格式转换的完整工作流

3dsconv实战手册&#xff1a;三步完成3DS游戏格式转换的完整工作流 【免费下载链接】3dsconv Python script to convert Nintendo 3DS CCI (".cci", ".3ds") files to the CIA format 项目地址: https://gitcode.com/gh_mirrors/3d/3dsconv 3dsconv…

作者头像 李华
网站建设 2026/4/24 13:43:36

Github热榜项目推荐 | 榜单迎来新鲜事儿

本期推荐的五个项目涵盖了AI Agent自动化训练、代码语义搜索、多模态RAG框架、全能安全测试工具和WiFi人体姿态感知等前沿技术方向&#xff0c;均来自GitHub上近期快速增长或颇具影响力的开源项目。 huggingface/ml-intern ⭐ 3,000 源链接&#xff1a; https://github.com/hu…

作者头像 李华
网站建设 2026/4/24 13:43:34

HS2-HF Patch完全指南:200+插件一键优化你的Honey Select 2游戏体验

HS2-HF Patch完全指南&#xff1a;200插件一键优化你的Honey Select 2游戏体验 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 你是否遇到过这些令人沮丧的情况…

作者头像 李华