ParameterFileManager.cs 78 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows.Forms.VisualStyles;
  6. using System.Xml.Schema;
  7. using System.Xml;
  8. using System.IO;
  9. using Aitex.Core.RT.Log;
  10. using System.Text.RegularExpressions;
  11. using Aitex.Common.Util;
  12. using Aitex.Core.RT.Event;
  13. using Aitex.Core.Util;
  14. using Aitex.Core.Utilities;
  15. using Aitex.Core.WCF;
  16. using MECF.Framework.Common.OperationCenter;
  17. using MECF.Framework.Common.Properties;
  18. using MECF.Framework.Common.RecipeCenter;
  19. using System.Collections.ObjectModel;
  20. using Aitex.Core.RT.SCCore;
  21. using MECF.Framework.Common.DataCenter;
  22. using MECF.Framework.Common.ParameterCenter;
  23. using System.Linq;
  24. using MECF.Framework.Common.CommonData;
  25. namespace Aitex.Core.RT.ParameterCenter
  26. {
  27. public class ParameterFileManager : Singleton<ParameterFileManager>
  28. {
  29. //Recipe文件 统一放在 Recipes 文件夹下面
  30. public const string SourceModule = "Parameter";
  31. string _chamberId;
  32. private bool _recipeIsValid;
  33. private List<string> _validationErrors = new List<string>();
  34. private List<string> _validationWarnings = new List<string>();
  35. private Dictionary<int, Dictionary<string, string>> _parameterItems;
  36. IParameterFileContext _rcpContext;
  37. public ParameterFileManager()
  38. {
  39. _chamberId = SC.GetStringValue("System.EditParameter.EditChamberType");
  40. if (_chamberId == null)
  41. _chamberId = "Parameter";
  42. }
  43. public void Initialize(IParameterFileContext context)
  44. {
  45. Initialize(context, true);
  46. }
  47. public void Initialize(IParameterFileContext rcpContext, bool enableService)
  48. {
  49. _rcpContext = rcpContext == null ? new DefaultParameterFileContext() : rcpContext;
  50. CultureSupported.UpdateCoreCultureResource(CultureSupported.English);
  51. if (enableService)
  52. {
  53. Singleton<WcfServiceManager>.Instance.Initialize(new Type[]
  54. {
  55. typeof(ParameterService)
  56. });
  57. }
  58. var dir = string.Format("{0}{1}\\", PathManager.GetParameterDir(), "");
  59. DirectoryInfo di = new DirectoryInfo(dir);
  60. if (!di.Exists)
  61. {
  62. di.Create();
  63. }
  64. }
  65. private void ValidationEventHandler(object sender, ValidationEventArgs e)
  66. {
  67. switch (e.Severity)
  68. {
  69. case XmlSeverityType.Error:
  70. _validationErrors.Add(e.Message);
  71. _recipeIsValid = false;
  72. break;
  73. case XmlSeverityType.Warning:
  74. _validationWarnings.Add(e.Message);
  75. break;
  76. }
  77. }
  78. /// <summary>
  79. /// XML schema checking
  80. /// </summary>
  81. /// <param name="chamId"></param>
  82. /// <param name="parameterName"></param>
  83. /// <param name="parameterContent"></param>
  84. /// <param name="reason"></param>
  85. /// <returns></returns>
  86. public bool ValidateParameter(string chamberId, string parameterName, string parameterContent, out List<string> reason)
  87. {
  88. try
  89. {
  90. XmlDocument document = new XmlDocument();
  91. document.LoadXml(parameterContent);
  92. MemoryStream schemaStream = new MemoryStream(ASCIIEncoding.ASCII.GetBytes(GetParameterSchema(chamberId)));
  93. XmlReader xmlSchemaReader = XmlReader.Create(schemaStream);
  94. XmlSchema schema1 = XmlSchema.Read(xmlSchemaReader, ValidationEventHandler);
  95. document.Schemas.Add(schema1);
  96. document.LoadXml(parameterContent);
  97. ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
  98. _recipeIsValid = true;
  99. _validationErrors = new List<string>();
  100. _validationWarnings = new List<string>();
  101. // Validates recipe.
  102. document.Validate(eventHandler);
  103. }
  104. catch (Exception ex)
  105. {
  106. LOG.Write(ex.Message);
  107. _recipeIsValid = false;
  108. }
  109. if (!_recipeIsValid && _validationErrors.Count == 0)
  110. {
  111. _validationErrors.Add(Resources.RecipeFileManager_ValidateRecipe_XMLSchemaValidateFailed);
  112. }
  113. reason = _validationErrors;
  114. return _recipeIsValid;
  115. }
  116. public bool GetParameterChecked(string chamberId, string parameterName)
  117. {
  118. string chamberType = chamberId.Split('\\')[0];
  119. string processType = chamberId.Split('\\')[1];
  120. string parameterContent = LoadParameter(chamberId, parameterName, false);
  121. var xmlParameter = new XmlDocument();
  122. try
  123. {
  124. if (string.IsNullOrEmpty(parameterContent))
  125. throw new Exception("invalid Parameter file.");
  126. xmlParameter.LoadXml(parameterContent);
  127. XmlNodeList nodeSteps = xmlParameter.SelectNodes($"Aitex/TableParameterData/Module[@Name='{processType}']/Step");
  128. XmlNode nodeConfig = xmlParameter.SelectNodes($"Aitex/TableParameterData/Config")[0];
  129. foreach (var item in nodeSteps)
  130. {
  131. XmlElement step = item as XmlElement;
  132. string strModuleName = step.Attributes["ModuleName"]?.Value;
  133. if (string.IsNullOrEmpty(strModuleName)) continue;
  134. if (!string.IsNullOrEmpty(strModuleName))
  135. {
  136. string[] temp = strModuleName.Split(',')[0].Split(' ');
  137. if (temp.Length > 1)
  138. strModuleName = temp[1];
  139. }
  140. else
  141. continue;
  142. if (ovenModuleName.Contains(strModuleName))
  143. strModuleName = "Oven";
  144. string linkParameterName = step.Attributes["ParameterName"]?.Value;
  145. if (string.IsNullOrEmpty(linkParameterName)) continue;
  146. string[] subParameterNames = linkParameterName.Split(',');
  147. foreach (var subItem in subParameterNames)
  148. {
  149. string subParameterName = string.Empty;
  150. string[] subParameterNameStrings = subItem.Split(':');
  151. if (subParameterNameStrings.Length > 1)
  152. {
  153. subParameterName = subParameterNameStrings[1];
  154. }
  155. else
  156. {
  157. subParameterName = subParameterNameStrings[0];
  158. }
  159. if (!GetParameterChecked($"{_chamberId}\\{strModuleName}", subParameterName))
  160. {
  161. return false;
  162. }
  163. }
  164. }
  165. //check system Parameter
  166. string strSystemParameterName = nodeConfig.Attributes["SystemParameter"]?.Value;
  167. if (!string.IsNullOrEmpty(strSystemParameterName))
  168. {
  169. if (!GetParameterChecked($"{_chamberId}\\System", strSystemParameterName))
  170. {
  171. return false;
  172. }
  173. }
  174. XmlElement nodeData = xmlParameter.SelectSingleNode($"Aitex/TableParameterData") as XmlElement;
  175. string checkResult = nodeData.Attributes["CheckResult"].Value;
  176. if (string.IsNullOrEmpty(checkResult))
  177. return false;
  178. else
  179. return true;
  180. }
  181. catch (Exception ex)
  182. {
  183. LOG.Write(ex);
  184. return false;
  185. }
  186. }
  187. /// <summary>
  188. /// Check recipe content
  189. /// </summary>
  190. /// <param name="chamId"></param>
  191. /// <param name="parameterContent"></param>
  192. /// <param name="reasons"></param>
  193. /// <returns></returns>
  194. public bool CheckParameter(string chamberId, string parameterName, out List<string> reasons)
  195. {
  196. reasons = new List<string>();
  197. string chamberType = chamberId.Split('\\')[0];
  198. string processType = chamberId.Split('\\')[1];
  199. string parameterContent = LoadParameter(chamberId, parameterName, false);
  200. var xmlParameter = new XmlDocument();
  201. try
  202. {
  203. if (string.IsNullOrEmpty(parameterContent))
  204. throw new Exception("invalid Parameter file.");
  205. xmlParameter.LoadXml(parameterContent);
  206. XmlNodeList nodeSteps = xmlParameter.SelectNodes($"Aitex/TableParameterData/Module[@Name='{processType}']/Step");
  207. XmlNode nodeConfig = xmlParameter.SelectNodes($"Aitex/TableParameterData/Config")[0];
  208. }
  209. catch (Exception ex)
  210. {
  211. reasons.Add(ex.Message);
  212. LOG.Write(ex);
  213. return false;
  214. }
  215. XmlElement nodeData = xmlParameter.SelectSingleNode($"Aitex/TableParameterData") as XmlElement;
  216. bool bResult = reasons.Count == 0;
  217. if (bResult)
  218. {
  219. nodeData.SetAttribute("CheckResult", "Correct");
  220. }
  221. else
  222. {
  223. nodeData.SetAttribute("CheckResult", "Error");
  224. }
  225. SaveParameter(chamberId, parameterName, xmlParameter.OuterXml, false, false);
  226. return bResult;
  227. }
  228. /// <summary>
  229. /// Check recipe content
  230. /// </summary>
  231. /// <param name="chamId"></param>
  232. /// <param name="recipeContent"></param>
  233. /// <param name="reasons"></param>
  234. /// <returns></returns>
  235. public bool CheckRestoreParameter(string chamberId, string parameterName, out List<string> reasons)
  236. {
  237. reasons = new List<string>();
  238. string chamberType = chamberId.Split('\\')[0];
  239. string processType = chamberId.Split('\\')[1];
  240. string recipeContent = LoadRestoreParameter(chamberId, parameterName, false);
  241. var xmlRecipe = new XmlDocument();
  242. try
  243. {
  244. if (string.IsNullOrEmpty(recipeContent))
  245. throw new Exception("invalid recipe file.");
  246. xmlRecipe.LoadXml(recipeContent);
  247. XmlNodeList nodeSteps = xmlRecipe.SelectNodes($"Aitex/TableParameterData/Module[@Name='{processType}']/Step");
  248. XmlNode nodeConfig = xmlRecipe.SelectNodes($"Aitex/TableParameterData/Config")[0];
  249. }
  250. catch (Exception ex)
  251. {
  252. reasons.Add(ex.Message);
  253. LOG.Write(ex);
  254. return false;
  255. }
  256. XmlElement nodeData = xmlRecipe.SelectSingleNode($"Aitex/TableParameterData") as XmlElement;
  257. bool bResult = reasons.Count == 0;
  258. if (bResult)
  259. {
  260. nodeData.SetAttribute("CheckResult", "Correct");
  261. }
  262. else
  263. {
  264. nodeData.SetAttribute("CheckResult", "Error");
  265. }
  266. SaveRestoreParameter(chamberId, parameterName, xmlRecipe.OuterXml, false, false);
  267. return bResult;
  268. }
  269. /// <summary>
  270. /// This method will be invoked by two places:
  271. /// (1) Load a recipe from server to GUI for editing (do not need validation when loading, do validation when saving);
  272. /// (2) Load a recipe from recipe engine to run process(always do a validation before run recipe);
  273. /// </summary>
  274. /// <param name="parameterName"></param>
  275. /// <param name="needValidation">indicate whether a recipe format validation is needed or not</param>
  276. /// <returns></returns>
  277. public string LoadParameter(string chamberId, string parameterName, bool needValidation)
  278. {
  279. string rcp = string.Empty;
  280. try
  281. {
  282. using (StreamReader fs = new StreamReader(GenerateParameterFilePath(chamberId, parameterName)))
  283. {
  284. rcp = fs.ReadToEnd();
  285. fs.Close();
  286. }
  287. //if (needValidation)
  288. //{
  289. // List<string> reason;
  290. // if (!ValidateRecipe(chamberId, recipeName, rcp, out reason))
  291. // {
  292. // rcp = string.Empty;
  293. // LOG.Write("校验recipe file 出错, " + string.Join(",", reason.ToArray()));
  294. // }
  295. //}
  296. }
  297. catch (Exception ex)
  298. {
  299. LOG.Write(ex, $"load recipe file failed, {parameterName}");
  300. rcp = string.Empty;
  301. }
  302. return rcp;
  303. }
  304. /// <summary>
  305. /// Get recipe list
  306. /// </summary>
  307. /// <param name="chamId"></param>
  308. /// <param name="includingUsedRecipe"></param>
  309. /// <returns></returns>
  310. public IEnumerable<string> GetParameters(string chamberId, bool includingUsedRecipe)
  311. {
  312. return _rcpContext.GetParameters(chamberId, includingUsedRecipe);
  313. }
  314. /// <summary>
  315. /// Get recipe list in xml format
  316. /// </summary>
  317. /// <param name="chamId"></param>
  318. /// <param name="includingUsedParameter"></param>
  319. /// <returns></returns>
  320. public string GetXmlParameterList(string chamberId, bool includingUsedParameter)
  321. {
  322. XmlDocument doc = new XmlDocument();
  323. var baseFolderPath = getParameterDirPath(chamberId);
  324. DirectoryInfo curFolderInfo = new DirectoryInfo(baseFolderPath);
  325. doc.AppendChild(GenerateParameterList(chamberId, curFolderInfo, doc, includingUsedParameter));
  326. return doc.OuterXml;
  327. }
  328. public void SaveParameterHistory(string chamberId, string parameterName, string parameterContent, bool needSaveAs = true)
  329. {
  330. try
  331. {
  332. if (!string.IsNullOrEmpty(parameterName) && needSaveAs)
  333. {
  334. string newRecipeName = string.Format("HistoryParameter\\{0}\\{1}", DateTime.Now.ToString("yyyyMM"), parameterName);
  335. SaveParameter(chamberId, newRecipeName, parameterContent, true, false);
  336. LOG.Write(string.Format("{0}通知TM保存工艺程序{1}", chamberId, parameterName));
  337. }
  338. }
  339. catch (Exception ex)
  340. {
  341. LOG.Write(ex, string.Format("保存{0}工艺程序{1}发生错误", chamberId, parameterName));
  342. }
  343. }
  344. /// <summary>
  345. /// generate recipe list information in current directory
  346. /// </summary>
  347. /// <param name="chamId"></param>
  348. /// <param name="currentDir"></param>
  349. /// <param name="doc"></param>
  350. /// <returns></returns>
  351. XmlElement GenerateParameterList(string chamberId, DirectoryInfo currentDir, XmlDocument doc, bool includingUsedParameter)
  352. {
  353. int trimLength = getParameterDirPath(chamberId).Length;
  354. XmlElement folderEle = doc.CreateElement("Folder");
  355. folderEle.SetAttribute("Name", currentDir.FullName.Substring(trimLength));
  356. DirectoryInfo[] dirInfos = currentDir.GetDirectories();
  357. foreach (DirectoryInfo dirInfo in dirInfos)
  358. {
  359. if (!includingUsedParameter && dirInfo.Name == "HistoryParameter")
  360. continue;
  361. folderEle.AppendChild(GenerateParameterList(chamberId, dirInfo, doc, includingUsedParameter));
  362. }
  363. FileInfo[] fileInfos = currentDir.GetFiles("*.rcp");
  364. foreach (FileInfo fileInfo in fileInfos)
  365. {
  366. XmlElement fileNd = doc.CreateElement("File");
  367. string fileStr = fileInfo.FullName.Substring(trimLength).TrimStart(new char[] { '\\' }); ;
  368. fileStr = fileStr.Substring(0, fileStr.LastIndexOf("."));
  369. fileNd.SetAttribute("Name", fileStr);
  370. folderEle.AppendChild(fileNd);
  371. }
  372. return folderEle;
  373. }
  374. XmlElement GeneratelRestoreParameterList(string chamberId, DirectoryInfo currentDir, XmlDocument doc, bool includingUsedRecipe)
  375. {
  376. int trimLength = getParameterBackupDirPath(chamberId).Length;
  377. XmlElement folderEle = doc.CreateElement("Folder");
  378. var name = currentDir.FullName.Substring(trimLength);
  379. folderEle.SetAttribute("Name", name);
  380. DirectoryInfo[] dirInfos = currentDir.GetDirectories();
  381. foreach (DirectoryInfo dirInfo in dirInfos)
  382. {
  383. if (!includingUsedRecipe && dirInfo.Name == "HistoryParameter")
  384. continue;
  385. folderEle.AppendChild(GeneratelRestoreParameterList(chamberId, dirInfo, doc, includingUsedRecipe));
  386. }
  387. FileInfo[] fileInfos = currentDir.GetFiles("*.rcp");
  388. foreach (FileInfo fileInfo in fileInfos)
  389. {
  390. XmlElement fileNd = doc.CreateElement("File");
  391. string fileStr = fileInfo.FullName.Substring(trimLength).TrimStart(new char[] { '\\' }); ;
  392. fileStr = fileStr.Substring(0, fileStr.LastIndexOf("."));
  393. fileNd.SetAttribute("Name", fileStr);
  394. folderEle.AppendChild(fileNd);
  395. }
  396. return folderEle;
  397. }
  398. /// <summary>
  399. /// Delete a recipe by recipe name
  400. /// </summary>
  401. /// <param name="chamId"></param>
  402. /// <param name="parameterName"></param>
  403. /// <returns></returns>
  404. public bool DeleteParameter(string chamberId, string parameterName)
  405. {
  406. try
  407. {
  408. File.Delete(GenerateParameterFilePath(chamberId, parameterName));
  409. EventInfo(string.Format(Resources.RecipeFileManager_DeleteRecipe_RecipeFile0DeleteSucceeded, parameterName));
  410. }
  411. catch (Exception ex)
  412. {
  413. LOG.Write(ex, "删除recipe file 出错");
  414. EventWarning(string.Format(Resources.RecipeFileManager_DeleteRecipe_RecipeFile0DeleteFailed, parameterName));
  415. return false;
  416. }
  417. return true;
  418. }
  419. /// <summary>
  420. /// Rename recipe
  421. /// </summary>
  422. /// <param name="chamId"></param>
  423. /// <param name="oldName"></param>
  424. /// <param name="newName"></param>
  425. /// <returns></returns>
  426. public bool RenameParameter(string chamId, string oldName, string newName)
  427. {
  428. try
  429. {
  430. if (File.Exists(GenerateParameterFilePath(chamId, newName)))
  431. {
  432. EventWarning(string.Format(Resources.RecipeFileManager_RenameRecipe_RecipeFile0FileExisted, oldName));
  433. return false;
  434. }
  435. else
  436. {
  437. File.Move(GenerateParameterFilePath(chamId, oldName), GenerateParameterFilePath(chamId, newName));
  438. EventInfo(string.Format(Resources.RecipeFileManager_RenameRecipe_RecipeFile0Renamed, oldName, newName));
  439. }
  440. }
  441. catch (Exception ex)
  442. {
  443. LOG.Write(ex, "重命名recipe file 出错");
  444. EventWarning(string.Format(Resources.RecipeFileManager_RenameRecipe_RecipeFile0RenameFailed, oldName, newName));
  445. return false;
  446. }
  447. return true;
  448. }
  449. private static string ovenModuleName = "CPL,HHP,LHP,CHP,TCP";
  450. private string[] ovenModuleNames = ovenModuleName.Split(',');
  451. private void UpdateCheckResult(string parameterName)
  452. {
  453. var xmlRecipe = new XmlDocument();
  454. using (StreamReader fs = new StreamReader(parameterName))
  455. {
  456. string parameterContent = fs.ReadToEnd();
  457. fs.Close();
  458. xmlRecipe.LoadXml(parameterContent);
  459. }
  460. XmlNode nodeConfig = xmlRecipe.SelectNodes($"Aitex/TableParameterData")[0];
  461. nodeConfig.Attributes["CheckResult"].Value = string.Empty;
  462. XmlTextWriter writer = new XmlTextWriter(parameterName, Encoding.UTF8);
  463. writer.Formatting = Formatting.Indented;
  464. xmlRecipe.Save(writer);
  465. writer.Close();
  466. }
  467. public bool BackupParameter(string fileOriginalPath, string fileDestinationPath, bool isSaveLinkParameter, List<string> parameterNames)
  468. {
  469. try
  470. {
  471. }
  472. catch (Exception ex)
  473. {
  474. LOG.Write(ex, "Backup Recipe file error");
  475. }
  476. return true;
  477. }
  478. public bool CheckBackParameterIsLinkParameter(string fileOriginalPath, List<string> parameterNames)
  479. {
  480. string chamberType = fileOriginalPath.Split('\\')[0];
  481. string processType = fileOriginalPath.Split('\\')[1];
  482. foreach (var item in parameterNames)
  483. {
  484. string parameterContent = LoadParameter(fileOriginalPath, item, false);
  485. var xmlParameter = new XmlDocument();
  486. try
  487. {
  488. if (string.IsNullOrEmpty(parameterContent))
  489. continue;
  490. xmlParameter.LoadXml(parameterContent);
  491. XmlNodeList nodeSteps = xmlParameter.SelectNodes($"Aitex/TableParameterData/Module[@Name='{processType}']/Step");
  492. XmlNode nodeConfig = xmlParameter.SelectNodes($"Aitex/TableParameterData/Config")[0];
  493. switch (processType)
  494. {
  495. case "WaferFlow":
  496. foreach (var step in nodeSteps)
  497. {
  498. XmlElement nodestep = step as XmlElement;
  499. string strModuleName = nodestep.Attributes["ModuleName"]?.Value;
  500. if (string.IsNullOrEmpty(strModuleName))
  501. { continue; }
  502. var linkRecipeName = nodestep.Attributes["RecipeName"].Value;
  503. if (string.IsNullOrEmpty(linkRecipeName))
  504. { continue; }
  505. else
  506. {
  507. return true;
  508. }
  509. }
  510. string strSystemReicpeName = nodeConfig.Attributes["SystemRecipe"]?.Value;
  511. if (!string.IsNullOrEmpty(strSystemReicpeName))
  512. {
  513. return true;
  514. }
  515. break;
  516. case "COT":
  517. case "DEV":
  518. string pumpRecipeName = nodeConfig.Attributes["COTPumpRecipe"]?.Value;
  519. if (!string.IsNullOrEmpty(pumpRecipeName))
  520. {
  521. return true;
  522. }
  523. break;
  524. case "Dummy":
  525. foreach (var step in nodeSteps)
  526. {
  527. XmlElement nodestep = step as XmlElement;
  528. string regularSequence = nodestep.Attributes["RegularSequence"]?.Value;
  529. string preSequence = nodestep.Attributes["PreSequence"]?.Value;
  530. if (!string.IsNullOrEmpty(regularSequence))
  531. {
  532. string[] regularSequences = regularSequence.Split(';');
  533. foreach (var subItem in regularSequences)
  534. {
  535. if (string.IsNullOrEmpty(subItem)) continue;
  536. var pumpRecipe = GetKeyValue(subItem, "PumpRecipe");
  537. if (!string.IsNullOrEmpty(pumpRecipe)) return true;
  538. }
  539. }
  540. if (!string.IsNullOrEmpty(preSequence))
  541. {
  542. string[] preSequences = preSequence.Split(';');
  543. foreach (var subItem in preSequences)
  544. {
  545. if (string.IsNullOrEmpty(subItem)) continue;
  546. var pumpRecipe = GetKeyValue(subItem, "PumpRecipe");
  547. if (!string.IsNullOrEmpty(pumpRecipe)) return true;
  548. }
  549. }
  550. }
  551. break;
  552. case "Wash":
  553. foreach (var step in nodeSteps)
  554. {
  555. XmlElement nodestep = step as XmlElement;
  556. string sequence = nodestep.Attributes["Sequence"]?.Value;
  557. if (string.IsNullOrEmpty(sequence))
  558. { continue; }
  559. var subSequences = sequence.Split(';');
  560. foreach (var subSeq in subSequences)
  561. {
  562. if (string.IsNullOrEmpty(subSeq))
  563. {
  564. continue;
  565. }
  566. var pumpRecipe = GetKeyValue(subSeq, "PumpRecipe");
  567. if (!string.IsNullOrEmpty(subSeq))
  568. {
  569. return true;
  570. }
  571. }
  572. }
  573. break;
  574. case "ADH":
  575. case "Oven":
  576. break;
  577. }
  578. }
  579. catch (Exception ex)
  580. {
  581. LOG.Write(ex);
  582. return false;
  583. }
  584. }
  585. return false;
  586. }
  587. private static string GetKeyValue(string args, string name)
  588. {
  589. string indexString = $"{name}=";
  590. string subString = args.Substring(args.IndexOf(indexString) + indexString.Length);
  591. int endIndex = subString.IndexOf(',');
  592. if (endIndex > 0)
  593. return subString.Substring(0, endIndex);
  594. else
  595. return subString;
  596. }
  597. public string GetXmlRestoreParameterList(string chamberId, bool includingUsedParameter)
  598. {
  599. XmlDocument doc = new XmlDocument();
  600. var baseFolderPath = getParameterBackupDirPath(chamberId);
  601. DirectoryInfo curFolderInfo = new DirectoryInfo(baseFolderPath);
  602. doc.AppendChild(GeneratelRestoreParameterList(chamberId, curFolderInfo, doc, includingUsedParameter));
  603. return doc.OuterXml;
  604. }
  605. public List<string> RestoreParameterFolderList()
  606. {
  607. List<string> folderList = new List<string>();
  608. var parameterBackupPath = PathManager.GetParameterBackupDir();
  609. DirectoryInfo directoryInfo = new DirectoryInfo(parameterBackupPath);
  610. DirectoryInfo[] directoryInfos = directoryInfo.GetDirectories();
  611. foreach (var item in directoryInfos)
  612. {
  613. folderList.Add(item.Name);
  614. }
  615. return folderList;
  616. }
  617. public string LoadRestoreParameter(string chamberId, string parameterName, bool needValidation)
  618. {
  619. string rcp = string.Empty;
  620. try
  621. {
  622. using (StreamReader fs = new StreamReader(GenerateBackupParameterFilePath(chamberId, parameterName)))
  623. {
  624. rcp = fs.ReadToEnd();
  625. fs.Close();
  626. }
  627. }
  628. catch (Exception ex)
  629. {
  630. LOG.Write(ex, $"load recipe file failed, {parameterName}");
  631. rcp = string.Empty;
  632. }
  633. return rcp;
  634. }
  635. public bool SigRestoreParameter(string chamId, List<string> parameterNames)
  636. {
  637. try
  638. {
  639. string filePath = getParameterBackupDirPath(chamId);
  640. foreach (var item in parameterNames)
  641. {
  642. string strdest = chamId;
  643. string destFilePath = GenerateParameterFilePath(strdest, item);
  644. string sourceFilePath = GenerateBackupParameterFilePath(chamId, item);
  645. if (item.Contains("\\"))
  646. {
  647. DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(destFilePath));
  648. if (!di.Exists) di.Create();
  649. }
  650. File.Copy(sourceFilePath, destFilePath, true);
  651. }
  652. }
  653. catch (Exception ex)
  654. {
  655. LOG.Write(ex, "Backup Recipe file error");
  656. }
  657. return true;
  658. }
  659. private static Dictionary<string, List<string>> CreateRestoreDirectory = new Dictionary<string, List<string>>();
  660. private string RestoreDestFileCheck(string chamId, string parameterName)
  661. {
  662. string newParameterName = parameterName;
  663. //有文件夹的处理方式
  664. if (parameterName.Contains("\\"))
  665. {
  666. int index = 1;
  667. while (true)
  668. {
  669. int firstIndex = parameterName.IndexOf("\\");
  670. string firstStr = parameterName.Substring(0, firstIndex);
  671. string tempRecipeDirectory = "";
  672. string lastStr = parameterName.Substring(firstIndex + 1, parameterName.Length - firstStr.Length - 1);
  673. if (firstStr.Contains("(") && firstStr.Contains(")") && (firstStr.IndexOf("(") < firstStr.IndexOf(")")) && (firstStr.IndexOf(")") == firstStr.Length - 1))
  674. {
  675. var tempFirstStr = firstStr.Remove(firstStr.IndexOf("("), firstStr.IndexOf(")"));
  676. newParameterName = $"{tempFirstStr}({index}){lastStr}";
  677. tempRecipeDirectory = $"{tempFirstStr}({index})";
  678. }
  679. else
  680. {
  681. newParameterName = $"{firstStr}({index})\\{lastStr}";
  682. tempRecipeDirectory = $"{firstStr}({index})";
  683. }
  684. var fileName = getParameterDirPath(chamId) + newParameterName + ".rcp";
  685. DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(fileName));
  686. if (CreateRestoreDirectory.ContainsKey(chamId) && CreateRestoreDirectory[chamId].Contains(tempRecipeDirectory))
  687. {
  688. break;
  689. }
  690. else if (di.Exists)
  691. {
  692. index++;
  693. }
  694. else
  695. {
  696. if (!CreateRestoreDirectory.ContainsKey(chamId))
  697. {
  698. List<string> recipeDicectory = new List<string>();
  699. recipeDicectory.Add(tempRecipeDirectory);
  700. CreateRestoreDirectory.Add(chamId, recipeDicectory);
  701. }
  702. else
  703. {
  704. CreateRestoreDirectory[chamId].Add(tempRecipeDirectory);
  705. }
  706. di.Create();
  707. break;
  708. }
  709. }
  710. }
  711. //直接文件的处理方式
  712. else
  713. {
  714. int index = 1;
  715. while (true)
  716. {
  717. if (parameterName.Contains("(") && parameterName.Contains(")") && (parameterName.IndexOf("(") < parameterName.IndexOf(")")) && (parameterName.IndexOf(")") == parameterName.Length - 1))
  718. {
  719. var tempFirstStr = parameterName.Remove(parameterName.IndexOf("("), parameterName.IndexOf(")"));
  720. newParameterName = $"{tempFirstStr}({index})";
  721. }
  722. else
  723. {
  724. newParameterName = $"{parameterName}({index})";
  725. break;
  726. }
  727. }
  728. }
  729. return getParameterDirPath(chamId) + newParameterName + ".rcp";
  730. }
  731. public bool RestoreParameter(string chamId, bool isSaveLink, List<string> parameterNames)
  732. {
  733. try
  734. {
  735. string filePath = getParameterBackupDirPath(chamId);
  736. CreateRestoreDirectory.Clear();
  737. foreach (var item in parameterNames)
  738. {
  739. string strdest = chamId.Remove(5, 14);
  740. //string destFilePath = GenerateRecipeFilePath(strdest, item);
  741. string destFilePath = RestoreDestFileCheck(strdest, item);
  742. string sourceFilePath = GenerateBackupParameterFilePath(chamId, item);
  743. if (File.Exists(sourceFilePath))
  744. {
  745. DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(destFilePath));
  746. if (!di.Exists) di.Create();
  747. File.Copy(sourceFilePath, destFilePath, true);
  748. }
  749. if (isSaveLink)
  750. {
  751. string recipeContent = LoadRestoreParameter(chamId, item, false);
  752. var xmlRecipe = new XmlDocument();
  753. try
  754. {
  755. string chamberType = chamId.Split('\\')[0];
  756. string processType = chamId.Split('\\')[1];
  757. if (string.IsNullOrEmpty(recipeContent))
  758. continue;
  759. xmlRecipe.LoadXml(recipeContent);
  760. XmlNodeList nodeSteps = xmlRecipe.SelectNodes($"Aitex/TableRecipeData/Module[@Name='{processType}']/Step");
  761. XmlNode nodeConfig = xmlRecipe.SelectNodes($"Aitex/TableRecipeData/Config")[0];
  762. switch (processType)
  763. {
  764. case "WaferFlow":
  765. string strSystemReicpeName = nodeConfig.Attributes["SystemRecipe"]?.Value;
  766. if (!string.IsNullOrEmpty(strSystemReicpeName))
  767. {
  768. string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\System", strSystemReicpeName);
  769. string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\System", strSystemReicpeName);
  770. if (File.Exists(subSourceFilePath))
  771. {
  772. DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));
  773. if (!di.Exists) di.Create();
  774. File.Copy(subSourceFilePath, subDestFilePath, true);
  775. }
  776. }
  777. foreach (var step in nodeSteps)
  778. {
  779. XmlElement nodestep = step as XmlElement;
  780. string strModuleName = nodestep.Attributes["ModuleName"]?.Value;
  781. if (string.IsNullOrEmpty(strModuleName))
  782. { continue; }
  783. else
  784. {
  785. string[] temp = strModuleName.Split(',')[0].Split(' ');
  786. if (temp.Length > 1)
  787. strModuleName = temp[1];
  788. }
  789. var linkRecipeName = nodestep.Attributes["RecipeName"].Value;
  790. if (string.IsNullOrEmpty(linkRecipeName))
  791. { continue; }
  792. string[] subRecipeNames = linkRecipeName.Split(',');
  793. foreach (var subitem in subRecipeNames)
  794. {
  795. string subRecipeName = string.Empty;
  796. string[] subRecipeNameStrings = subitem.Split(':');
  797. if (subRecipeNameStrings.Length > 1)
  798. {
  799. subRecipeName = subRecipeNameStrings[1];
  800. }
  801. else
  802. {
  803. subRecipeName = subRecipeNameStrings[0];
  804. }
  805. if (ovenModuleName.Contains(strModuleName))
  806. {
  807. strModuleName = "Oven";
  808. }
  809. string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\{strModuleName}", subRecipeName);
  810. string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\{strModuleName}", subRecipeName);
  811. if (File.Exists(subSourceFilePath))
  812. {
  813. DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));
  814. if (!di.Exists) di.Create();
  815. File.Copy(subSourceFilePath, subDestFilePath, true);
  816. }
  817. if (strModuleName == "COT")
  818. {
  819. string subCotPath = GenerateBackupParameterFilePath($"{ _chamberId}\\{strModuleName}", subRecipeName);
  820. var subXmlRecipe = new XmlDocument();
  821. string subRecipeContent = LoadParameter($"{ _chamberId}\\{strModuleName}", subRecipeName, false);
  822. if (string.IsNullOrEmpty(subRecipeContent))
  823. continue;
  824. subXmlRecipe.LoadXml(subRecipeContent);
  825. XmlNode subNodeConfig = subXmlRecipe.SelectNodes($"Aitex/TableRecipeData/Config")[0];
  826. string subPumpRecipeName = subNodeConfig.Attributes["COTPumpRecipe"]?.Value;
  827. if (!string.IsNullOrEmpty(subPumpRecipeName))
  828. {
  829. string subPumpSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\Pump", subPumpRecipeName);
  830. string subPumpDestFilePath = RestoreDestFileCheck($"{_chamberId}\\Pump", subPumpRecipeName);
  831. if (File.Exists(subPumpSourceFilePath))
  832. {
  833. DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subPumpDestFilePath));
  834. if (!di.Exists) di.Create();
  835. File.Copy(subPumpSourceFilePath, subPumpDestFilePath, true);
  836. }
  837. }
  838. }
  839. }
  840. }
  841. break;
  842. case "COT":
  843. case "DEV":
  844. string pumpRecipeName = nodeConfig.Attributes["COTPumpRecipe"]?.Value;
  845. if (!string.IsNullOrEmpty(pumpRecipeName))
  846. {
  847. string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\Pump", pumpRecipeName);
  848. string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\Pump", pumpRecipeName);
  849. if (File.Exists(subSourceFilePath))
  850. {
  851. DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));
  852. if (!di.Exists) di.Create();
  853. File.Copy(subSourceFilePath, subDestFilePath, true);
  854. }
  855. }
  856. break;
  857. case "Dummy":
  858. foreach (var step in nodeSteps)
  859. {
  860. XmlElement nodestep = step as XmlElement;
  861. string regularSequence = nodestep.Attributes["RegularSequence"]?.Value;
  862. string preSequence = nodestep.Attributes["PreSequence"]?.Value;
  863. if (!string.IsNullOrEmpty(regularSequence))
  864. {
  865. string[] regularSequences = regularSequence.Split(';');
  866. foreach (var subItem in regularSequences)
  867. {
  868. if (string.IsNullOrEmpty(subItem)) continue;
  869. var pumpRecipe = GetKeyValue(subItem, "PumpRecipe");
  870. if (!string.IsNullOrEmpty(pumpRecipe))
  871. {
  872. string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\Pump", pumpRecipe);
  873. string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\Pump", pumpRecipe);
  874. if (File.Exists(subSourceFilePath))
  875. {
  876. DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));
  877. if (!di.Exists) di.Create();
  878. File.Copy(subSourceFilePath, subDestFilePath, true);
  879. }
  880. }
  881. }
  882. }
  883. if (!string.IsNullOrEmpty(preSequence))
  884. {
  885. string[] preSequences = preSequence.Split(';');
  886. foreach (var subItem in preSequences)
  887. {
  888. if (string.IsNullOrEmpty(subItem)) continue;
  889. var pumpRecipe = GetKeyValue(item, "PumpRecipe");
  890. if (!string.IsNullOrEmpty(pumpRecipe))
  891. {
  892. string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\Pump", pumpRecipe);
  893. string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\Pump", pumpRecipe);
  894. if (File.Exists(subSourceFilePath))
  895. {
  896. DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));
  897. if (!di.Exists) di.Create();
  898. File.Copy(subSourceFilePath, subDestFilePath, true);
  899. }
  900. }
  901. }
  902. }
  903. }
  904. break;
  905. case "Wash":
  906. foreach (var step in nodeSteps)
  907. {
  908. XmlElement nodestep = step as XmlElement;
  909. string sequence = nodestep.Attributes["Sequence"]?.Value;
  910. if (string.IsNullOrEmpty(sequence))
  911. { continue; }
  912. var subSequences = sequence.Split(';');
  913. foreach (var subSeq in subSequences)
  914. {
  915. if (string.IsNullOrEmpty(subSeq))
  916. {
  917. continue;
  918. }
  919. var pumpRecipe = GetKeyValue(subSeq, "PumpRecipe");
  920. if (!string.IsNullOrEmpty(pumpRecipe))
  921. {
  922. string subSourceFilePath = GenerateBackupParameterFilePath($"{chamId.Split('\\')[0]}\\Pump", pumpRecipe);
  923. string subDestFilePath = RestoreDestFileCheck($"{_chamberId}\\Pump", pumpRecipe);
  924. if (File.Exists(subSourceFilePath))
  925. {
  926. DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(subDestFilePath));
  927. if (!di.Exists) di.Create();
  928. File.Copy(subSourceFilePath, subDestFilePath, true);
  929. }
  930. }
  931. }
  932. }
  933. break;
  934. case "ADH":
  935. case "Oven":
  936. break;
  937. }
  938. }
  939. catch (Exception ex)
  940. {
  941. LOG.Write(ex);
  942. continue;
  943. }
  944. }
  945. }
  946. }
  947. catch (Exception ex)
  948. {
  949. LOG.Write(ex, "Backup Parameter file error");
  950. }
  951. return true;
  952. }
  953. private void EventInfo(string message)
  954. {
  955. _rcpContext.PostInfoEvent(message);
  956. }
  957. private void EventWarning(string message)
  958. {
  959. _rcpContext.PostWarningEvent(message);
  960. }
  961. private void EventAlarm(string message)
  962. {
  963. _rcpContext.PostAlarmEvent(message);
  964. }
  965. private void InfoDialog(string message)
  966. {
  967. _rcpContext.PostInfoDialogMessage(message);
  968. }
  969. private void WarningDialog(string message)
  970. {
  971. _rcpContext.PostWarningDialogMessage(message);
  972. }
  973. //private void AlarmDialog(string message)
  974. //{
  975. // _rcpContext.PostAlarmDialogMessage(message);
  976. //}
  977. private void EventDialog(string message, List<string> reason)
  978. {
  979. string msg = message;
  980. foreach (var r in reason)
  981. {
  982. msg += "\r\n" + r;
  983. }
  984. _rcpContext.PostDialogEvent(msg);
  985. }
  986. /// <summary>
  987. /// get recipe's file path
  988. /// </summary>
  989. /// <param name="parameterName"></param>
  990. /// <returns></returns>
  991. public string GenerateParameterFilePath(string chamId, string parameterName)
  992. {
  993. return getParameterDirPath(chamId) + parameterName + ".rcp";
  994. }
  995. private string GenerateBackupParameterFilePath(string chamId, string parameterName)
  996. {
  997. return getParameterBackupDirPath(chamId) + parameterName + ".rcp";
  998. }
  999. /// <summary>
  1000. /// get recipe's dir path
  1001. /// </summary>
  1002. /// <param name="recipeName"></param>
  1003. /// <returns></returns>
  1004. private string getParameterDirPath(string chamId)
  1005. {
  1006. var dir = string.Format("{0}{1}\\", PathManager.GetParameterDir(), chamId);
  1007. DirectoryInfo di = new DirectoryInfo(dir);
  1008. if (!di.Exists) di.Create();
  1009. return dir;
  1010. }
  1011. /// <summary>
  1012. /// get parameter's dir path
  1013. /// </summary>
  1014. /// <param name="ParameterName"></param>
  1015. /// <returns></returns>
  1016. private string getParameterBackupDirPath(string chamId)
  1017. {
  1018. var dir = string.Format("{0}{1}\\", PathManager.GetParameterBackupDir(), chamId);
  1019. DirectoryInfo di = new DirectoryInfo(dir);
  1020. if (!di.Exists) di.Create();
  1021. return dir;
  1022. }
  1023. /// <summary>
  1024. /// delete a recipe folder
  1025. /// </summary>
  1026. /// <param name="chamId"></param>
  1027. /// <param name="folderName"></param>
  1028. /// <returns></returns>
  1029. public bool DeleteFolder(string chamId, string folderName)
  1030. {
  1031. try
  1032. {
  1033. Directory.Delete(getParameterDirPath(chamId) + folderName, true);
  1034. EventInfo(string.Format(Resources.RecipeFileManager_DeleteFolder_RecipeFolder0DeleteSucceeded, folderName));
  1035. }
  1036. catch (Exception ex)
  1037. {
  1038. LOG.Write(ex, "删除recipe folder 出错");
  1039. EventAlarm(string.Format("recipe folder {0} delete failed", folderName));
  1040. return false;
  1041. }
  1042. return true;
  1043. }
  1044. /// <summary>
  1045. /// save as recipe content
  1046. /// </summary>
  1047. /// <param name="chamId"></param>
  1048. /// <param name="recipeName"></param>
  1049. /// <param name="recipeContent"></param>
  1050. /// <returns></returns>
  1051. public bool SaveAsParameter(string chamId, string recipeName, string recipeContent)
  1052. {
  1053. var path = GenerateParameterFilePath(chamId, recipeName);
  1054. if (File.Exists(path))
  1055. {
  1056. EventAlarm(string.Format(Resources.RecipeFileManager_SaveAsRecipe_RecipeFile0savefailed, recipeName));
  1057. return false;
  1058. }
  1059. return SaveParameter(chamId, recipeName, recipeContent, true, true);
  1060. }
  1061. /// <summary>
  1062. /// save recipe content
  1063. /// </summary>
  1064. /// <param name="chamId"></param>
  1065. /// <param name="parameterName"></param>
  1066. /// <param name="parameterContent"></param>
  1067. /// <returns></returns>
  1068. public bool SaveParameter(string chamId, string parameterName, string parameterContent, bool clearBarcode, bool notifyUI)
  1069. {
  1070. //validate recipe format when saving a recipe file
  1071. //var reasons1 = new List<string>();
  1072. //var reasons2 = new List<string>();
  1073. //ValidateRecipe(chamId, recipeName, recipeContent, out reasons1);
  1074. //CheckRecipe(chamId, recipeContent, out reasons2);
  1075. //reasons1.AddRange(reasons2);
  1076. //if (reasons1.Count > 0)
  1077. //{
  1078. // EventDialog(string.Format( Resources.RecipeFileManager_SaveRecipe_SaveRecipeContentError, recipeName), reasons1);
  1079. //}
  1080. bool ret = true;
  1081. try
  1082. {
  1083. var path = GenerateParameterFilePath(chamId, parameterName);
  1084. FileInfo fi = new FileInfo(path);
  1085. if (!fi.Directory.Exists)
  1086. fi.Directory.Create();
  1087. XmlDocument xml = new XmlDocument();
  1088. xml.LoadXml(parameterContent);
  1089. XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8);
  1090. writer.Formatting = Formatting.Indented;
  1091. xml.Save(writer);
  1092. writer.Close();
  1093. if (notifyUI)
  1094. {
  1095. InfoDialog(string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveCompleted, parameterName));
  1096. }
  1097. else
  1098. {
  1099. EV.PostMessage("System", EventEnum.GeneralInfo, string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveCompleted, parameterName));
  1100. }
  1101. }
  1102. catch (Exception ex)
  1103. {
  1104. LOG.Write(ex, "保存recipe file 出错");
  1105. if (notifyUI)
  1106. {
  1107. WarningDialog(string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveFailed, parameterName));
  1108. }
  1109. ret = false;
  1110. }
  1111. return ret;
  1112. }
  1113. /// <summary>
  1114. /// save recipe content
  1115. /// </summary>
  1116. /// <param name="chamId"></param>
  1117. /// <param name="parameterName"></param>
  1118. /// <param name="parameterContent"></param>
  1119. /// <returns></returns>
  1120. public bool SaveRestoreParameter(string chamId, string parameterName, string parameterContent, bool clearBarcode, bool notifyUI)
  1121. {
  1122. //validate recipe format when saving a recipe file
  1123. //var reasons1 = new List<string>();
  1124. //var reasons2 = new List<string>();
  1125. //ValidateRecipe(chamId, recipeName, recipeContent, out reasons1);
  1126. //CheckRecipe(chamId, recipeContent, out reasons2);
  1127. //reasons1.AddRange(reasons2);
  1128. //if (reasons1.Count > 0)
  1129. //{
  1130. // EventDialog(string.Format( Resources.RecipeFileManager_SaveRecipe_SaveRecipeContentError, recipeName), reasons1);
  1131. //}
  1132. bool ret = true;
  1133. try
  1134. {
  1135. var path = GenerateBackupParameterFilePath(chamId, parameterName);
  1136. FileInfo fi = new FileInfo(path);
  1137. if (!fi.Directory.Exists)
  1138. fi.Directory.Create();
  1139. XmlDocument xml = new XmlDocument();
  1140. xml.LoadXml(parameterContent);
  1141. XmlTextWriter writer = new XmlTextWriter(path, Encoding.UTF8);
  1142. writer.Formatting = Formatting.Indented;
  1143. xml.Save(writer);
  1144. writer.Close();
  1145. if (notifyUI)
  1146. {
  1147. InfoDialog(string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveCompleted, parameterName));
  1148. }
  1149. else
  1150. {
  1151. EV.PostMessage("System", EventEnum.GeneralInfo, string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveCompleted, parameterName));
  1152. }
  1153. }
  1154. catch (Exception ex)
  1155. {
  1156. LOG.Write(ex, "保存recipe file 出错");
  1157. if (notifyUI)
  1158. {
  1159. WarningDialog(string.Format(Resources.RecipeFileManager_SaveRecipe_RecipeFile0SaveFailed, parameterName));
  1160. }
  1161. ret = false;
  1162. }
  1163. return ret;
  1164. }
  1165. /// <summary>
  1166. /// create a new recipe folder
  1167. /// </summary>
  1168. /// <param name="chamId"></param>
  1169. /// <param name="folderName"></param>
  1170. /// <returns></returns>
  1171. public bool CreateFolder(string chamId, string folderName)
  1172. {
  1173. try
  1174. {
  1175. Directory.CreateDirectory(getParameterDirPath(chamId) + folderName);
  1176. EventInfo(string.Format(Resources.RecipeFileManager_CreateFolder_RecipeFolder0Created, folderName));
  1177. }
  1178. catch (Exception ex)
  1179. {
  1180. LOG.Write(ex, "create recipe folder failed");
  1181. EventAlarm(string.Format(Resources.RecipeFileManager_CreateFolder_RecipeFolder0CreateFailed, folderName));
  1182. return false;
  1183. }
  1184. return true;
  1185. }
  1186. /// <summary>
  1187. /// Rename recipe folder name
  1188. /// </summary>
  1189. /// <param name="chamId"></param>
  1190. /// <param name="oldName"></param>
  1191. /// <param name="newName"></param>
  1192. /// <returns></returns>
  1193. public bool RenameFolder(string chamId, string oldName, string newName)
  1194. {
  1195. try
  1196. {
  1197. string oldPath = getParameterDirPath(chamId) + oldName;
  1198. string newPath = getParameterDirPath(chamId) + newName;
  1199. Directory.Move(oldPath, newPath);
  1200. EventInfo(string.Format(Resources.RecipeFileManager_RenameFolder_RecipeFolder0renamed, oldName, newName));
  1201. }
  1202. catch (Exception ex)
  1203. {
  1204. LOG.Write(ex, "Rename recipe folder failed");
  1205. EventAlarm(string.Format(Resources.RecipeFileManager_RenameFolder_RecipeFolder0RenameFailed, oldName, newName));
  1206. return false;
  1207. }
  1208. return true;
  1209. }
  1210. public XmlDocument ParameterDom = new XmlDocument();
  1211. private string GetParameterBody(string chamberId, string nodePath)
  1212. {
  1213. if (_rcpContext == null)
  1214. return string.Empty;
  1215. string schema = _rcpContext.GetParameterDefiniton(chamberId);
  1216. ParameterDom = new XmlDocument();
  1217. ParameterDom.LoadXml(schema);
  1218. XmlNode node = ParameterDom.SelectSingleNode(nodePath);
  1219. return node.OuterXml;
  1220. }
  1221. public string ChamberType
  1222. {
  1223. get;
  1224. set;
  1225. }
  1226. public string Version
  1227. {
  1228. get;
  1229. set;
  1230. }
  1231. public int TableNumber
  1232. {
  1233. get;
  1234. set;
  1235. }
  1236. public Dictionary<string, ObservableCollection<ParameterTemplateColumnBase>> GetGroupParameterTemplate()
  1237. {
  1238. try
  1239. {
  1240. XmlNode nodeRoot = ParameterDom.SelectSingleNode("Aitex/TableParameterFormat");
  1241. ChamberType = nodeRoot.Attributes["ChamberType"].Value;
  1242. Version = nodeRoot.Attributes["Version"].Value;
  1243. TableNumber = nodeRoot.Attributes["TableNumber"] != null ? Convert.ToInt32(nodeRoot.Attributes["TableNumber"].Value) : 0;
  1244. }
  1245. catch (Exception ex)
  1246. {
  1247. LOG.Write(ex);
  1248. return null;
  1249. }
  1250. var columns = new Dictionary<string, ObservableCollection<ParameterTemplateColumnBase>>();
  1251. ParameterTemplateColumnBase col = null;
  1252. XmlNodeList nodes = ParameterDom.SelectNodes("Aitex/TableParameterFormat/Catalog/Group");
  1253. foreach (XmlNode node in nodes)
  1254. {
  1255. XmlNodeList childNodes = node.SelectNodes("Step");
  1256. int tableNum = 1;
  1257. string nameList = null;
  1258. if (node.Attributes["TableNumber"] != null)
  1259. {
  1260. tableNum = Convert.ToInt32(node.Attributes["TableNumber"].Value);
  1261. }
  1262. if (node.Attributes["NameList"] != null)
  1263. {
  1264. nameList = node.Attributes["NameList"].Value.Replace("\t\t\t\t ", "").Replace("\n", "").Replace("\r", "");
  1265. }
  1266. if (nameList != null && nameList.Contains(","))
  1267. {
  1268. tableNum = tableNum > nameList.Split(',').Length ? tableNum : nameList.Split(',').Length;
  1269. }
  1270. string[] namelist = new string[tableNum];
  1271. for (int i = 0; i < namelist.Length; i++)
  1272. {
  1273. namelist[i] = "";
  1274. }
  1275. if (!string.IsNullOrEmpty(nameList))
  1276. {
  1277. var list = nameList.Split(',');
  1278. for (int i = 0; i < list.Length; i++)
  1279. {
  1280. namelist[i] = list[i];
  1281. }
  1282. }
  1283. for (int i = 1; i <= tableNum; i++)
  1284. {
  1285. var sigcolumns = new ObservableCollection<ParameterTemplateColumnBase>();
  1286. foreach (XmlNode step in childNodes)
  1287. {
  1288. //step number
  1289. if (step.Attributes["ControlName"].Value == "TableNo")
  1290. {
  1291. col = new ParameterTemplateColumnBase()
  1292. {
  1293. DisplayName = "Table",
  1294. ControlName = "TableNo",
  1295. };
  1296. sigcolumns.Add(col);
  1297. continue;
  1298. }
  1299. switch (step.Attributes["InputType"].Value)
  1300. {
  1301. case "TextInput":
  1302. col = new ParameterTemplateColumnBase()
  1303. {
  1304. ValueType = "TextInput",
  1305. ModuleName = step.Attributes["ModuleName"].Value,
  1306. ControlName = step.Attributes["ControlName"].Value,
  1307. DisplayName = step.Attributes["DisplayName"].Value,
  1308. IsEnable = !bool.Parse(step.Attributes["ReadOnly"] != null ? step.Attributes["ReadOnly"].Value : "false"),
  1309. EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),
  1310. Default = step.Attributes["DefaultValue"] != null ? step.Attributes["DefaultValue"].Value : "",
  1311. EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),
  1312. };
  1313. sigcolumns.Add(col);
  1314. break;
  1315. case "NumInput":
  1316. col = new ParameterTemplateColumnBase()
  1317. {
  1318. ValueType = "NumInput",
  1319. ModuleName = step.Attributes["ModuleName"].Value,
  1320. ControlName = step.Attributes["ControlName"].Value,
  1321. DisplayName = step.Attributes["DisplayName"].Value,
  1322. InputMode = step.Attributes["InputMode"].Value,
  1323. Minimun = double.Parse(step.Attributes["Min"].Value),
  1324. Maximun = double.Parse(step.Attributes["Max"].Value),
  1325. Value = step.Attributes["DefaultValue"] != null ? Convert.ToInt32(step.Attributes["DefaultValue"].Value) : 0,
  1326. IsEnable = !bool.Parse(step.Attributes["ReadOnly"] != null ? step.Attributes["ReadOnly"].Value : "false"),
  1327. EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),
  1328. EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),
  1329. };
  1330. sigcolumns.Add(col);
  1331. break;
  1332. case "DoubleInput":
  1333. col = new ParameterTemplateColumnBase()
  1334. {
  1335. ValueType = "DoubleInput",
  1336. ModuleName = step.Attributes["ModuleName"].Value,
  1337. ControlName = step.Attributes["ControlName"].Value,
  1338. DisplayName = step.Attributes["DisplayName"].Value,
  1339. InputMode = step.Attributes["InputMode"].Value,
  1340. Minimun = double.Parse(step.Attributes["Min"].Value),
  1341. Maximun = double.Parse(step.Attributes["Max"].Value),
  1342. Value = step.Attributes["DefaultValue"] != null ? Convert.ToDouble(step.Attributes["DefaultValue"].Value) : 0.0f,
  1343. IsEnable = !bool.Parse(step.Attributes["ReadOnly"] != null ? step.Attributes["ReadOnly"].Value : "false"),
  1344. EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),
  1345. EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),
  1346. };
  1347. sigcolumns.Add(col);
  1348. break;
  1349. case "EditableSelection":
  1350. col = new ParameterTemplateColumnBase()
  1351. {
  1352. ValueType = "EditableSelection",
  1353. ModuleName = step.Attributes["ModuleName"].Value,
  1354. Default = step.Attributes["Default"] != null ? step.Attributes["Default"].Value : "",
  1355. ControlName = step.Attributes["ControlName"].Value,
  1356. DisplayName = step.Attributes["DisplayName"].Value,
  1357. IsEnable = !bool.Parse(step.Attributes["ReadOnly"] != null ? step.Attributes["ReadOnly"].Value : "false"),
  1358. EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),
  1359. EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),
  1360. };
  1361. XmlNodeList items = step.SelectNodes("Item");
  1362. foreach (XmlNode item in items)
  1363. {
  1364. Option opt = new Option();
  1365. opt.ControlName = item.Attributes["ControlName"].Value;
  1366. opt.DisplayName = item.Attributes["DisplayName"].Value;
  1367. ((ParameterTemplateColumnBase)col).Options.Add(opt);
  1368. }
  1369. sigcolumns.Add(col);
  1370. break;
  1371. case "ReadOnlySelection":
  1372. case "LoopSelection":
  1373. col = new ParameterTemplateColumnBase()
  1374. {
  1375. ValueType = "LoopSelection",
  1376. IsReadOnly = bool.Parse(step.Attributes["ReadOnly"] != null ? step.Attributes["ReadOnly"].Value : "false"),
  1377. ModuleName = step.Attributes["ModuleName"].Value,
  1378. ControlName = step.Attributes["ControlName"].Value,
  1379. DisplayName = step.Attributes["DisplayName"].Value,
  1380. EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),
  1381. EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),
  1382. };
  1383. XmlNodeList options = step.SelectNodes("Item");
  1384. foreach (XmlNode item in options)
  1385. {
  1386. Option opt = new Option();
  1387. opt.ControlName = item.Attributes["ControlName"].Value;
  1388. opt.DisplayName = item.Attributes["DisplayName"].Value;
  1389. ((ParameterTemplateColumnBase)col).Options.Add(opt);
  1390. }
  1391. sigcolumns.Add(col);
  1392. break;
  1393. case "PopSetting":
  1394. col = new ParameterTemplateColumnBase()
  1395. {
  1396. ValueType = "LoopSelection",
  1397. ModuleName = step.Attributes["ModuleName"].Value,
  1398. ControlName = step.Attributes["ControlName"].Value,
  1399. DisplayName = step.Attributes["DisplayName"].Value,
  1400. EnableConfig = step.Attributes["EnableConfig"] != null && Convert.ToBoolean(step.Attributes["EnableConfig"].Value),
  1401. EnableTolerance = step.Attributes["EnableTolerance"] != null && Convert.ToBoolean(step.Attributes["EnableTolerance"].Value),
  1402. };
  1403. sigcolumns.Add(col);
  1404. break;
  1405. }
  1406. }
  1407. if (tableNum == 1 && string.IsNullOrEmpty(nameList))
  1408. {
  1409. columns.Add(node.Attributes["DisplayName"].Value, sigcolumns);
  1410. }
  1411. else if (tableNum == 1 && !string.IsNullOrEmpty(nameList))
  1412. {
  1413. columns.Add($"{node.Attributes["DisplayName"].Value}\t1\t{namelist[0]}", sigcolumns);
  1414. }
  1415. else
  1416. {
  1417. columns.Add($"{node.Attributes["DisplayName"].Value}\t{i}\t{namelist[i - 1]}", sigcolumns);
  1418. }
  1419. }
  1420. }
  1421. return columns;
  1422. }
  1423. /// <summary>
  1424. /// get reactor's recipe format define file
  1425. /// </summary>
  1426. /// <param name="chamId"></param>
  1427. /// <returns></returns>
  1428. public string GetParameterFormatXml(string chamberId)
  1429. {
  1430. var rtn = GetParameterBody(chamberId, "/Aitex/TableParameterFormat");
  1431. return rtn;
  1432. }
  1433. /// <summary>
  1434. /// get reactor's template recipe file
  1435. /// </summary>
  1436. /// <param name="chamId"></param>
  1437. /// <returns></returns>
  1438. public string GetParameterTemplate(string chamberId)
  1439. {
  1440. if (_rcpContext != null)
  1441. return _rcpContext.GetParameterTemplate(chamberId);
  1442. return GetParameterBody(chamberId, "/Aitex/TableParameterData");
  1443. }
  1444. /// <summary>
  1445. /// get reactor's template recipe file
  1446. /// </summary>
  1447. /// <param name="chamId"></param>
  1448. /// <returns></returns>
  1449. public string GetParameterSchema(string chamberId)
  1450. {
  1451. if (_rcpContext == null)
  1452. return string.Empty;
  1453. string schema = _rcpContext.GetParameterDefiniton(chamberId);
  1454. XmlDocument dom = new XmlDocument();
  1455. dom.LoadXml(schema);
  1456. XmlNode node = dom.SelectSingleNode("/Aitex/TableParameterSchema");
  1457. return node.InnerXml;
  1458. }
  1459. public string GetParameterByBarcode(string chamberId, string barcode)
  1460. {
  1461. try
  1462. {
  1463. string parameterPath = PathManager.GetRecipeDir() + chamberId + "\\";
  1464. var di = new DirectoryInfo(parameterPath);
  1465. var fis = di.GetFiles("*.rcp", SearchOption.AllDirectories);
  1466. XmlDocument xml = new XmlDocument();
  1467. foreach (var fi in fis)
  1468. {
  1469. string str = fi.FullName.Substring(parameterPath.Length);
  1470. if (!str.Contains("HistoryParameter\\"))
  1471. {
  1472. xml.Load(fi.FullName);
  1473. if (xml.SelectSingleNode(string.Format("/TableParameterData[@Barcode='{0}']", barcode)) != null)
  1474. {
  1475. return str.Substring(0, str.LastIndexOf('.'));
  1476. }
  1477. }
  1478. }
  1479. return string.Empty;
  1480. }
  1481. catch (Exception ex)
  1482. {
  1483. LOG.Write(ex);
  1484. return string.Empty;
  1485. }
  1486. }
  1487. public List<FileNodeItem> GetFileNodeParameterListByPath(string chamberId)
  1488. {
  1489. List<FileNodeItem> files = new List<FileNodeItem>();
  1490. var baseFolderPath = getParameterDirPath(chamberId);
  1491. DirectoryInfo curFolderInfo = new DirectoryInfo(baseFolderPath);
  1492. FileNodeItem nodeItem = new FileNodeItem();
  1493. nodeItem.IsFile = false;
  1494. GenerateFileNodeParameterList(chamberId, curFolderInfo, nodeItem);
  1495. files.Add(nodeItem);
  1496. return files;
  1497. }
  1498. FileNodeItem GenerateFileNodeParameterList(string chamberId, DirectoryInfo currentDir, FileNodeItem nodeItem)
  1499. {
  1500. int trimLength = getParameterDirPath(chamberId).Length;
  1501. DirectoryInfo[] dirInfos = currentDir.GetDirectories();
  1502. foreach (DirectoryInfo dirInfo in dirInfos)
  1503. {
  1504. GenerateFileNodeParameterList(chamberId, dirInfo, nodeItem);
  1505. }
  1506. FileInfo[] fileInfos = currentDir.GetFiles("*.rcp");
  1507. foreach (FileInfo fileInfo in fileInfos)
  1508. {
  1509. string fileStr = fileInfo.FullName.Substring(trimLength).TrimStart(new char[] { '\\' }); ;
  1510. FileNodeItem subNodeItem = new FileNodeItem();
  1511. subNodeItem.Name = fileInfo.Name.Replace(".rcp", "");
  1512. subNodeItem.FullPath = subNodeItem.Name;
  1513. subNodeItem.PrefixPath = chamberId;
  1514. subNodeItem.IsFile = true;
  1515. ReadFileSetFileNode(chamberId, subNodeItem.Name, subNodeItem);
  1516. nodeItem.Files.Add(subNodeItem);
  1517. }
  1518. return nodeItem;
  1519. }
  1520. private void ReadFileSetFileNode(string chamberId,string fileName, FileNodeItem fileNodeItem)
  1521. {
  1522. string content = LoadParameter(chamberId, fileName, false);
  1523. XmlDocument _doc = new XmlDocument();
  1524. _doc.LoadXml(content);
  1525. XmlElement nodeData = _doc.SelectSingleNode($"Aitex/TableParameterData") as XmlElement;
  1526. fileNodeItem.Creator = nodeData.GetAttribute("CreatedBy");
  1527. fileNodeItem.Description = nodeData.GetAttribute("Description");
  1528. fileNodeItem.CreatTime = nodeData.GetAttribute("CreationTime");
  1529. fileNodeItem.ReviseTime = nodeData.GetAttribute("LastRevisionTime");
  1530. fileNodeItem.Revisor = nodeData.GetAttribute("LastRevisedBy");
  1531. fileNodeItem.Permission = nodeData.GetAttribute("Permission");
  1532. fileNodeItem.Level = nodeData.GetAttribute("Level");
  1533. fileNodeItem.IsChecked = nodeData.GetAttribute("CheckResult") == "Correct";
  1534. }
  1535. }
  1536. }