代码改变世界

记一次简单的服务开发

  糯米粥  阅读(407)  评论(0编辑  收藏  举报

因为需要做一个每天定时同步数据的操作,需要把同步的数据用特定的分隔符分割然后写入文件

客户是通过一个工具。来识别我生成的文件,其实就是 |  但必须通过16进制转字符串然后拼接

核心代码如下:

复制代码
 1    /// <summary>
 2         /// 获取数据
 3         /// </summary>
 4         /// <param name="dt"></param>
 5         /// <param name="fileName"></param>
 6         protected static StringBuilder GetDate(DataTable dt)
 7         {
 8             StringBuilder datInfo = new StringBuilder();
 9             //if (dt == null || dt.Rows.Count <= 0) return datInfo;
10             DataColumnCollection dColumn = dt.Columns;
11 
12             string uh = UnHex("7C1C", "GBK");
13             for (int i = 0; i < dt.Rows.Count; i++)
14             {
15                 foreach (DataColumn col in dColumn)
16                 {
17                     string val = dt.Rows[i][col.ColumnName].ToString();
18                     datInfo.AppendFormat("{0}{1}", val, uh);
19                 }
20                 datInfo.AppendFormat("{0}", "\n"); //一行分隔符
21             }
22             return datInfo;
23 
24         }
25 
26         ///<summary>
27         /// 从16进制转换成汉字
28         /// </summary>
29         /// <param name="hex"></param>
30         /// <param name="charset">编码,如"utf-8","gb2312"</param>
31         /// <returns></returns>
32         public static string UnHex(string hex, string charset)
33         {
34             //if (hex == null)
35             //    throw new ArgumentNullException("hex");
36             hex = hex.Replace(",", "");
37             hex = hex.Replace("\n", "");
38             hex = hex.Replace("\\", "");
39             hex = hex.Replace(" ", "");
40             if (hex.Length % 2 != 0)
41             {
42                 hex += "20";//空格
43             }
44             // 需要将 hex 转换成 byte 数组。 
45             byte[] bytes = new byte[hex.Length / 2];
46 
47             for (int i = 0; i < bytes.Length; i++)
48             {
49                 try
50                 {
51                     // 每两个字符是一个 byte。 
52                     bytes[i] = byte.Parse(hex.Substring(i * 2, 2),
53                     System.Globalization.NumberStyles.HexNumber);
54                 }
55                 catch (Exception ex)
56                 {
57                     // Rethrow an exception with custom message. 
58                     //throw new ArgumentException("hex is not a valid hex number!", "hex");
59 
60                     File.AppendAllText(timeLog, ex.Message);
61                 }
62             }
63             System.Text.Encoding chs = System.Text.Encoding.GetEncoding(charset);
64             return chs.GetString(bytes);
65         }
复制代码

 

配置文件:

复制代码
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
    <add name="链接字符串" connectionString="" />
  </connectionStrings>
<appSettings>
    <!--定时执行的时间 格式:HH:mm-->
       <add key="time" value="16:21" />
    <!--定时器执行的时间 单位:ms-->
    <add key="interval" value="2000" />
    <!--同步目录的文件,绝对路径-->
    <add key="exprotFile" value="D:\exprotFile" />
    </appSettings>
</configuration>
复制代码

 

服务部分:

复制代码
using CAS.DataAccess.BaseDAModels;
using CMB.RetailSyncData;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using Newtonsoft.Json.Linq;

namespace SyncDataService
{
    public partial class Service : ServiceBase
    {
        //static DirectoryInfo rootDir = Directory.GetParent(Environment.CurrentDirectory);
        static string applicatRoot = AppDomain.CurrentDomain.SetupInformation.ApplicationBase.TrimEnd('\\');
        //日志路径
        public static string timeLog = Path.Combine(applicatRoot, "log\\") + DateTime.Now.ToString("yyyyMMdd") + ".txt";
        Configuration config;public Service()
        {
            InitializeComponent();
            Init();
        }
        public void Init()
        {
            try
            {
                InitConfig();
            }
            catch (Exception ex)
            {
                WriteLog(ex.Message + "\r\n" + ex.StackTrace);
            }
            WriteLog("服务初始化成功");
        }

        protected override void OnStart(string[] args)
        {
            WriteLog("服务启动");
            LoadFromWebservice();
        }
        public void InitConfig()
        {
            ExeConfigurationFileMap map = new ExeConfigurationFileMap();
            //(引号里面的是你的配置文件的在程序的绝对路径)。
            map.ExeConfigFilename = applicatRoot + @"\config\App.config";

            config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
        }
        protected override void OnStop()
        {
            WriteLog("服务停止");
            //this.Stop();
        }
       
        /// <summary>
        /// 开启计时器
        /// </summary>
        /// <param name="wait">是否需要延时开启</param>
        public void LoadFromWebservice(bool wait = false)
        {
            /*
             * 等待一分钟。在开启计时器。
             * 防止:同一个时间点重复导出
            */
            if (wait) System.Threading.Thread.Sleep(1000 * 60);//等待一分钟

            //定义一个定时器,并开启和配置相关属性
            double interval = double.Parse(config.AppSettings.Settings["interval"].Value);
            System.Timers.Timer Synctimer = new System.Timers.Timer(interval);//执行任务的周期
            Synctimer.Elapsed += new System.Timers.ElapsedEventHandler(Synctimer_Elapsed);
            Synctimer.Enabled = true;
            Synctimer.AutoReset = true;
        }

        public void Synctimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Timer timer = (Timer)sender;

            if (DateTime.Now.ToString("HH:mm") == config.AppSettings.Settings["time"].Value)
            {
                //先停止计时器
                timer.Enabled = false;
                int count = 0;
                try
                {
                    //开始同步
                }
                catch (Exception ex)
                {
                    WriteLog(ex.Message + "\r\n" + ex.StackTrace);
                }

                timer.Dispose(); //释放资源

                LoadFromWebservice(true); //重新开启一个计时器
            }
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }

        /// <summary>
        /// 写log
        /// </summary>
        /// <param name="msg">message</param>
        protected void WriteLog(string msg)
        {
            File.AppendAllText(timeLog, DateTime.Now.ToString() + ":" + msg + "\r\n");
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="datInfo">内容</param>
        /// <param name="fileName">前缀</param>
        /// <param name="exprotTime">导出时间(T-1)</param>
        /// <param name="count">导出数量</param>
        public void WriteFile(StringBuilder datInfo, string fileName, DateTime exprotTime, int count)
        {
            //string exprot = applicatRoot + @"\exprotFile";

            string exprot = config.AppSettings.Settings["exprotFile"].Value;
            if (!Directory.Exists(exprot))
            {
                Directory.CreateDirectory(exprot);
            }

            string time = exprotTime.AddDays(-1).ToString("yyyyMMdd");
            string DATName = string.Format(exprot + @"\{0}{1}.DAT", fileName, time);
            string CTLName = string.Format(exprot + @"\{0}{1}.CTL", fileName, time);

            if (File.Exists(DATName)) File.Delete(DATName);
            if (File.Exists(CTLName)) File.Delete(CTLName);


            //写数据文件 DAT
            using (StreamWriter writer = new StreamWriter(DATName, true, Encoding.GetEncoding("GBK")))
            {
                writer.Write(datInfo);
            }

            //写控制文件 CLT
            if (File.Exists(DATName))
            {
                FileInfo f = new FileInfo(DATName);
                long fize = f.Length;
                string ctlInfo = Path.GetFileName(DATName) + "\t" + fize + "\t" + count + "\tGBK\tSTD_01\n";

                using (StreamWriter writer = new StreamWriter(CTLName, true, Encoding.GetEncoding("GBK")))
                {
                    writer.Write(ctlInfo);
                }
            }
        }
    }
}
复制代码

 

 

服务是不能直接运行的。必须安装。可以用SC执行。关于SC语法。可以网上搜索。比如:

打开cmd 命令提示窗口

创建服务:
//注意 = 号右边有空格
start= auto :开机自动启动
注意事项,每个=号之前 一定不要有空格    =号后面一定要有空格
sc create top1 binpath= "F:\cc.exe start= auto"


创建服务后开启服务
sc start top1

停止服务:
sc stop top

删除服务:
注意:如果服务没有停止。删除的话。服务还在。
sc delete top1

添加描述:

sc description top1 "描述"

 

如果代码有更新,则先停止服务。然后更新。在开启服务

 

当然,如果觉得麻烦,可以写一个bat文件

 

创建服务

@echo.SyncDataService服务创建中......  
@echo off  
@sc create SyncDataService binPath= ""%cd%\SyncDataService.exe"  
@sc config SyncDataService start= AUTO
@sc description SyncDataService "这里是服务的描述"
@echo off  
@echo 创建完毕!  
@pause

 

启动服务:

@echo.SyncDataService服务启动中......  
@echo off  
@sc start SyncDataService  
@echo off  
@echo 启动完毕!  
@pause

 

停止服务:

@echo.服务关闭  
@echo off  
@net stop SyncDataService  
@echo off  
@echo.关闭结束!  
@pause 

 

删除服务:

@echo.服务删除  
@echo off  
@sc delete SyncDataService  
@echo off  
@echo.删除结束!  
@pause 

 

这仅仅是一个记录。没什么高级部分。。。。。

 

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
'
点击右上角即可分享
微信分享提示