终端一体化运控平台
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

473 rader
18 KiB

  1. using BeDesignerSCADA.Controls;
  2. using BeDesignerSCADA.ViewModel;
  3. using BPA.Communication;
  4. using BPA.Helper;
  5. using BPASmart.Model;
  6. using System;
  7. using System.Collections.Concurrent;
  8. using System.Collections.Generic;
  9. using System.Collections.ObjectModel;
  10. using System.Diagnostics;
  11. using System.IO;
  12. using System.Linq;
  13. using System.Text;
  14. using System.Threading;
  15. using System.Threading.Tasks;
  16. using System.Windows;
  17. using System.Windows.Forms;
  18. namespace BPASmart.ConfigurationSoftware
  19. {
  20. /// <summary>
  21. /// 服务中心
  22. /// </summary>
  23. public class ServiceCenter
  24. {
  25. private volatile static ServiceCenter _Instance;
  26. public static ServiceCenter GetInstance => _Instance ?? (_Instance = new ServiceCenter());
  27. private ServiceCenter() { }
  28. private PipeServer pipeServer { get; set; } = new PipeServer(PipeTopic.PipeName);
  29. private ConcurrentQueue<string> msg { get; set; } = new ConcurrentQueue<string>();
  30. public ObservableCollection<string> Message { get; set; } = new ObservableCollection<string>();
  31. public List<MainCanvasPageModel> mainCanvasPanels { get; set; } = new List<MainCanvasPageModel>();
  32. public ObservableCollection<string> Pages { get; set; } = new ObservableCollection<string>();
  33. /// <summary>
  34. /// 页面切换委托
  35. /// </summary>
  36. public Action<FrameworkElement> PageChange { get; set; }
  37. /// <summary>
  38. /// 项目名称改变委托
  39. /// </summary>
  40. public Action<string> ProjectNameChange { get; set; }
  41. public void Init()
  42. {
  43. MessageLog.GetInstance.NotifyShow = new Action<string>((o) => { App.Current.Dispatcher.Invoke(() => { Message.Add(o); }); });
  44. MessageLog.GetInstance.NotifyShowEx = new Action<string>((o) => { App.Current.Dispatcher.Invoke(() => { Message.Add(o); }); });
  45. PipeMsgMonitor();
  46. ProjectStartInit();
  47. PageAdd();
  48. }
  49. /// <summary>
  50. /// 退出通知
  51. /// </summary>
  52. public void ExitNotify()
  53. {
  54. pipeServer.SendCommand(PipeTopic.ExitNotify);
  55. }
  56. /// <summary>
  57. /// 管道消息监听,和服务启动
  58. /// </summary>
  59. private void PipeMsgMonitor()
  60. {
  61. ThreadManage.GetInstance().StartLong(new Action(() =>
  62. {
  63. while (msg.Count > 0)
  64. {
  65. if (msg.TryDequeue(out string s))
  66. {
  67. if (s == PipeTopic.VarSave)
  68. {
  69. DataBusModel.GetInstance().RefreshVariableManager(FileConfigModel.VarConfigPath);
  70. for (int i = 0; i < mainCanvasPanels.Count; i++)
  71. {
  72. mainCanvasPanels.ElementAt(i).MainCanvasPanelModel.VariableManagerPath(FileConfigModel.VarConfigPath);
  73. }
  74. }
  75. else
  76. {
  77. MessageLog.GetInstance.Show(s);
  78. }
  79. }
  80. }
  81. Thread.Sleep(100);
  82. }), "管道消息控制");
  83. pipeServer.PushCommand = new Action<string>((o) => { msg.Enqueue(o); });
  84. pipeServer.StartPipeStream();
  85. }
  86. /// <summary>
  87. /// 通过项目启动文件加载的数据初始化
  88. /// </summary>
  89. private void ProjectStartInit()
  90. {
  91. if (Json<ProjectModel>.Data.ProjectName != null && Json<ProjectModel>.Data.ProjectName.Length > 0)
  92. {
  93. ProjectNameChange?.Invoke(Json<ProjectModel>.Data.ProjectName);
  94. FileConfigModel.ConstPath = Json<ProjectModel>.Data.ProjectPath;
  95. DataBusModel.GetInstance().RefreshVariableManager(FileConfigModel.VarConfigPath);
  96. }
  97. if (Json<ProjectModel>.Data.Pages?.Count > 0)
  98. {
  99. for (int i = 0; i < Json<ProjectModel>.Data.Pages.Count; i++)
  100. {
  101. Pages.Add(Json<ProjectModel>.Data.Pages.ElementAt(i).Key);
  102. }
  103. }
  104. }
  105. /// <summary>
  106. /// 保存配置
  107. /// </summary>
  108. private void Save()
  109. {
  110. string path = Json<ProjectModel>.Data.ProjectPath;
  111. string name = Json<ProjectModel>.Data.ProjectName;
  112. var pages = Json<ProjectModel>.Data.Pages.OrderBy(p => p.Key).ToDictionary(p => p.Key, s => s.Value);
  113. if (pages != null) Json<ProjectModel>.Data.Pages = pages;
  114. Json<ProjectModel>.Save($"{path}\\{name}.project");
  115. }
  116. /// <summary>
  117. /// 页面添加委托设置
  118. /// </summary>
  119. private void PageAdd()
  120. {
  121. ActionManage.GetInstance.Register(new Action<object>((o) =>
  122. {
  123. if (Pages.Count <= 0)
  124. {
  125. Serialization<BinConfigFile>.Data.StartPageName = o.ToString();
  126. Serialization<BinConfigFile>.Save($"{FileConfigModel.GetBinConfigPath}");
  127. }
  128. Pages.Add(o.ToString());
  129. string path = $"{ Json<ProjectModel>.Data.ProjectPath}\\{FileConfigModel.PageDirName}";
  130. Directory.CreateDirectory(path);
  131. File.WriteAllText($"{path}\\{o.ToString()}.lay", null, Encoding.Unicode);
  132. Json<ProjectModel>.Data.Pages.TryAdd(o.ToString(), $"{path}\\{o.ToString()}.lay");
  133. }), "AddPage");
  134. }
  135. /// <summary>
  136. /// 打开新建项目弹窗
  137. /// </summary>
  138. public void OpenNewProjectWindow()
  139. {
  140. NewProjectView newProjectView = new NewProjectView();
  141. bool? result = newProjectView.ShowDialog();
  142. if (result != null && result == true)
  143. {
  144. if (newProjectView.Tag != null && newProjectView.Tag is NewProjectModel objModel)
  145. {
  146. string path = $"{objModel.ProjectPath}\\{objModel.ProjectName}";
  147. Directory.CreateDirectory(path);
  148. Json<ProjectModel>.Data.ProjectPath = path;
  149. Json<ProjectModel>.Data.ProjectName = objModel.ProjectName;
  150. ProjectNameChange?.Invoke(objModel.ProjectName);
  151. FileConfigModel.ConstPath = $"{path}";
  152. Save();
  153. //FileHelper.GetInstance.RegisterOpenFileType();
  154. RegisterOpenFileType();
  155. }
  156. }
  157. }
  158. /// <summary>
  159. /// 注册使用默认应用程序打开自定义文件
  160. /// </summary>
  161. private void RegisterOpenFileType()
  162. {
  163. try
  164. {
  165. string icoFile = System.Windows.Forms.Application.StartupPath + $"\\Images\\fyf.ico";
  166. string DirectoryPath = $"{Json<ProjectModel>.Data.ProjectPath}\\Images";
  167. Directory.CreateDirectory(DirectoryPath);
  168. File.Copy(icoFile, $"{DirectoryPath}\\fyf.ico");
  169. SystemHelper.GetInstance.RegisterOpenFileType("project", "HBL", System.Windows.Forms.Application.ExecutablePath, $"{DirectoryPath}\\fyf.ico");
  170. }
  171. catch (Exception ex)
  172. {
  173. }
  174. }
  175. /// <summary>
  176. /// 打开新建页面弹窗
  177. /// </summary>
  178. public void OpenNewPageWindow()
  179. {
  180. NewPageView newPageView = new NewPageView();
  181. newPageView.ShowDialog();
  182. }
  183. /// <summary>
  184. /// 打开变量管理器工具
  185. /// </summary>
  186. public void OpenVariableManagerTool()
  187. {
  188. Json<LocalPar>.Data.ProjectPath = Json<ProjectModel>.Data.ProjectPath;
  189. FileConfigModel.ConstPath = Json<ProjectModel>.Data.ProjectPath;
  190. Json<LocalPar>.Save();
  191. if (File.Exists(FileConfigModel.VarManagerPath))
  192. {
  193. Process[] pro = Process.GetProcesses();
  194. if (pro?.ToList().FirstOrDefault(p => p.ProcessName.Contains("BPASmart.VariableManager")) == null)
  195. {
  196. Process.Start(FileConfigModel.VarManagerPath);
  197. }
  198. }
  199. }
  200. /// <summary>
  201. /// 选中页面
  202. /// </summary>
  203. /// <param name="o"></param>
  204. public void SelectedPage(object o)
  205. {
  206. string path = $"{Json<ProjectModel>.Data.ProjectPath}\\{FileConfigModel.PageDirName}\\{o.ToString()}.lay";
  207. if (mainCanvasPanels.FirstOrDefault(p => p.PageName == o.ToString()) == null)
  208. {
  209. mainCanvasPanels.Add(new MainCanvasPageModel()
  210. {
  211. MainCanvasPanelModel = new MainCanvasPanel(path),
  212. PageName = o.ToString(),
  213. });
  214. }
  215. int index = Array.FindIndex(mainCanvasPanels.ToArray(), p => p.PageName == o.ToString());
  216. if (index >= 0 && index < mainCanvasPanels.Count)
  217. {
  218. mainCanvasPanels.ElementAt(index).MainCanvasPanelModel.VariableManagerPath(FileConfigModel.VarConfigPath);
  219. PageChange?.Invoke(mainCanvasPanels.ElementAt(index).MainCanvasPanelModel);
  220. }
  221. }
  222. /// <summary>
  223. /// 删除指定界面
  224. /// </summary>
  225. /// <param name="o"></param>
  226. public void RemovePageCommand(object o)
  227. {
  228. MessageLog.GetInstance.Show($"准备删除页面:{o.ToString()}");
  229. if (!string.IsNullOrEmpty(o?.ToString()))
  230. {
  231. if (Pages.FirstOrDefault(p => p == o.ToString()) != null)
  232. {
  233. Pages.Remove(o.ToString());
  234. if (Json<ProjectModel>.Data.Pages.ContainsKey(o.ToString()))
  235. Json<ProjectModel>.Data.Pages.Remove(o.ToString());
  236. string path = $"{FileConfigModel.ConstPath}\\{FileConfigModel.PageDirName}\\{o.ToString()}.lay";
  237. if (File.Exists(path)) File.Delete(path);
  238. if (!File.Exists(path)) MessageLog.GetInstance.Show($"页面 {o.ToString()} 删除成功");
  239. else MessageLog.GetInstance.Show($"页面 {o.ToString()} 删除失败");
  240. }
  241. }
  242. }
  243. /// <summary>
  244. /// 设置界面为启动界面
  245. /// </summary>
  246. /// <param name="o"></param>
  247. public void SetStartPageCommand(object o)
  248. {
  249. if (!string.IsNullOrEmpty(o?.ToString()))
  250. {
  251. Serialization<BinConfigFile>.Data.StartPageName = o.ToString();
  252. Serialization<BinConfigFile>.Save($"{FileConfigModel.GetBinConfigPath}");
  253. }
  254. MessageLog.GetInstance.Show($"当前启动页面:{Serialization<BinConfigFile>.Data.StartPageName}");
  255. }
  256. /// <summary>
  257. /// 重命名界面名称
  258. /// </summary>
  259. /// <param name="o"></param>
  260. public void ReNameCommand(object o)
  261. {
  262. if (!string.IsNullOrEmpty(o?.ToString()))
  263. {
  264. MessageLog.GetInstance.Show($"页面 {o.ToString()}重命名");
  265. }
  266. }
  267. /// <summary>
  268. /// 项目保存
  269. /// </summary>
  270. public void ProjectSave()
  271. {
  272. for (int i = 0; i < mainCanvasPanels.Count; i++)
  273. {
  274. mainCanvasPanels.ElementAt(i).MainCanvasPanelModel.FileSave();
  275. }
  276. Save();
  277. MessageLog.GetInstance.Show("项目保存成功");
  278. }
  279. /// <summary>
  280. /// 运行项目
  281. /// </summary>
  282. /// <returns></returns>
  283. public async Task RunProjectAsync()
  284. {
  285. MessageLog.GetInstance.Show("启动中....");
  286. await ApplicationBaleAsync();
  287. string publishPath = $"{FileConfigModel.ConstPath}\\Publish\\{Json<ProjectModel>.Data.ProjectName}\\";
  288. string name = $" {publishPath}{ Json<ProjectModel>.Data.ProjectName}.exe";
  289. if (File.Exists(name))
  290. {
  291. Process[] pro = Process.GetProcesses();
  292. if (pro?.ToList().FirstOrDefault(p => p.ProcessName.Contains("BPASmart.PageLoad")) == null)
  293. {
  294. Process.Start(name);
  295. }
  296. }
  297. MessageLog.GetInstance.Show("启动完成");
  298. }
  299. /// <summary>
  300. /// 打开项目
  301. /// </summary>
  302. public void OpenProject()
  303. {
  304. OpenFileDialog ofd = new OpenFileDialog();
  305. ofd.Filter = "项目|*.project;";
  306. if (ofd.ShowDialog() == DialogResult.OK)
  307. {
  308. Json<ProjectModel>.Read(ofd.FileName);
  309. var pages = Json<ProjectModel>.Data.Pages.OrderBy(p => p.Key).ToDictionary(p => p.Key, s => s.Value);
  310. ProjectStartInit();
  311. }
  312. }
  313. /// <summary>
  314. /// 应用程序打包程序
  315. /// </summary>
  316. public async Task ApplicationBaleAsync()
  317. {
  318. ProjectSave();
  319. await Task.Factory.StartNew(new Action(() =>
  320. {
  321. if (string.IsNullOrEmpty(FileConfigModel.ConstPath))
  322. {
  323. MessageLog.GetInstance.Show("打包路径不合法,打包失败");
  324. return;
  325. }
  326. string publishPath = $"{FileConfigModel.ConstPath}\\Publish";
  327. if (Directory.Exists(publishPath))
  328. {
  329. MessageLog.GetInstance.Show("清理旧数据");
  330. Directory.Delete(publishPath, true);
  331. }
  332. MessageLog.GetInstance.Show("开始打包");
  333. string path = $"{FileConfigModel.ConstPath}\\Publish\\{Json<ProjectModel>.Data.ProjectName}";
  334. Directory.CreateDirectory(path);
  335. MessageLog.GetInstance.Show($"打包路径:{path}");
  336. //打包组件
  337. string dllPath = AppDomain.CurrentDomain.BaseDirectory;
  338. if (Directory.Exists(dllPath)) CopyFolder(dllPath, $"{path}", new string[] { FileConfigModel.ConfigDirName, "Videos" });
  339. //打包配置文件
  340. string ConfigFilePath = $"{FileConfigModel.ConstPath}\\{FileConfigModel.ConfigDirName}";
  341. if (Directory.Exists(ConfigFilePath)) CopyFolder(ConfigFilePath, $"{path}\\{FileConfigModel.ConfigDirName}");
  342. //打包页面文件
  343. string pageFilePath = $"{FileConfigModel.ConstPath}\\{FileConfigModel.PageDirName}";
  344. if (Directory.Exists(pageFilePath)) CopyFolder(pageFilePath, $"{path}\\{FileConfigModel.PageDirName}");
  345. //打包图片文件资源
  346. string imageFilePath = $"{FileConfigModel.ConstPath}\\{FileConfigModel.ImageDirName}";
  347. if (Directory.Exists(imageFilePath)) CopyFolder(imageFilePath, $"{path}\\{FileConfigModel.ImageDirName}");
  348. MessageLog.GetInstance.Show("打包完成");
  349. }));
  350. }
  351. /// <summary>
  352. /// 复制文件夹及文件
  353. /// </summary>
  354. /// <param name="sourceFolder">原文件路径</param>
  355. /// <param name="destFolder">目标文件路径</param>
  356. /// <returns></returns>
  357. private int CopyFolder(string sourceFolder, string destFolder, string[] FilterFolders = null)
  358. {
  359. try
  360. {
  361. Directory.CreateDirectory(destFolder);
  362. //得到原文件根目录下的所有文件
  363. string[] files = Directory.GetFiles(sourceFolder);
  364. foreach (string file in files)
  365. {
  366. string name = Path.GetFileName(file);
  367. if (name.Contains("BPASmart.PageLoad.exe"))
  368. {
  369. name = $"{Json<ProjectModel>.Data.ProjectName}.exe";
  370. }
  371. string dest = Path.Combine(destFolder, name);
  372. File.Copy(file, dest);//复制文件
  373. }
  374. //AccessFile,Videos
  375. //得到原文件根目录下的所有文件夹
  376. var folders = Directory.GetDirectories(sourceFolder)?.ToList();
  377. FilterFolders?.ToList()?.ForEach(item =>
  378. {
  379. int index = Array.FindIndex(folders.ToArray(), p => p.Contains(item));
  380. if (index >= 0 && index < folders.Count)
  381. {
  382. folders.RemoveAt(index);
  383. }
  384. });
  385. foreach (string folder in folders)
  386. {
  387. //if (FilterFolders!=null && FilterFolders.ToList()?.FirstOrDefault(p=>p.Contains()))
  388. string name = Path.GetFileName(folder);
  389. string dest = Path.Combine(destFolder, name);
  390. CopyFolder(folder, dest);//构建目标路径,递归复制文件
  391. }
  392. return 1;
  393. }
  394. catch (Exception e)
  395. {
  396. return -1;
  397. }
  398. }
  399. /// <summary>
  400. /// 创建快捷方式
  401. /// </summary>
  402. /// <returns></returns>
  403. private bool CreateShortcut(string name, string path)
  404. {
  405. string deskTop = string.Empty;
  406. try
  407. {
  408. if (System.IO.File.Exists($"{path}{name}.lnk")) return true;
  409. IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell();
  410. IWshRuntimeLibrary.IWshShortcut shortcut = shell.CreateShortcut($"{path}{name}.lnk") as IWshRuntimeLibrary.IWshShortcut;
  411. shortcut.TargetPath = path; //目标文件
  412. //该属性指定应用程序的工作目录,当用户没有指定一个具体的目录时,快捷方式的目标应用程序将使用该属性所指定的目录来装载或保存文件。
  413. shortcut.WorkingDirectory = System.Environment.CurrentDirectory;
  414. shortcut.WindowStyle = 1; //目标应用程序的窗口状态分为普通、最大化、最小化【1,3,7】
  415. shortcut.Description = name; //描述
  416. //shortcut.IconLocation = exePath + "\\logo.ico"; //快捷方式图标
  417. shortcut.Arguments = "";
  418. shortcut.Save(); //必须调用保存快捷才成创建成功
  419. return true;
  420. }
  421. catch (Exception ex)
  422. {
  423. MessageLog.GetInstance.ShowEx(ex.ToString());
  424. return false;
  425. }
  426. }
  427. }
  428. }