From ad39eae8ad4309f91d09800e7ebcbc0bec8015b5 Mon Sep 17 00:00:00 2001 From: sc <2401809606@qq.com> Date: Sat, 19 Jul 2025 00:20:39 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=95=B0=E6=8D=AE=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ProcessManageUI.sln | 25 + ProcessManageUI/App.config | 6 + ProcessManageUI/App.xaml | 9 + ProcessManageUI/App.xaml.cs | 17 + ProcessManageUI/ClsLock.cs | 138 ++++ ProcessManageUI/IniFile.cs | 52 ++ ProcessManageUI/LogGing.cs | 118 +++ ProcessManageUI/MainWindow.xaml | 13 + ProcessManageUI/MainWindow.xaml.cs | 125 ++++ ProcessManageUI/ProcessManage.db | Bin 0 -> 16384 bytes ProcessManageUI/ProcessManageUI.csproj | 108 +++ ProcessManageUI/Properties/AssemblyInfo.cs | 52 ++ .../Properties/Resources.Designer.cs | 71 ++ ProcessManageUI/Properties/Resources.resx | 117 +++ .../Properties/Settings.Designer.cs | 30 + ProcessManageUI/Properties/Settings.settings | 7 + ProcessManageUI/SqliteHelper.cs | 686 ++++++++++++++++++ 17 files changed, 1574 insertions(+) create mode 100644 ProcessManageUI.sln create mode 100644 ProcessManageUI/App.config create mode 100644 ProcessManageUI/App.xaml create mode 100644 ProcessManageUI/App.xaml.cs create mode 100644 ProcessManageUI/ClsLock.cs create mode 100644 ProcessManageUI/IniFile.cs create mode 100644 ProcessManageUI/LogGing.cs create mode 100644 ProcessManageUI/MainWindow.xaml create mode 100644 ProcessManageUI/MainWindow.xaml.cs create mode 100644 ProcessManageUI/ProcessManage.db create mode 100644 ProcessManageUI/ProcessManageUI.csproj create mode 100644 ProcessManageUI/Properties/AssemblyInfo.cs create mode 100644 ProcessManageUI/Properties/Resources.Designer.cs create mode 100644 ProcessManageUI/Properties/Resources.resx create mode 100644 ProcessManageUI/Properties/Settings.Designer.cs create mode 100644 ProcessManageUI/Properties/Settings.settings create mode 100644 ProcessManageUI/SqliteHelper.cs diff --git a/ProcessManageUI.sln b/ProcessManageUI.sln new file mode 100644 index 0000000..c01e309 --- /dev/null +++ b/ProcessManageUI.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36202.13 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProcessManageUI", "ProcessManageUI\ProcessManageUI.csproj", "{6DA7C6F9-C096-481A-B9E1-C19E72C35E58}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6DA7C6F9-C096-481A-B9E1-C19E72C35E58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6DA7C6F9-C096-481A-B9E1-C19E72C35E58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6DA7C6F9-C096-481A-B9E1-C19E72C35E58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6DA7C6F9-C096-481A-B9E1-C19E72C35E58}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {DFE05529-79C8-4D27-B69B-CEFF2B5C8F5C} + EndGlobalSection +EndGlobal diff --git a/ProcessManageUI/App.config b/ProcessManageUI/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/ProcessManageUI/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ProcessManageUI/App.xaml b/ProcessManageUI/App.xaml new file mode 100644 index 0000000..55bb5a9 --- /dev/null +++ b/ProcessManageUI/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/ProcessManageUI/App.xaml.cs b/ProcessManageUI/App.xaml.cs new file mode 100644 index 0000000..c916a77 --- /dev/null +++ b/ProcessManageUI/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace ProcessManageUI +{ + /// + /// App.xaml 的交互逻辑 + /// + public partial class App : Application + { + } +} diff --git a/ProcessManageUI/ClsLock.cs b/ProcessManageUI/ClsLock.cs new file mode 100644 index 0000000..b8bd4e9 --- /dev/null +++ b/ProcessManageUI/ClsLock.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace ProcessManageUI +{ + /// + /// 使用using代替lock操作的对象,可指定写入和读取锁定模式 + /// + public sealed class ClsLock + { + #region 内部类 + + /// + /// 利用IDisposable的using语法糖方便的释放锁定操作内部类 + /// + private struct Lock : IDisposable + { + /// + /// 读写锁对象 + /// + private readonly ReaderWriterLockSlim _Lock; + /// + /// 是否为写入模式 + /// + private bool _IsWrite; + /// + /// 利用IDisposable的using语法糖方便的释放锁定操作构造函数 + /// + /// 读写锁 + /// 写入模式为true,读取模式为false + public Lock(ReaderWriterLockSlim rwl, bool isWrite) + { + _Lock = rwl; + _IsWrite = isWrite; + } + /// + /// 释放对象时退出指定锁定模式 + /// + public void Dispose() + { + if (_IsWrite) + { + if (_Lock.IsWriteLockHeld) + { + _Lock.ExitWriteLock(); + } + } + else + { + if (_Lock.IsReadLockHeld) + { + _Lock.ExitReadLock(); + } + } + } + } + + /// + /// 空的可释放对象,免去了调用时需要判断是否为null的问题内部类 + /// + private class Disposable : IDisposable + { + /// + /// 空的可释放对象 + /// + public static readonly Disposable Empty = new Disposable(); + /// + /// 空的释放方法 + /// + public void Dispose() { } + } + + #endregion + + /// + /// 读写锁 + /// + private readonly ReaderWriterLockSlim _LockSlim = new ReaderWriterLockSlim(); + /// + /// 使用using代替lock操作的对象,可指定写入和读取锁定模式构造函数 + /// + public ClsLock() + { + Enabled = true; + } + /// + /// 是否启用,当该值为false时,Read()和Write()方法将返回 Disposable.Empty + /// + public bool Enabled { get; set; } + + /// + /// 进入读取锁定模式,该模式下允许多个读操作同时进行, + /// 退出读锁请将返回对象释放,建议使用using语块, + /// Enabled为false时,返回Disposable.Empty, + /// 在读取或写入锁定模式下重复执行,返回Disposable.Empty; + /// + public IDisposable Read() + { + if (Enabled == false || _LockSlim.IsReadLockHeld || _LockSlim.IsWriteLockHeld) + { + return Disposable.Empty; + } + else + { + _LockSlim.EnterReadLock(); + return new Lock(_LockSlim, false); + } + } + + /// + /// 进入写入锁定模式,该模式下只允许同时执行一个读操作, + /// 退出读锁请将返回对象释放,建议使用using语块, + /// Enabled为false时,返回Disposable.Empty, + /// 在写入锁定模式下重复执行,返回Disposable.Empty + /// + /// 读取模式下不能进入写入锁定状态 + public IDisposable Write() + { + if (Enabled == false || _LockSlim.IsWriteLockHeld) + { + return Disposable.Empty; + } + else if (_LockSlim.IsReadLockHeld) + { + throw new NotImplementedException("读取模式下不能进入写入锁定状态"); + } + else + { + _LockSlim.EnterWriteLock(); + return new Lock(_LockSlim, true); + } + } + } +} diff --git a/ProcessManageUI/IniFile.cs b/ProcessManageUI/IniFile.cs new file mode 100644 index 0000000..4796dad --- /dev/null +++ b/ProcessManageUI/IniFile.cs @@ -0,0 +1,52 @@ +using System.Runtime.InteropServices; +using System.Text; + +namespace ProcessManageUI +{ + internal class IniFile + { + public class IniFiles + { + public string path; + [DllImport("kernel32")] //返回0表示失败,非0为成功 + private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); + [DllImport("kernel32")] //返回取得字符串缓冲区的长度 + private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath); + /// + /// 保存ini文件的路径 + /// 调用示例:var ini = IniFiles("C:\file.ini"); + /// + /// + public IniFiles(string iniPath) + { + this.path = iniPath; + } + /// + /// 写Ini文件 + /// 调用示例:ini.IniWritevalue("Server","name","localhost"); + /// + /// [缓冲区] + /// 键 + /// 值 + public void IniWritevalue(string Section, string Key, string value) + { + WritePrivateProfileString(Section, Key, value, this.path); + } + /// + /// 读Ini文件 + /// 调用示例:ini.IniWritevalue("Server","name"); + /// + /// [缓冲区] + /// 键 + /// + public string IniReadvalue(string Section, string Key) + { + StringBuilder temp = new StringBuilder(255); + + int i = GetPrivateProfileString(Section, Key, "", temp, 255, this.path); + return temp.ToString(); + } + + } + } +} diff --git a/ProcessManageUI/LogGing.cs b/ProcessManageUI/LogGing.cs new file mode 100644 index 0000000..31b90ff --- /dev/null +++ b/ProcessManageUI/LogGing.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; + +namespace ProcessManageUI +{ + public class LogGing + { + public static void LogGingDATA(string dat) + { + string logpath = System.Environment.CurrentDirectory + "\\Log";//日志文件目录 + string logPath = "" + System.Environment.CurrentDirectory + "\\Log\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";//日志文件 + string Log_time = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]:"; + + if (Directory.Exists(logpath))//检查日志路径 + { + if (!File.Exists(logPath))//检查日志文件并写入启动日志 + { + FileStream fs = new FileStream(logPath, FileMode.CreateNew, FileAccess.Write);//创建写入文件 + StreamWriter wr = new StreamWriter(fs);//创建文件 + wr.WriteLine(Log_time + dat); + wr.Close(); + } + else + { + try + { + FileStream fs = new FileStream(logPath, FileMode.Append, FileAccess.Write); + StreamWriter wr = new StreamWriter(fs);//创建文件 + wr.WriteLine(Log_time + dat); + wr.Close(); + } + catch { } + } + } + else + { + DirectoryInfo directoryInfo = new DirectoryInfo(logpath); + directoryInfo.Create();//创建日志路径 + } + } + public static void ERRDATA(System.Exception dat) + { + string Log_time = DateTime.Now.ToString("yyyy-MM-dd"); + string logpath = System.Environment.CurrentDirectory + "\\ERR";//日志文件目录 + // string logPathtxt = "" + System.Environment.CurrentDirectory + "\\Log\\"+ Log_time + "Log.txt";//日志文件 + // System.IO.DirectoryInfo log = new System.IO.DirectoryInfo();//生成日志文件目录 + string log_path = logpath + "\\ERR" + Log_time + ".txt"; + string Log_timehms = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + if (Directory.Exists(logpath))//检查日志路径 + { + if (!File.Exists(log_path))//检查文件并写入 + { + // FileStream fs = new FileStream(log_path, FileMode.CreateNew, FileAccess.Write);//创建文件 + // StreamWriter wr = new StreamWriter(fs);//创建文件 + // wr.Close(); + FileStream fil = new FileStream(log_path, FileMode.CreateNew, FileAccess.Write);//创建写入文件 + StreamWriter wfil = new StreamWriter(fil);//创建文件 + wfil.WriteLine("[" + Log_timehms + "];[Error] ||" + Environment.NewLine.ToString()); + wfil.WriteLine("[" + Log_timehms + "];[Error source] ||" + dat.Source.ToString() + Environment.NewLine.ToString()); + wfil.WriteLine("[" + Log_timehms + "];[Error message] ||" + dat.Message.ToString() + Environment.NewLine.ToString()); + wfil.WriteLine("[" + Log_timehms + "];[Error area] ||" + dat.StackTrace.ToString()); + wfil.Close(); + } + else + { + FileStream fs = new FileStream(log_path, FileMode.Append, FileAccess.Write);//创建写入文件 + StreamWriter wr = new StreamWriter(fs);//创建文件 + wr.WriteLine("[" + Log_timehms + "];[Error] ||" + Environment.NewLine.ToString()); + wr.WriteLine("[" + Log_timehms + "];[Error source] ||" + dat.ToString() + Environment.NewLine.ToString()); + wr.WriteLine("[" + Log_timehms + "];[Error message] ||" + dat.Message.ToString() + Environment.NewLine.ToString()); + wr.WriteLine("[" + Log_timehms + "];[Error area] ||" + dat.ToString()); + wr.Close(); + } + } + else + { + DirectoryInfo directoryInfo = new DirectoryInfo(logpath); + directoryInfo.Create(); + } + } + public static void ExchangeDATA(string dat) + { + string Log_time = DateTime.Now.ToString("yyyy-MM-dd"); + string logpath = System.Environment.CurrentDirectory + "\\Exchange";//日志文件目录 + // string logPathtxt = "" + System.Environment.CurrentDirectory + "\\Log\\"+ Log_time + "Log.txt";//日志文件 + // System.IO.DirectoryInfo log = new System.IO.DirectoryInfo();//生成日志文件目录 + string log_path = logpath + "\\Exchange" + Log_time + ".txt"; + string Log_timehms = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + if (Directory.Exists(logpath))//检查日志路径 + { + if (!File.Exists(log_path))//检查文件并写入 + { + // FileStream fs = new FileStream(log_path, FileMode.CreateNew, FileAccess.Write);//创建文件 + // StreamWriter wr = new StreamWriter(fs);//创建文件 + // wr.Close(); + FileStream fil = new FileStream(log_path, FileMode.CreateNew, FileAccess.Write);//创建写入文件 + StreamWriter wfil = new StreamWriter(fil);//创建文件 + wfil.WriteLine("[" + Log_timehms + "];[Exchange] ||" + dat); + wfil.Close(); + } + else + { + FileStream fs = new FileStream(log_path, FileMode.Append, FileAccess.Write);//创建写入文件 + StreamWriter wr = new StreamWriter(fs);//创建文件 + wr.WriteLine("[" + Log_timehms + "];[Exchange] ||" + dat); + wr.Close(); + } + } + else + { + DirectoryInfo directoryInfo = new DirectoryInfo(logpath); + directoryInfo.Create(); + } + } + } +} diff --git a/ProcessManageUI/MainWindow.xaml b/ProcessManageUI/MainWindow.xaml new file mode 100644 index 0000000..bf52c66 --- /dev/null +++ b/ProcessManageUI/MainWindow.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/ProcessManageUI/MainWindow.xaml.cs b/ProcessManageUI/MainWindow.xaml.cs new file mode 100644 index 0000000..7a96b27 --- /dev/null +++ b/ProcessManageUI/MainWindow.xaml.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Windows.Threading; +using static ProcessManageUI.SqliteHelper; +using static System.Net.WebRequestMethods; + +namespace ProcessManageUI +{ + /// + /// MainWindow.xaml 的交互逻辑 + /// + public partial class MainWindow : Window + { + private static IniFile.IniFiles Configini = new IniFile.IniFiles(Convert.ToString(System.AppDomain.CurrentDomain.BaseDirectory) + "ProcessManageConfigini.ini"); + private static string SQLIP = Configini.IniReadvalue("SQL_SERVER", "SQL1"); //读配置文件 + private static string SQLNAME = Configini.IniReadvalue("SQL_SERVER", "SQL2"); + private static string SQMOD = Configini.IniReadvalue("SQL_SERVER", "SQL3"); + private static string SQLUSER = Configini.IniReadvalue("SQL_SERVER", "SQL4"); + private static string SQLPASWORD = Configini.IniReadvalue("SQL_SERVER", "SQL5"); + private static DataTable DyelotsBulkedRecipe = new DataTable(); + private static DataTable Product = new DataTable(); + private static DataTable Gram = new DataTable(); + private static int Count = 0; + private static readonly int _intervalMs = int.Parse(Configini.IniReadvalue("SQL_SERVER", "SQL6")); + private static SQLiteHelper SQLiteHelpers = null; //定义数据库 + private readonly static string DBAddress = Environment.CurrentDirectory + "\\ProcessManage.db"; //数据库路径 + + //设置定时器 + DispatcherTimer disTimer = new DispatcherTimer + { + Interval = TimeSpan.FromMilliseconds(_intervalMs) //毫秒 + }; + public MainWindow() + { + InitializeComponent(); + + SQLiteHelpers = new SQLiteHelper(DBAddress); //数据库连接路径 + SQLiteHelpers.Open(); //打开数据库 + Gram = SQLiteHelpers.ExecuteDataSet("select * from Gram", null).Tables[0]; //读取表写入缓存 + Product = SQLiteHelpers.ExecuteDataSet("select * from ProcessManage", null).Tables[0]; + SQLiteHelpers.Close(); + + disTimer.Tick += EXTask; + disTimer.Start();//计时开始 + } + + + private void EXTask(object sender, EventArgs e) + { + disTimer.Stop();//停止计时 + string Connstr_SC; + string DyelotsBulkedRecipe_sql = "SELECT * FROM [dbo].[DyelotsBulkedRecipe] WHERE Created > '" + + DateTime.Now.AddDays(-1).ToString("yyyy/MM/dd") + "' AND ProductType = '1' AND Process IS NULL"; + try + { + DyelotsBulkedRecipe.Clear(); + Datalog.Text = null; + + if (SQMOD == "Windows Authentication") + { + Connstr_SC = "server=" + SQLIP + ";database=" + SQLNAME + ";Trusted_Connection=SSPI"; + } + else + { + Connstr_SC = "server=" + SQLIP + ";database=" + SQLNAME + ";User ID=" + SQLUSER + ";Password=" + SQLPASWORD; + } + SqlConnection conn_SC = new SqlConnection(Connstr_SC); + conn_SC.OpenAsync(); //连接数据库 + SqlDataAdapter DyelotsBulkedRecipe_ = new SqlDataAdapter(DyelotsBulkedRecipe_sql, Connstr_SC); + conn_SC.Close(); + DyelotsBulkedRecipe_.Fill(DyelotsBulkedRecipe); + + for (int i = DyelotsBulkedRecipe.Rows.Count; i > 0; i--) + { + if (DyelotsBulkedRecipe.Rows.Count <= 0) { break; }//跳出循环 + + string Dyelot = DyelotsBulkedRecipe.Rows[0].Field("Dyelot"); + double gram = 0; + int type_id = 0; + DataRow[] rowdat = DyelotsBulkedRecipe.Select("Dyelot ='" + Dyelot + "'");//行 + + foreach (DataRow row in rowdat)//删除指定信息行 + { + row.Field("ProductCode"); + gram += row.Field("Grams"); + row.Delete(); + row.AcceptChanges(); + } + + + + Count++; + Datalog.AppendText("\n" + DateTime.Now.ToString("yyyy/MM/dd-HH:mm:ss") + " 转换工单:" + Dyelot + "流程:"); + LogGing.LogGingDATA( "转换工单:" + Dyelot + "流程:"); + } + Datalog.AppendText("\n" + DateTime.Now.ToString("yyyy/MM/dd-HH:mm:ss") + $" 转换{Count}条"); + Count = 0; + } + catch (Exception ex) + {//错误处理 + LogGing.ERRDATA(ex); + Datalog.AppendText(ex.ToString()); + } + finally + { + disTimer.Start();//计时开始 + } + } + } +} diff --git a/ProcessManageUI/ProcessManage.db b/ProcessManageUI/ProcessManage.db new file mode 100644 index 0000000000000000000000000000000000000000..bb47c685ff6aaa3a730dc2a1217565ed23fa57f8 GIT binary patch literal 16384 zcmeI3PfQ$D9LL|hHv_w~JM(DiGP|=tr;1$=w(Kt5kdzD9kfouJR!M52hK#VSBwe7e zZSW=s8}y=yf5NfGq>@w*rp91;QsdFolLupJVp43IXgt_xdg|}Z&a&@q{gZeS^BXd6 z-o7utf1lrbOP0Vhr%x_a%ih_gm5N{WhDaOHG&1UWgb)jEJ-jt|wuEzd1eaL*r^_No z&fc@^D}>rpgfH1s@W2ZRAOR$R1dsp{Kmter2_OL^fCTnBfzx`clSpXmM%91ue7UsZ zSH#VZKRrG+Gw#idJ#}*26DwZt^w`w6cgbIwd&yrJ@G1+7-oj!PCjMG&GV}6sSdM0Gu)>@rRMq7U_@N{ZrX|BAwI^{3==gP_ps-&(+UN5|y zzc^PtzBFHMKnxeB{ffFM0zC3vyL`ome8ztu{64=254?~75tQ|rFZ+8Zp7}!zK*>eyA)rGorw*{ocI~@_xOnT+It`|VcgvY=cUj{YHk;FkB&*Er8Xu=WkJGpCsgq*#g)c z+nn~O(CnopcVW1eD#OCwq;osIOkgu4COAW$8??9cx>)sc|fQSQgc& zEd7Kmsx4*K^TZWBdGrLNdt@`U(=7E^u#szKN)^nWAW6~3z@yZ})FH`4X+3ie1{*ds zY3zOGbW4KNJLYuBLZfjk>4ESk(YINb(<#|V4P|LJs5Ct3>Y1SFlq{-fseKMML$W;x zSu>Xk-llw3{P}p=kv*s&scQ)_dVAyY&O7fnwbhNwni|@T$(q_!*OWCiU@9u!xWahq z`AkMcgF;E^X@@Sz)st+z1$8iaz0n1Jlk6izqZ=@Zh>6o85QPq8L>-3YK{~h{R9csM zbwCpbFLbnfKH$fa19!`Q14fO)5JXM3N(Cu94!$F}_yhhM|ApV-Kl1PSxAj$gA^{|T v1dsp{Kmter2_OL^fCP{L5^S*@Q?c~!Ds}d9*is)X)tO!{BqzSl)#!6 literal 0 HcmV?d00001 diff --git a/ProcessManageUI/ProcessManageUI.csproj b/ProcessManageUI/ProcessManageUI.csproj new file mode 100644 index 0000000..0dd25fa --- /dev/null +++ b/ProcessManageUI/ProcessManageUI.csproj @@ -0,0 +1,108 @@ + + + + + Debug + AnyCPU + {6DA7C6F9-C096-481A-B9E1-C19E72C35E58} + WinExe + ProcessManageUI + ProcessManageUI + v4.7.2 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + MainWindow.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + 1.0.119 + + + + \ No newline at end of file diff --git a/ProcessManageUI/Properties/AssemblyInfo.cs b/ProcessManageUI/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4ea1142 --- /dev/null +++ b/ProcessManageUI/Properties/AssemblyInfo.cs @@ -0,0 +1,52 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("ProcessManageUI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ProcessManageUI")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +//若要开始生成可本地化的应用程序,请设置 +//.csproj 文件中的 CultureYouAreCodingWith +//在 中。例如,如果你使用的是美国英语。 +//使用的是美国英语,请将 设置为 en-US。 然后取消 +//对以下 NeutralResourceLanguage 特性的注释。 更新 +//以下行中的“en-US”以匹配项目文件中的 UICulture 设置。 + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //主题特定资源词典所处位置 + //(未在页面中找到资源时使用, + //或应用程序资源字典中找到时使用) + ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置 + //(未在页面中找到资源时使用, + //、应用程序或任何主题专用资源字典中找到时使用) +)] + + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ProcessManageUI/Properties/Resources.Designer.cs b/ProcessManageUI/Properties/Resources.Designer.cs new file mode 100644 index 0000000..c952be0 --- /dev/null +++ b/ProcessManageUI/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本: 4.0.30319.42000 +// +// 对此文件的更改可能导致不正确的行为,如果 +// 重新生成代码,则所做更改将丢失。 +// +//------------------------------------------------------------------------------ + +namespace ProcessManageUI.Properties +{ + + + /// + /// 强类型资源类,用于查找本地化字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// 返回此类使用的缓存 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ProcessManageUI.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 重写当前线程的 CurrentUICulture 属性,对 + /// 使用此强类型资源类的所有资源查找执行重写。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/ProcessManageUI/Properties/Resources.resx b/ProcessManageUI/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/ProcessManageUI/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ProcessManageUI/Properties/Settings.Designer.cs b/ProcessManageUI/Properties/Settings.Designer.cs new file mode 100644 index 0000000..56e4ea1 --- /dev/null +++ b/ProcessManageUI/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ProcessManageUI.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/ProcessManageUI/Properties/Settings.settings b/ProcessManageUI/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/ProcessManageUI/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/ProcessManageUI/SqliteHelper.cs b/ProcessManageUI/SqliteHelper.cs new file mode 100644 index 0000000..bd8eeae --- /dev/null +++ b/ProcessManageUI/SqliteHelper.cs @@ -0,0 +1,686 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Data; +using System.IO; +using System.Data.Common; +using System.Windows.Media.Animation; +using System.Data.SQLite; +using System.Windows.Shapes; +using System.Drawing; + + +namespace ProcessManageUI +{ + public class SqliteHelper + { + + public class SQLiteHelper + { + #region 字段 + + /// + /// 事务的基类 + /// + private DbTransaction DBtrans; + /// + /// 使用静态变量字典解决多线程实例本类,实现一个数据库对应一个clslock + /// + private static readonly Dictionary RWL = new Dictionary(); + /// + /// 数据库地址 + /// + private readonly string mdataFile; + /// + /// 数据库密码 + /// + private readonly string mPassWord; + private readonly string LockName = null; + /// + /// 数据库连接定义 + /// + private SQLiteConnection mConn; + + #endregion + + #region 构造函数 + + /// + /// 根据数据库地址初始化 + /// + /// 数据库地址 + public SQLiteHelper(string dataFile) + { + this.mdataFile = dataFile ?? throw new ArgumentNullException("dataFile=null"); + //this.mdataFile = AppDomain.CurrentDomain.BaseDirectory + dataFile; + this.mdataFile = dataFile; + if (!RWL.ContainsKey(dataFile)) + { + LockName = dataFile; + RWL.Add(dataFile, new ClsLock()); + } + } + + /// + /// 使用密码打开数据库 + /// + /// 数据库地址 + /// 数据库密码 + public SQLiteHelper(string dataFile, string PassWord) + { + this.mdataFile = dataFile ?? throw new ArgumentNullException("dataFile is null"); + this.mPassWord = PassWord ?? throw new ArgumentNullException("PassWord is null"); + //this.mdataFile = AppDomain.CurrentDomain.BaseDirectory + dataFile; + this.mdataFile = dataFile; + if (!RWL.ContainsKey(dataFile)) + { + LockName = dataFile; + RWL.Add(dataFile, new ClsLock()); + } + } + + #endregion + + #region 打开/关闭 数据库 + + /// + /// 打开 SQLiteManager 使用的数据库连接 + /// + public void Open() + { + if (string.IsNullOrWhiteSpace(mPassWord)) + { + mConn = OpenConnection(this.mdataFile); + } + else + { + mConn = OpenConnection(this.mdataFile, mPassWord); + } + Console.WriteLine("The database was opened successfully"); + } + + /// + /// 关闭连接 + /// + public void Close() + { + if (this.mConn != null) + { + try + { + this.mConn.Close(); + if (RWL.ContainsKey(LockName)) + { + RWL.Remove(LockName); + } + } + catch + { + Console.WriteLine("Shutdown failed"); + } + } + Console.WriteLine("The database was shut down successfully"); + } + + #endregion + + #region 事务 + + /// + /// 开始事务 + /// + public void BeginTrain() + { + EnsureConnection(); + DBtrans = mConn.BeginTransaction(); + } + + /// + /// 提交事务 + /// + public void DBCommit() + { + try + { + DBtrans.Commit(); + } + catch (Exception) + { + DBtrans.Rollback(); + } + } + + #endregion + + #region 工具 + + /// + /// 打开一个SQLite数据库文件,如果文件不存在,则创建(无密码) + /// + /// + /// SQLiteConnection 类 + private SQLiteConnection OpenConnection(string dataFile) + { + if (dataFile == null) + { + throw new ArgumentNullException("dataFiledataFile=null"); + } + if (!File.Exists(dataFile)) + { + SQLiteConnection.CreateFile(dataFile); + } + SQLiteConnection conn = new SQLiteConnection(); + SQLiteConnectionStringBuilder conStr = new SQLiteConnectionStringBuilder + { + DataSource = dataFile + }; + conn.ConnectionString = conStr.ToString(); + conn.Open(); + return conn; + } + + /// + /// 打开一个SQLite数据库文件,如果文件不存在,则创建(有密码) + /// + /// + /// + /// SQLiteConnection 类 + private SQLiteConnection OpenConnection(string dataFile, string Password) + { + if (dataFile == null) + { + throw new ArgumentNullException("dataFile=null"); + } + if (!File.Exists(Convert.ToString(dataFile))) + { + SQLiteConnection.CreateFile(dataFile); + } + try + { + SQLiteConnection conn = new SQLiteConnection(); + SQLiteConnectionStringBuilder conStr = new SQLiteConnectionStringBuilder + { + DataSource = dataFile, + Password = Password + }; + conn.ConnectionString = conStr.ToString(); + conn.Open(); + return conn; + } + catch (Exception) + { + return null; + } + } + + /// + /// 读取 或 设置 SQLiteManager 使用的数据库连接 + /// + public SQLiteConnection Connection + { + get + { + return mConn; + } + private set + { + mConn = value ?? throw new ArgumentNullException(); + } + } + + /// + /// 确保数据库是连接状态 + /// + /// + protected void EnsureConnection() + { + if (this.mConn == null) + { + throw new Exception("SQLiteManager.Connection=null"); + } + if (mConn.State != ConnectionState.Open) + { + mConn.Open(); + } + } + + /// + /// 获取数据库文件的路径 + /// + /// + public string GetDataFile() + { + return this.mdataFile; + } + + /// + /// 判断表 table 是否存在 + /// + /// + /// 存在返回true,否则返回false + public bool TableExists(string table) + { + if (table == null) + { + throw new ArgumentNullException("table=null"); + } + EnsureConnection(); + SQLiteDataReader reader = ExecuteReader("SELECT count(*) as c FROM sqlite_master WHERE type='table' AND name=@tableName ", new SQLiteParameter[] { new SQLiteParameter("tableName", table) }); + if (reader == null) + { + return false; + } + reader.Read(); + int c = reader.GetInt32(0); + reader.Close(); + reader.Dispose(); + //return false; + return c == 1; + } + + /// + /// VACUUM 命令(通过复制主数据库中的内容到一个临时数据库文件,然后清空主数据库,并从副本中重新载入原始的数据库文件) + /// + /// + public bool Vacuum() + { + try + { + using (SQLiteCommand Command = new SQLiteCommand("VACUUM", Connection)) + { + Command.ExecuteNonQuery(); + } + return true; + } + catch (System.Data.SQLite.SQLiteException) + { + return false; + } + } + + #endregion + + #region 执行SQL + + /// + /// 执行SQL, 并返回 SQLiteDataReader 对象结果 + /// + /// + /// null 表示无参数 + /// + public SQLiteDataReader ExecuteReader(string sql, SQLiteParameter[] paramArr) + { + if (sql == null) + { + throw new ArgumentNullException("sql=null"); + } + EnsureConnection(); + using (RWL[LockName].Read()) + { + using (SQLiteCommand cmd = new SQLiteCommand(sql, Connection)) + { + if (paramArr != null) + { + cmd.Parameters.AddRange(paramArr); + } + try + { + SQLiteDataReader reader = cmd.ExecuteReader(); + cmd.Parameters.Clear(); + return reader; + } + catch (Exception) + { + return null; + } + } + } + } + + /// + /// 执行查询,并返回dataset对象 + /// + /// SQL查询语句 + /// 参数数组 + /// + public DataSet ExecuteDataSet(string sql, SQLiteParameter[] paramArr) + { + if (sql == null) + { + throw new ArgumentNullException("sql=null"); + } + this.EnsureConnection(); + using (RWL[LockName].Read()) + { + using (SQLiteCommand cmd = new SQLiteCommand(sql, this.Connection)) + { + if (paramArr != null) + { + cmd.Parameters.AddRange(paramArr); + } + try + { + SQLiteDataAdapter da = new SQLiteDataAdapter(); + DataSet ds = new DataSet(); + da.SelectCommand = cmd; + da.Fill(ds); + cmd.Parameters.Clear(); + da.Dispose(); + return ds; + } + catch (Exception) + { + return null; + } + } + } + } + + /// + /// 执行SQL查询,并返回dataset对象。 + /// + /// 映射源表的名称 + /// SQL语句 + /// SQL参数数组 + /// + public DataSet ExecuteDataSet(string strTable, string sql, SQLiteParameter[] paramArr) + { + if (sql == null) + { + throw new ArgumentNullException("sql=null"); + } + this.EnsureConnection(); + using (RWL[LockName].Read()) + { + using (SQLiteCommand cmd = new SQLiteCommand(sql, this.Connection)) + { + if (paramArr != null) + { + cmd.Parameters.AddRange(paramArr); + } + try + { + SQLiteDataAdapter da = new SQLiteDataAdapter(); + DataSet ds = new DataSet(); + da.SelectCommand = cmd; + da.Fill(ds, strTable); + cmd.Parameters.Clear(); + da.Dispose(); + return ds; + } + catch (Exception) + { + return null; + } + } + } + } + + /// + /// 执行SQL,返回受影响的行数,可用于执行表创建语句,paramArr == null 表示无参数 + /// + /// + /// + public int ExecuteNonQuery(string sql, SQLiteParameter[] paramArr) + { + if (sql == null) + { + throw new ArgumentNullException("sql=null"); + } + this.EnsureConnection(); + using (RWL[LockName].Read()) + { + try + { + using (SQLiteCommand cmd = new SQLiteCommand(sql, Connection)) + { + if (paramArr != null) + { + foreach (SQLiteParameter p in paramArr) + { + cmd.Parameters.Add(p); + } + } + int c = cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + return c; + } + } + catch (SQLiteException) + { + return 0; + } + } + } + + /// + /// 执行SQL,返回结果集第一行,如果结果集为空,那么返回空 List(List.Count=0), + /// rowWrapper = null 时,使用 WrapRowToDictionary + /// + /// + /// + /// + public object ExecuteScalar(string sql, SQLiteParameter[] paramArr) + { + if (sql == null) + { + throw new ArgumentNullException("sql=null"); + } + this.EnsureConnection(); + using (RWL[LockName].Read()) + { + using (SQLiteCommand cmd = new SQLiteCommand(sql, Connection)) + { + if (paramArr != null) + { + cmd.Parameters.AddRange(paramArr); + } + try + { + object reader = cmd.ExecuteScalar(); + cmd.Parameters.Clear(); + cmd.Dispose(); + return reader; + } + catch (Exception) + { + return null; + } + } + } + } + + /// + /// 查询一行记录,无结果时返回 null,conditionCol = null 时将忽略条件,直接执行 select * from table + /// + /// 表名 + /// + /// + /// + public object QueryOne(string table, string conditionCol, object conditionVal) + { + if (table == null) + { + throw new ArgumentNullException("table=null"); + } + this.EnsureConnection(); + string sql = "select * from " + table; + if (conditionCol != null) + { + sql += " where " + conditionCol + "=@" + conditionCol; + } + object result = ExecuteScalar(sql, new SQLiteParameter[] { new SQLiteParameter(conditionCol, conditionVal) }); + return result; + } + + #endregion + + #region 增 删 改 + + /// + /// 执行 insert into 语句 + /// + /// + /// + /// + public int InsertData(string table, Dictionary entity) + { + if (table == null) + { + throw new ArgumentNullException("table=null"); + } + this.EnsureConnection(); + string sql = BuildInsert(table, entity); + return this.ExecuteNonQuery(sql, BuildParamArray(entity)); + } + + /// + /// 执行 update 语句,注意:如果 where = null,那么 whereParams 也为 null, + /// + /// 表名 + /// 要修改的列名和列名的值 + /// 查找符合条件的列 + /// where条件中参数的值 + /// + public int Update(string table, Dictionary entity, string where, SQLiteParameter[] whereParams) + { + if (table == null) + { + throw new ArgumentNullException("table=null"); + } + this.EnsureConnection(); + string sql = BuildUpdate(table, entity); + SQLiteParameter[] parameter = BuildParamArray(entity); + if (where != null) + { + sql += " where " + where; + if (whereParams != null) + { + SQLiteParameter[] newArr = new SQLiteParameter[(parameter.Length + whereParams.Length)]; + Array.Copy(parameter, newArr, parameter.Length); + Array.Copy(whereParams, 0, newArr, parameter.Length, whereParams.Length); + parameter = newArr; + } + } + return this.ExecuteNonQuery(sql, parameter); + } + + /// + /// 执行 delete from table 语句,where不必包含'where'关键字,where = null 时将忽略 whereParams + /// + /// + /// + /// + /// + public int Delete(string table, string where, SQLiteParameter[] whereParams) + { + if (table == null) + { + throw new ArgumentNullException("table=null"); + } + this.EnsureConnection(); + string sql = "delete from " + table + " "; + if (where != null) + { + sql += "where " + where; + } + return ExecuteNonQuery(sql, whereParams); + } + + /// + /// 将 Dictionary 类型数据 转换为 SQLiteParameter[] 类型 + /// + /// + /// + private SQLiteParameter[] BuildParamArray(Dictionary entity) + { + List list = new List(); + foreach (string key in entity.Keys) + { + list.Add(new SQLiteParameter(key, entity[key])); + } + if (list.Count == 0) + { + return null; + } + return list.ToArray(); + } + + /// + /// 将 Dictionary 类型数据 转换为 插入数据 的 SQL语句 + /// + /// 表名 + /// 字典 + /// + private string BuildInsert(string table, Dictionary entity) + { + StringBuilder buf = new StringBuilder(); + buf.Append("insert into ").Append(table); + buf.Append(" ("); + foreach (string key in entity.Keys) + { + buf.Append(key).Append(","); + } + buf.Remove(buf.Length - 1, 1); // 移除最后一个, + buf.Append(") "); + buf.Append("values("); + foreach (string key in entity.Keys) + { + buf.Append("@").Append(key).Append(","); // 创建一个参数 + } + buf.Remove(buf.Length - 1, 1); + buf.Append(") "); + + return buf.ToString(); + } + + /// + /// 将 Dictionary 类型数据 转换为 修改数据 的 SQL语句 + /// + /// 表名 + /// 字典 + /// + private string BuildUpdate(string table, Dictionary entity) + { + StringBuilder buf = new StringBuilder(); + buf.Append("update ").Append(table).Append(" set "); + foreach (string key in entity.Keys) + { + buf.Append(key).Append("=").Append("@").Append(key).Append(","); + } + buf.Remove(buf.Length - 1, 1); + buf.Append(" "); + return buf.ToString(); + } + + /// + /// 将 DataTable 转换为 Dictionary 类型数据 + /// + public Dictionary DataTableToDictionary(DataTable dataTable) + { + Dictionary result = new Dictionary(); + if (dataTable != null) + { + foreach (DataRow dataRow in dataTable.Rows) + { + foreach (DataColumn dataColumn in dataTable.Columns) + { + result.Add(dataColumn.ColumnName, dataRow[dataColumn].ToString()); + //result = Console.WriteLine(dataRow[dataColumn].ToString()); + //result.Add(dataColumn.ColumnName, dataRow[dataColumn].ToString())(new RepeatDictionaryComparer()); + } + } + } + else + { + result = null; + } + return result; + } + + } + #endregion + } +}