{"record":{"id":"778484376fa03753","repo":"OdysseusYuan/LKY_OfficeTools","slug":"perpetualvl2021-778484","errorCode":null,"errorMessage":"无法获取 PerpetualVL2021 对应的下载地址！","messagePattern":"无法获取 PerpetualVL2021 对应的下载地址！","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"LKY_OfficeTools/Lib/Lib_OfficeInfo.cs","lineNumber":180,"sourceCode":"                        {\n                            return null;\n                        }\n\n                        new Log(\"\\n------> 正在解析 最新可用 Office 下载服务器 ...\", ConsoleColor.DarkCyan);\n\n                        //获取版本信息\n                        string latest_info = Com_TextOS.GetCenterText(OfficeChannelInfo, \"\\\"PerpetualVL2021\\\",\", \"name\");                     //获取 2021 LTSC\n                        if (!string.IsNullOrEmpty(latest_info))\n                        {\n                            //获取office下载地址\n                            var url = Com_TextOS.GetCenterText(latest_info, \"baseUrl\\\":\\\"\", \"\\\"\");                         //官方Json取值，格式和自己的不一样，千万注意\n\n                            new Log($\"     √ 已获得 Office 最新下载服务器信息\", ConsoleColor.DarkGreen);\n\n                            return _office_url_root = url + \"/office/data\";\n                        }\n\n                        throw new Exception(\"无法获取 PerpetualVL2021 对应的下载地址！\");\n                    }\n                    catch (Exception Ex)\n                    {\n                        new Log(\"     × 无法获取 最新可用 Office 下载服务器\", ConsoleColor.DarkRed);\n                        new Log(Ex.ToString());\n                        return null;\n                    }\n                }\n            }\n\n            private static List<string> _office_file_list;\n            internal static List<string> OfficeFileList\n            {\n                get\n                {\n                    try\n                    {\n                        //非空返回","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/OdysseusYuan/LKY_OfficeTools/blob/6f9a1bd471918f3310e6be4a6d7f42d0d6e467cf/LKY_OfficeTools/Lib/Lib_OfficeInfo.cs#L162-L198","documentation":"Thrown when the PerpetualVL2021 block is found (latest_info is non-empty) but the baseUrl field cannot be extracted from within it. The code looks for the marker `baseUrl\":\"` inside the extracted block. Unlike error 24, this fires at a later stage: the channel block exists but the download-URL field is absent or reformatted. The resulting URL would be combined with a hard-coded \"/office/data\" suffix to form OfficeUrlRoot.","triggerScenarios":"(a) The PerpetualVL2021 block is present but the baseUrl field was renamed or removed by Microsoft; (b) the field's escaping/quoting changed so the `baseUrl\":\"` marker no longer matches; (c) Microsoft restructured the CDN URL field while keeping version data intact (so error 24 passes but this one fires).","commonSituations":"Microsoft changed the download URL field name in the channel JSON; the JSON escaping changed (e.g., pretty-printed vs compact); a CDN restructure moved baseUrl to a nested object; the channel data was partially published.","solutions":["Inspect the raw PerpetualVL2021 block content to see the current field name for the download URL.","Update the baseUrl marker string in GetCenterText to match Microsoft's current field name/escaping.","Switch to structured JSON parsing so nested/moved fields are accessed by path, not string markers.","Verify the resulting URL + \"/office/data\" still resolves against Microsoft's current CDN layout.","Add a regression test using a captured channel JSON sample."],"exampleFix":"// before\nvar url = Com_TextOS.GetCenterText(latest_info, \"baseUrl\\\":\\\"\", \"\\\"\");\nreturn _office_url_root = url + \"/office/data\";\n...\nthrow new Exception(\"无法获取 PerpetualVL2021 对应的下载地址！\");\n\n// after — structured field access with a null-safe message\nvar json = JObject.Parse(OfficeChannelInfo);\nvar channel = json[\"PerpetualVL2021\"];\nvar baseUrlToken = channel?[\"baseUrl\"];\nif (baseUrlToken == null)\n    throw new Exception(\"PerpetualVL2021 缺少 baseUrl 字段，CDN 结构可能已变更。\");\nreturn _office_url_root = baseUrlToken.ToString() + \"/office/data\";","handlingStrategy":"fallback","validationCode":"// Confirm the baseUrl field is present inside the PerpetualVL2021 block before relying on it.\nstring latest_info = Com_TextOS.GetCenterText(OfficeChannelInfo, \"\\\"PerpetualVL2021\\\",\", \"name\");\nstring url = string.IsNullOrEmpty(latest_info) ? null\n    : Com_TextOS.GetCenterText(latest_info, \"baseUrl\\\":\\\"\", \"\\\"\");\nif (string.IsNullOrEmpty(url))\n{\n    new Log(\"PerpetualVL2021 块中缺少 baseUrl 字段，CDN 结构可能已变更。\", ConsoleColor.DarkRed);\n    return;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Access baseUrl via structured JSON path rather than string markers so nested moves survive.","Verify the composed URL (<baseUrl>/office/data) resolves against the current CDN after any schema update.","Unit-test baseUrl extraction against a saved channel JSON sample.","Log the raw PerpetualVL2021 block on failure so field-name changes are immediately visible."],"tags":["office","json-parsing","download-url","fragile-parsing","cdn"],"backgroundTag":null,"analyzedSha":"6f9a1bd471918f3310e6be4a6d7f42d0d6e467cf","analyzedAt":"2026-08-13T18:00:34.810Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}