/// <summary> /// Removes group with specified name /// </summary> /// <param name="groupToDelete"></param> public void RemoveGroup(string groupToDelete) { // Required group can't be removed if (!REQUIRED_GROUP_NAME.Equals(groupToDelete)) { InstallGroup currentGroup = _GetGroup(groupToDelete, _Groups); if (currentGroup.exists) { _Groups.Remove(currentGroup); // Set instructions to required group InstallGroup requiredGroup = _GetGroup(REQUIRED_GROUP_NAME, _Groups); for (int i = 0; i < _PatchInstructions.Count; i++) { PatchInstruction currentInstruction = _PatchInstructions[i]; if (currentInstruction.Group.Equals(currentGroup)) { currentInstruction.Group = requiredGroup; } } } } }
/// <summary> /// Adds or replace an instruction. If instruction order already exists, corresponding instruction is replaced; else specified instruction is added to the list. /// </summary> /// <param name="instruction">Instruction to set</param> public void SetInstruction(PatchInstruction instruction) { if (instruction == null || instruction.Order < 1) { return; } // Unsupported parameters are removed instruction.RemoveUnsupportedParameters(); if (instruction.Order > PatchInstructions.Count) { // Add mode PatchInstructions.Add(instruction); } else { // Replace mode for (int i = 0; i < PatchInstructions.Count; i++) { PatchInstruction currentInstruction = PatchInstructions[i]; if (currentInstruction.Order == instruction.Order) { PatchInstructions[i] = instruction; break; } } } }
public static PatchInstruction Configure(this PatchInstruction patchInstruction, AppInfo context, PatchingManifest manifest, string location, bool enabled = true) { patchInstruction.IsEnabled = enabled; patchInstruction.Patch = manifest; patchInstruction.Location = location; patchInstruction.AppInfo = context; return(patchInstruction); }
public static XmlInstruction ToXmlInstruction(this PatchInstruction instruction) { return(new XmlInstruction { IsEnabled = instruction.IsEnabled, Name = instruction.Patch.PatchInfo.PatchName, Location = instruction.Location }); }
/// <summary> /// Import specified instruction to current patch /// </summary> /// <param name="anotherInstruction"></param> public void ImportInstruction(PatchInstruction anotherInstruction) { if (anotherInstruction != null) { anotherInstruction.Order = PatchInstructions.Count + 1; PatchInstructions.Add(anotherInstruction); } }
/// <summary> /// Processes a single instruction /// </summary> /// <param name="instr">Instruction to execute</param> /// <param name="instructionNumber"></param> /// <returns></returns> private static RunResult _ProcessInstruction(PatchInstruction instr, int instructionNumber) { // Logger if (_PatchLog != null) { _PatchLog.WriteEvent(string.Format(_MSG_RUNNING_INSTRUCTION, instructionNumber, instr.Group.name, instr.Comment)); } return(instr.Run(_PatchLog)); }
/// <summary> /// Method to create an instruction from a XML node /// </summary> /// <param name="node">node to process</param> /// <param name="order">instruction order</param> /// <returns>Correponding instruction</returns> private PatchInstruction _ProcessInstruction(XmlNode node, int order) { PatchInstruction processedPI = null; if (node != null && order > 0) { // Main attributes string instructionType = node.Attributes[_TYPE_ATTRIBUTE].Value; string isFailOnError = Xml2.GetAttributeWithDefaultValue(node, _FAIL_ON_ERROR_ATTRIBUTE, true.ToString()); string isEnabled = Xml2.GetAttributeWithDefaultValue(node, _ENABLED_ATTRIBUTE, true.ToString()); string comment = Xml2.GetAttributeWithDefaultValue(node, _COMMENT_ATTRIBUTE, ""); string groupName = Xml2.GetAttributeWithDefaultValue(node, _GROUP_ATTRIBUTE, REQUIRED_GROUP_NAME); processedPI = PatchInstruction.MakeInstruction(instructionType); if (processedPI != null) { processedPI.FailOnError = bool.Parse(isFailOnError); processedPI.Enabled = bool.Parse(isEnabled); processedPI.Order = order; processedPI.Comment = comment; if (string.IsNullOrEmpty(groupName)) { groupName = REQUIRED_GROUP_NAME; } processedPI.Group = GetGroupFromName(groupName); // Instruction parameters XmlNodeList allParameterNodes = node.SelectNodes(_PARAMETER_NODE); if (allParameterNodes != null) { foreach (XmlNode anotherParameterNode in allParameterNodes) { PatchInstructionParameter pip = _ProcessParameter(anotherParameterNode); if (pip == null) { throw new Exception("Invalid parameter: " + anotherParameterNode.Value); } processedPI.Parameters.Add(pip.Name, pip); } } } } return(processedPI); }
/// <exception cref="T:PatchworkLauncher.PatchingProcessException">Cannot patch manifest during the patching process</exception> public static void TryPatchManifest(this AssemblyPatcher patcher, PatchInstruction patch, PatchGroup patchGroup, ProgressObject patchProgress) { try { patcher.PatchManifest(patch.Patch, patchProgress.ToMonitor()); } catch (PatchException patchException) { throw new PatchingProcessException(patchException) { AssociatedInstruction = patch, AssociatedPatchGroup = patchGroup, Step = PatchProcessingStep.ApplyingSpecificPatch }; } }
/// <summary> /// Handles single execution /// </summary> /// <param name="patchToRun">Patch instance to execute</param> /// <param name="instructionNumber">Instruction number to execute</param> /// <param name="log">Log for message storing</param> /// <param name="tduPath">Path for tdu files; can be null = default</param> /// <param name="filePath">Path for patch files</param> /// <param name="currentCulture"></param> /// <returns></returns> public static RunResult RunSingleInstruction(PCH patchToRun, int instructionNumber, Log log, string tduPath, string filePath, DB.Culture currentCulture) { RunResult result = RunResult.NotRun; if (patchToRun == null || string.IsNullOrEmpty(filePath)) { return(result); } _InitializeComponents(patchToRun, filePath, currentCulture, log); // Instruction finding PatchInstruction instr = patchToRun.GetInstruction(instructionNumber); if (instr != null) { result = _ProcessInstruction(instr, instructionNumber); switch (result) { case RunResult.RunWithWarnings: // Non-critical failure > next instruction _PatchLog.WriteEvent(string.Format(_MSG_INSTRUCTION_END_WARN, instr.Order, 1)); break; case RunResult.RunWithErrors: _PatchLog.WriteEvent(_MSG_FINISHING_ERR); break; default: _PatchLog.WriteEvent(_MSG_FINISHING_OK); break; } } // Displaying collected messages _DisplayCollectedMessages(); // Saving Logger to file _PatchLog.SaveToFile(_PatchLog.Name); return(result); }
/// <summary> /// Imports instruction(s) according to provided bribe /// </summary> /// <param name="bribe">Instructions XML bribe</param> public void ImportInstruction(string bribe) { if (!string.IsNullOrEmpty(bribe)) { XmlDocument doc = new XmlDocument(); doc.LoadXml(bribe); try { XmlNode instructionsNode = doc.DocumentElement; if (instructionsNode != null) { XmlNodeList allInstructionNodes = instructionsNode.SelectNodes(_SINGLE_INSTRUCTION_NODE); int order = _PatchInstructions.Count + 1; if (allInstructionNodes != null) { foreach (XmlNode anotherInstructionNode in allInstructionNodes) { PatchInstruction pi = _ProcessInstruction(anotherInstructionNode, order); if (pi == null) { Log.Warning("Invalid instruction - can't be imported."); } else { _PatchInstructions.Add(pi); order++; } } } } } catch (Exception ex) { // Current instruction won't be added Exception2.PrintStackTrace(ex); } } }
/// <summary> /// Displays help about specified instruction /// </summary> /// <param name="instruction"></param> public void ShowHelp(PatchInstruction instruction) { string nameLabel = ""; string descriptionLabel = ""; if (instruction != null) { nameLabel = instruction.Name; descriptionLabel = instruction.Description; } nameGroupBox.Text = nameLabel; instructionDescriptionHelpTextBox.Text = descriptionLabel; // Displays if needed if (!Visible) { Show(_ParentForm); } }
/// <summary> /// Swaps 2 instructions according to their order /// </summary> /// <param name="order">Order of first instruction</param> /// <param name="anotherOrder">Order of second instruction</param> public void SwitchInstructions(int order, int anotherOrder) { if (order == anotherOrder || order < 1 || anotherOrder < 1 || order > PatchInstructions.Count || anotherOrder > PatchInstructions.Count) { return; } PatchInstruction instr1 = GetInstruction(order); PatchInstruction instr2 = GetInstruction(anotherOrder); if (instr1 != null && instr2 != null) { instr1.Order = anotherOrder; instr2.Order = order; _PatchInstructions[order - 1] = instr2; _PatchInstructions[anotherOrder - 1] = instr1; } }
/// <summary> /// Handles XML writing of specified instruction /// </summary> /// <param name="instr">Instruction to write</param> /// <param name="doc">Main XML document</param> /// <param name="instructionsElement">Instruction collection node. If null, written element becomes document element</param> private static void _SaveInstruction(PatchInstruction instr, XmlDocument doc, XmlNode instructionsElement) { if (instr != null && doc != null) { XmlElement currentInstructionElement = doc.CreateElement(_SINGLE_INSTRUCTION_NODE); if (instructionsElement == null) { doc.AppendChild(currentInstructionElement); } else { instructionsElement.AppendChild(currentInstructionElement); } // Instruction attributes currentInstructionElement.SetAttribute(_TYPE_ATTRIBUTE, instr.Name); currentInstructionElement.SetAttribute(_FAIL_ON_ERROR_ATTRIBUTE, instr.FailOnError.ToString()); currentInstructionElement.SetAttribute(_ENABLED_ATTRIBUTE, instr.Enabled.ToString()); currentInstructionElement.SetAttribute(_COMMENT_ATTRIBUTE, instr.Comment); string groupName = instr.Group.name; if (string.IsNullOrEmpty(groupName)) { groupName = REQUIRED_GROUP_NAME; } currentInstructionElement.SetAttribute(_GROUP_ATTRIBUTE, groupName); // Parameters foreach (KeyValuePair <string, PatchInstructionParameter> pair in instr.Parameters) { _SaveParameter(pair.Value, doc, currentInstructionElement); } } }
/// <summary> /// Deletes an instruction at specified order /// </summary> /// <param name="order">Instruction order</param> public void DeleteInstructionAt(int order) { if (order > PatchInstructions.Count) { return; } // Retrieving instruction & deletion PatchInstruction instructionToDelete = GetInstruction(order); if (instructionToDelete != null) { PatchInstructions.Remove(instructionToDelete); // Updating order of following instructions foreach (PatchInstruction anotherInstruction in _PatchInstructions) { if (anotherInstruction.Order > order) { anotherInstruction.Order--; } } } }
/// <summary> /// Utility method converting specified installer patch to uninstaller one /// </summary> /// <param name="installerPatch"></param> /// <param name="uninstallerPatchFileName"></param> public static void ConvertInstallerToUninstaller(PCH installerPatch, string uninstallerPatchFileName) { if (installerPatch == null) { throw new Exception("Invalid installer patch specified."); } PCH uninstallerPatch = TduFile.GetFile(uninstallerPatchFileName) as PCH; if (uninstallerPatch == null) { throw new Exception("Unable to create specified uninstaller patch."); } // Cloning properties installerPatch.DuplicateProperties(uninstallerPatch); // Browsing instructions int ignoredCount = 0; foreach (PatchInstruction patchInstruction in installerPatch.PatchInstructions) { PatchInstruction correspondingInstruction = patchInstruction.Clone() as PatchInstruction; // checkPatch instruction is not used in uninstaller if (correspondingInstruction == null || PatchInstruction.InstructionName.checkPatch.ToString().Equals(correspondingInstruction.Name) || PatchInstruction.InstructionName.nothing.ToString().Equals(correspondingInstruction.Name)) { ignoredCount++; continue; } // installFile instruction must be converted into uninstallFile, keeping parameter values if (PatchInstruction.InstructionName.installFile.ToString().Equals(correspondingInstruction.Name)) { correspondingInstruction = PatchInstruction.ChangeInstruction(correspondingInstruction, PatchInstruction.InstructionName.uninstallFile); } // bnkRemap instruction must be converted into bnkUnmap, keeping parameter values if (PatchInstruction.InstructionName.bnkRemap.ToString().Equals(correspondingInstruction.Name)) { correspondingInstruction = PatchInstruction.ChangeInstruction(correspondingInstruction, PatchInstruction.InstructionName.bnkUnmap); } // installPackedFile instruction must be converted into uninstallPackedFile, keeping parameter values if (PatchInstruction.InstructionName.installPackedFile.ToString().Equals(correspondingInstruction.Name)) { correspondingInstruction = PatchInstruction.ChangeInstruction(correspondingInstruction, PatchInstruction.InstructionName.uninstallPackedFile); } // Updates instruction index patchInstruction.Order -= ignoredCount; // Adding instruction to uninstaller uninstallerPatch.SetInstruction(correspondingInstruction); } // Saving uninstallerPatch.Save(); }
/// <summary> /// Reads patch from a PCH (XML format) file /// </summary> protected override sealed void _ReadData() { XmlDocument doc = new XmlDocument(); try { doc.Load(FileName); // Properties XmlElement docElement = doc.DocumentElement; if (docElement != null) { XmlNode propNode = docElement.SelectSingleNode(_PROPERTIES_NODE); _Name = propNode.Attributes[_NAME_ATTRIBUTE].Value; _Version = propNode.Attributes[_VERSION_ATTRIBUTE].Value; _Author = propNode.Attributes[_AUTHOR_ATTRIBUTE].Value; _Date = propNode.Attributes[_DATE_ATTRIBUTE].Value; _Free = Xml2.GetAttributeWithDefaultValue(propNode, _FREE_ATTRIBUTE, ""); _InstallerFileName = Xml2.GetAttributeWithDefaultValue(propNode, _INSTALLER_FILE_NAME_ATTRIBUTE, INSTALLER_FILE_NAME); // EVO_131: roles _RetrieveRoles(propNode); // EVO_134: groups _RetrieveGroups(propNode); // New attributes _SlotRef = Xml2.GetAttributeWithDefaultValue(propNode, _SLOT_REF_ATTRIBUTE, ""); InfoURL = Xml2.GetAttributeWithDefaultValue(propNode, _INFO_URL_ATTRIBUTE, ""); // Instructions XmlNode instrNode = docElement.SelectSingleNode(_INSTRUCTIONS_NODE); XmlNodeList allInstructionNodes = instrNode.SelectNodes(_SINGLE_INSTRUCTION_NODE); int order = 1; if (allInstructionNodes != null) { foreach (XmlNode anotherInstructionNode in allInstructionNodes) { try { PatchInstruction pi = _ProcessInstruction(anotherInstructionNode, order); if (pi == null) { throw new Exception(); } _PatchInstructions.Add(pi); // Groups update if (!_Groups.Contains(pi.Group)) { _Groups.Add(pi.Group); } order++; } catch (Exception ex) { // Current instruction won't be added Exception2.PrintStackTrace(new Exception("Invalid instruction.", ex)); } } } } } catch (Exception ex) { // Silent exception Exception2.PrintStackTrace(new Exception(_ERROR_LOADING_PATCH, ex)); } // EVO_65: Properties Property.ComputeValueDelegate instructionCountDelegate = () => PatchInstructions.Count.ToString(); Property.ComputeValueDelegate nameDelegate = () => Name; Property.ComputeValueDelegate authorDelegate = () => Author; Property.ComputeValueDelegate dateDelegate = () => Date; Property.ComputeValueDelegate versionDelegate = () => Version; Property.ComputeValueDelegate slotDelegate = () => SlotRef; Property.ComputeValueDelegate groupCountDelegate = () => Groups.Count.ToString(); Property.ComputeValueDelegate installerDelegate = () => InstallerFileName; Property.ComputeValueDelegate urlDelegate = () => InfoURL; Properties.Add(new Property("Patch name", "Patch", nameDelegate)); Properties.Add(new Property("Author", "Patch", authorDelegate)); Properties.Add(new Property("Date", "Patch", dateDelegate)); Properties.Add(new Property("Version", "Patch", versionDelegate)); Properties.Add(new Property("Group count", "Patch", groupCountDelegate)); Properties.Add(new Property("Instruction count", "Patch", instructionCountDelegate)); Properties.Add(new Property("Slot reference", "Patch", slotDelegate)); Properties.Add(new Property("Installer file name", "Patch", installerDelegate)); Properties.Add(new Property("Information URL", "Patch", urlDelegate)); }
public static XmlPatchHistory FromInstruction(PatchInstruction instr) { return(new XmlPatchHistory(instr.PatchLocation)); }
/// <summary> /// Parse un Statement suivi de son block. /// En général, on obtient : /// Statement + Operand + BlockGroup. /// Le statement if pouvant être composé différemment (avec else et elsif), il n'est pas traité /// dans cette fonction. /// </summary> /// <param name="tokens"></param> /// <returns></returns> public static Instruction ParseBlockStatement(TokenList tokens, GlobalContext mainContext) { // Patch if (tokens.Count == 4 && tokens.First().Type == TokenType.Statement) { PatchInstruction patchInstruction = new PatchInstruction(); InfoToken itoken = (InfoToken)tokens.First(); if (itoken.Content != "patch") { throw new Exception("Invalid statement format"); } patchInstruction.FuncName = ((InfoToken)((OperandToken)tokens[1]).Tokens[0]).Content; InfoToken keyToken = (InfoToken)((OperandToken)(((PrefixedOperatorToken)tokens[2]).Operand)).Tokens.First(); patchInstruction.Key = keyToken.Content; patchInstruction.Instructions = ParseBlock(((BlockGroupToken)tokens[3]).Tokens).Instructions; return(patchInstruction); } if (tokens.Count != 3) { throw new Exception("Invalid instruction format."); } // On récupère les jetons. InfoToken statementToken = tokens[0] as InfoToken; Token exprToken = tokens[1]; BlockGroupToken blockToken = tokens[2] as BlockGroupToken; if (statementToken == null || blockToken == null || statementToken.Type != TokenType.Statement) { throw new Exception("Invalid instruction format."); } Block block = ParseBlock(blockToken.Tokens, mainContext); switch (statementToken.Content) { case "return": throw new Exception(); case "function": throw new Exception(); /*TokenList exprTokens = ((OperandToken)exprToken).Tokens; * FunctionDeclarationInstruction declaration = new FunctionDeclarationInstruction(); * TokenList nameTokens = ((ParenthesisGroupToken)exprTokens[1]).Tokens; * * // Ici on parcours les jetons de exprToken (qui doit être un OperandToken) * // afin de trouver les noms des arguments. * * // Liste contenant les noms des arguments * List<string> argsNamesLists = new List<string>(); * string funName = ((InfoToken)(exprTokens[0])).Content; * * // Indique si le prochain jeton doit être une virgule * bool needComa = false; * foreach (Token tok in nameTokens) * { * if (needComa && tok.Type != TokenType.Separator) * throw new Exception("Expected ',' token in function declaration"); * else * needComa = false; * // Si c'est un nom : * if (tok.Type == TokenType.OperandTokens && ((OperandToken)tok).Tokens.First().Type == TokenType.Noun) * { * argsNamesLists.Add(((InfoToken)((OperandToken)tok).Tokens.First()).Content); * needComa = true; * } * } * // Setup de la déclaration de fonction. * declaration.Function = new Function(); * declaration.Function.ArgumentNames = argsNamesLists; * declaration.Function.Body = block; * declaration.FunctionName = funName; * * return declaration;*/ break; case "while": IGettable expr = ParseExpression(exprToken, mainContext); block = ParseBlock(blockToken.Tokens, mainContext); WhileStatement statement = new WhileStatement(); statement.Block = block; statement.Condition = expr; return(statement); case "for": // Dans le cas d'une boucle for, expr est une opérande, contenant // une instruction, une expression, et une autre instruction. // (bizarre, certes) TokenList initializationInstruction = new TokenList(); TokenList stepInstruction = new TokenList(); TokenList conditionExpr = new TokenList(); int step = 0; foreach (Token tok in ((OperandToken)exprToken).Tokens) { if (tok.Type == TokenType.EndOfInstruction) { step++; } else { switch (step) { case 0: initializationInstruction.Add(tok); break; case 1: conditionExpr.Add(tok); break; case 2: stepInstruction.Add(tok); break; } } } // On vérifie qu'on ait bien le bon nombre. if (step != 2) { throw new Exception("Incorrect for statement."); } // On crée et on retourne le for. ForStatement forStatement = new ForStatement(); forStatement.Initialisation = ParseInstruction(initializationInstruction, mainContext); forStatement.Condition = ParseExpression(new OperandToken(conditionExpr), mainContext); forStatement.Update = ParseInstruction(stepInstruction, mainContext); forStatement.Block = block; return(forStatement); default: throw new NotImplementedException("Not implemented statement"); } }