{"record":{"id":"ca4c8169e092159c","repo":"huiyadanli/RevokeMsgPatcher","slug":"installed","errorCode":"installed","errorMessage":"你已经安装过此补丁！","messagePattern":"你已经安装过此补丁！","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"warning","filePath":"RevokeMsgPatcher/Modifier/AppModifier.cs","lineNumber":337,"sourceCode":"                                matchingVersion = modifyInfo;\n                            }\n                        }\n                    }\n                }\n\n\n                // 补丁前SHA1匹配上，肯定是正确的dll\n                if (matchingSHA1Before != null)\n                {\n                    editor.FileModifyInfo = matchingSHA1Before;\n                    editor.TargetChanges = matchingSHA1Before.Changes;\n                    continue;\n                }\n\n                // 补丁后SHA1匹配上，肯定已经打过补丁\n                if (matchingSHA1After != null)\n                {\n                    throw new BusinessException(\"installed\", $\"你已经安装过此补丁！\");\n                }\n\n                // SHA1不匹配说明精准替换肯定不支持\n                if (matchingSHA1Before == null && matchingSHA1After == null)\n                {\n                    // 尝试使用特征码替换\n                    // 多个版本范围，匹配出对应版本可以使用的特征\n                    if (config.FileCommonModifyInfos != null)\n                    {\n                        editor.FileCommonModifyInfo = FindCommonModifyInfo(editor);\n                    }\n\n                    // 存在对应的特征时不报错\n                    if (editor.FileCommonModifyInfo != null && editor.FileCommonModifyInfo.ReplacePatterns != null)\n                    {\n                        List<ReplacePattern> replacePatterns = editor.FileCommonModifyInfo.ReplacePatterns;\n                        // 根据需要操作的功能类型（防撤回或者多开等）筛选特征码\n                        if (categories != null && categories.Count > 0)","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/huiyadanli/RevokeMsgPatcher/blob/89cbbb3f0cc896d5d092de0199a635c5c39944b6/RevokeMsgPatcher/Modifier/AppModifier.cs#L319-L355","documentation":"In ValidateAndFindModifyInfo (the precise/SHA1 patch path), the file's SHA1 matched a ModifyInfo.SHA1After (the hash of an already-patched file). AppModifier throws BusinessException('installed') because the file has already been patched and there is nothing to do.","triggerScenarios":"Running the precise (SHA1-based) patch on a DLL whose hash equals the post-patch hash for that version: the patch was already applied previously.","commonSituations":"User re-runs the patch without restoring; patch was applied in a prior session.","solutions":["Restore the original DLL first (the tool copies the .h.bak back).","If no backup exists, obtain a clean DLL of that version."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"static bool IsBusinessException(Exception e, string code) => e is BusinessException b && b.ErrorCode == code;\n\nstatic bool IsInstalled(Exception e) => IsBusinessException(e, \"installed\");","tryCatchPattern":"try\n{\n    modifier.ValidateAndFindModifyInfo(categories);\n}\ncatch (BusinessException ex) when (ex.ErrorCode == \"installed\")\n{\n    // SHA1After matched: already patched. Offer Restore instead.\n    MessageBox.Show(\"你已经安装过此补丁，如需重装请先还原。\");\n}","preventionTips":["Restore before re-patching to avoid the already-installed state.","Detect 'installed' via ErrorCode and surface a Restore option in the UI.","Keep a valid .h.bak so restore is always available."],"tags":["app-modifier","business-exception","already-patched"],"backgroundTag":null,"analyzedSha":"89cbbb3f0cc896d5d092de0199a635c5c39944b6","analyzedAt":"2026-08-13T10:37:37.073Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}