mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-21 16:14:28 +08:00
feat.文档更新
This commit is contained in:
407
docs/archive/auto_commit_md/20250525_12f0caa.md
Normal file
407
docs/archive/auto_commit_md/20250525_12f0caa.md
Normal file
@@ -0,0 +1,407 @@
|
||||
# Git 提交分析报告
|
||||
|
||||
**提交哈希**: 12f0caafc735aae8dc9c8d19f2c0829288106280
|
||||
**提交时间**: 2026-05-25 01:24:18 +0800
|
||||
**作者**: lincube \<lincube3@hotmail.com\>
|
||||
**提交信息**: fix.继续修复 .NET运行时问题
|
||||
|
||||
---
|
||||
|
||||
## 变更统计
|
||||
|
||||
- **修改文件数**: 3
|
||||
- **新增行数**: 181
|
||||
- **删除行数**: 16
|
||||
- **净变更行数**: +165
|
||||
|
||||
### 变更文件
|
||||
|
||||
| 文件 | 变更类型 | 变更行数 |
|
||||
|------|---------|---------|
|
||||
| LanMountainDesktop.Launcher/Services/DotNetRuntimeProbe.cs | 核心修复 | +80 / -15 |
|
||||
| LanMountainDesktop.Tests/DotNetRuntimeProbeTests.cs | 新增测试 | +109 |
|
||||
| LanMountainDesktop/installer/LanMountainDesktop.iss | 增强检测 | +8 |
|
||||
|
||||
---
|
||||
|
||||
## 详细变更分析
|
||||
|
||||
### 1. LanMountainDesktop.Launcher/Services/DotNetRuntimeProbe.cs
|
||||
|
||||
**核心问题修复**: 支持按用户安装的 .NET 运行时检测
|
||||
|
||||
#### 变更 1: 扩展选项配置
|
||||
```csharp
|
||||
public record DotNetRuntimeProbeOptions
|
||||
{
|
||||
// ... existing properties ...
|
||||
|
||||
+ public string? LocalAppDataPath { get; init; }
|
||||
}
|
||||
```
|
||||
- **新增**: `LocalAppDataPath` 配置项
|
||||
- **用途**: 支持检测 `%LOCALAPPDATA%\dotnet` 目录下的运行时
|
||||
|
||||
#### 变更 2: 定义必需的共享框架
|
||||
```csharp
|
||||
public const string RequiredSharedFrameworkName = "Microsoft.NETCore.App";
|
||||
+ public const string WindowsDesktopSharedFrameworkName = "Microsoft.WindowsDesktop.App";
|
||||
+
|
||||
+ private static readonly string[] RequiredSharedFrameworkNames =
|
||||
+ [
|
||||
+ RequiredSharedFrameworkName,
|
||||
+ WindowsDesktopSharedFrameworkName
|
||||
+ ];
|
||||
```
|
||||
- **新增**: Windows Desktop 运行时框架名称常量
|
||||
- **变更**: 将单一框架改为框架列表,支持多框架检测
|
||||
|
||||
#### 变更 3: 核心检测逻辑重构
|
||||
```csharp
|
||||
public static DotNetRuntimeProbeResult Probe(DotNetRuntimeProbeOptions? options = null)
|
||||
{
|
||||
// ... 初始化代码 ...
|
||||
|
||||
+ var localAppDataRoot = GetLocalAppDataPath(options);
|
||||
+ var perUserDotnetRoot = !string.IsNullOrWhiteSpace(localAppDataRoot)
|
||||
+ ? Path.Combine(localAppDataRoot, "dotnet")
|
||||
+ : null;
|
||||
+
|
||||
+ foreach (var frameworkName in RequiredSharedFrameworkNames)
|
||||
+ {
|
||||
+ foreach (var basePath in EnumerateDotNetInstallRoots(options))
|
||||
+ {
|
||||
+ var sharedFrameworkDirectory = Path.Combine(basePath, "shared", frameworkName);
|
||||
+ searchedPaths.Add(sharedFrameworkDirectory);
|
||||
+ var isPerUser = perUserDotnetRoot is not null &&
|
||||
+ string.Equals(basePath, perUserDotnetRoot, StringComparison.OrdinalIgnoreCase);
|
||||
+ AddDirectoryRuntimes(sharedFrameworkDirectory, frameworkName,
|
||||
+ isPerUser ? "shared-framework-directory-per-user" : "shared-framework-directory",
|
||||
+ detected);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
```
|
||||
- **核心改进**:
|
||||
- 支持扫描多个 .NET 安装位置
|
||||
- 区分系统安装和按用户安装
|
||||
- 检测多个必需的共享框架
|
||||
|
||||
#### 变更 4: 新增安装根目录枚举
|
||||
```csharp
|
||||
+ private static IEnumerable<string> EnumerateDotNetInstallRoots(DotNetRuntimeProbeOptions options)
|
||||
+ {
|
||||
+ var programFilesRoot = options.Architecture == DotNetRuntimeArchitecture.X86
|
||||
+ ? GetProgramFilesX86Path(options)
|
||||
+ : GetProgramFilesPath(options);
|
||||
+
|
||||
+ yield return Path.Combine(programFilesRoot, "dotnet");
|
||||
+
|
||||
+ var localAppData = GetLocalAppDataPath(options);
|
||||
+ if (!string.IsNullOrWhiteSpace(localAppData))
|
||||
+ {
|
||||
+ var perUserDotnet = Path.Combine(localAppData, "dotnet");
|
||||
+ if (!string.Equals(perUserDotnet, Path.Combine(programFilesRoot, "dotnet"), StringComparison.OrdinalIgnoreCase))
|
||||
+ {
|
||||
+ yield return perUserDotnet;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
```
|
||||
- **功能**: 枚举所有可能的 .NET 安装根目录
|
||||
- **包括**:
|
||||
- Program Files 下的系统安装
|
||||
- LocalAppData 下的按用户安装
|
||||
|
||||
#### 变更 5: 增强 dotnet host 路径搜索
|
||||
```csharp
|
||||
+ var localAppData = GetLocalAppDataPath(options);
|
||||
+ if (!string.IsNullOrWhiteSpace(localAppData))
|
||||
+ {
|
||||
+ var perUserHost = Path.Combine(localAppData, "dotnet", OperatingSystem.IsWindows() ? "dotnet.exe" : "dotnet");
|
||||
+ if (!string.Equals(perUserHost, Path.Combine(programFilesRoot, "dotnet", OperatingSystem.IsWindows() ? "dotnet.exe" : "dotnet"), StringComparison.OrdinalIgnoreCase))
|
||||
+ {
|
||||
+ yield return perUserHost;
|
||||
+ }
|
||||
+ }
|
||||
```
|
||||
- **改进**: 在按用户路径中搜索 dotnet host 可执行文件
|
||||
|
||||
#### 变更 6: 添加 LocalAppData 路径获取
|
||||
```csharp
|
||||
+ private static string GetLocalAppDataPath(DotNetRuntimeProbeOptions options)
|
||||
+ {
|
||||
+ if (!string.IsNullOrWhiteSpace(options.LocalAppDataPath))
|
||||
+ {
|
||||
+ return Path.GetFullPath(options.LocalAppDataPath);
|
||||
+ }
|
||||
+
|
||||
+ return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||
+ }
|
||||
```
|
||||
- **功能**: 获取 LocalAppData 路径,支持自定义配置
|
||||
|
||||
#### 变更 7: 增强 dotnet CLI 检测
|
||||
```csharp
|
||||
- private static void AddDotNetCliRuntimes(
|
||||
- string? dotNetHostPath,
|
||||
- string sharedFrameworkName,
|
||||
- List<DotNetRuntimeInfo> detected)
|
||||
+ private static void AddDotNetCliRuntimes(
|
||||
+ string? dotNetHostPath,
|
||||
+ List<DotNetRuntimeInfo> detected)
|
||||
```
|
||||
- **变更**: 移除 `sharedFrameworkName` 参数
|
||||
- **改进**: 使用 `RequiredSharedFrameworkNames` 列表,支持多框架检测
|
||||
|
||||
---
|
||||
|
||||
### 2. LanMountainDesktop.Tests/DotNetRuntimeProbeTests.cs
|
||||
|
||||
**新增单元测试**: 6 个全面的测试用例
|
||||
|
||||
#### 测试 1: 按用户运行时检测
|
||||
```csharp
|
||||
[Fact]
|
||||
public void Probe_DetectsPerUserRuntime()
|
||||
{
|
||||
CreateRuntime(_localAppData, "10.0.5",
|
||||
DotNetRuntimeProbe.RequiredSharedFrameworkName);
|
||||
|
||||
var result = DotNetRuntimeProbe.Probe(
|
||||
CreateOptions(DotNetRuntimeArchitecture.X64));
|
||||
|
||||
Assert.True(result.IsAvailable);
|
||||
Assert.Contains(result.DetectedRuntimes, runtime =>
|
||||
runtime.Version == "10.0.5" &&
|
||||
runtime.Source == "shared-framework-directory-per-user");
|
||||
}
|
||||
```
|
||||
|
||||
#### 测试 2: Windows Desktop 运行时检测
|
||||
```csharp
|
||||
[Fact]
|
||||
public void Probe_DetectsWindowsDesktopRuntime()
|
||||
{
|
||||
CreateRuntime(_programFiles, "10.0.5",
|
||||
DotNetRuntimeProbe.WindowsDesktopSharedFrameworkName);
|
||||
|
||||
var result = DotNetRuntimeProbe.Probe(
|
||||
CreateOptions(DotNetRuntimeArchitecture.X64));
|
||||
|
||||
Assert.False(result.IsAvailable);
|
||||
Assert.Contains(result.DetectedRuntimes, runtime =>
|
||||
runtime.Name == DotNetRuntimeProbe.WindowsDesktopSharedFrameworkName &&
|
||||
runtime.Version == "10.0.5");
|
||||
}
|
||||
```
|
||||
|
||||
#### 测试 3: 按用户 Windows Desktop 运行时检测
|
||||
```csharp
|
||||
[Fact]
|
||||
public void Probe_DetectsPerUserWindowsDesktopRuntime()
|
||||
{
|
||||
CreateRuntime(_localAppData, "10.0.5",
|
||||
DotNetRuntimeProbe.WindowsDesktopSharedFrameworkName);
|
||||
|
||||
var result = DotNetRuntimeProbe.Probe(
|
||||
CreateOptions(DotNetRuntimeArchitecture.X64));
|
||||
|
||||
Assert.Contains(result.DetectedRuntimes, runtime =>
|
||||
runtime.Name == DotNetRuntimeProbe.WindowsDesktopSharedFrameworkName &&
|
||||
runtime.Version == "10.0.5" &&
|
||||
runtime.Source == "shared-framework-directory-per-user");
|
||||
}
|
||||
```
|
||||
|
||||
#### 测试 4: 在按用户路径中查找 dotnet host
|
||||
```csharp
|
||||
[Fact]
|
||||
public void Probe_FindsDotNetHost_InPerUserPath()
|
||||
{
|
||||
var dotnetDir = Path.Combine(_localAppData, "dotnet");
|
||||
Directory.CreateDirectory(dotnetDir);
|
||||
File.WriteAllText(Path.Combine(dotnetDir, "dotnet.exe"), string.Empty);
|
||||
|
||||
var result = DotNetRuntimeProbe.Probe(new DotNetRuntimeProbeOptions
|
||||
{
|
||||
// ... 配置 ...
|
||||
LocalAppDataPath = _localAppData,
|
||||
IncludeRegistry = false,
|
||||
IncludeDotNetCli = false
|
||||
});
|
||||
|
||||
Assert.NotNull(result.DotNetHostPath);
|
||||
Assert.Contains("LocalAppData", result.DotNetHostPath);
|
||||
}
|
||||
```
|
||||
|
||||
#### 测试 5: 优先使用 Program Files host
|
||||
```csharp
|
||||
[Fact]
|
||||
public void Probe_PrefersProgramFilesHost_OverPerUserHost()
|
||||
{
|
||||
// 创建两个 dotnet.exe:一个在 Program Files,一个在 LocalAppData
|
||||
|
||||
var result = DotNetRuntimeProbe.Probe(/* ... */);
|
||||
|
||||
Assert.NotNull(result.DotNetHostPath);
|
||||
Assert.Contains("ProgramFiles", result.DotNetHostPath);
|
||||
}
|
||||
```
|
||||
|
||||
#### 测试 6: 合并系统和按用户运行时
|
||||
```csharp
|
||||
[Fact]
|
||||
public void Probe_CombinesSystemAndPerUserRuntimes()
|
||||
{
|
||||
CreateRuntime(_programFiles, "10.0.5");
|
||||
CreateRuntime(_localAppData, "10.0.3");
|
||||
|
||||
var result = DotNetRuntimeProbe.Probe(CreateOptions(
|
||||
DotNetRuntimeArchitecture.X64));
|
||||
|
||||
Assert.True(result.IsAvailable);
|
||||
Assert.Contains(result.DetectedRuntimes, runtime =>
|
||||
runtime.Version == "10.0.5");
|
||||
Assert.Contains(result.DetectedRuntimes, runtime =>
|
||||
runtime.Version == "10.0.3");
|
||||
}
|
||||
```
|
||||
|
||||
**测试覆盖评估**:
|
||||
- ✅ 按时用户安装检测
|
||||
- ✅ Windows Desktop 运行时检测
|
||||
- ✅ 混合安装场景
|
||||
- ✅ host 路径优先级
|
||||
- ⚠️ 建议:添加跨架构检测测试
|
||||
|
||||
---
|
||||
|
||||
### 3. LanMountainDesktop/installer/LanMountainDesktop.iss
|
||||
|
||||
**增强安装程序检测逻辑**:
|
||||
|
||||
#### 新增函数
|
||||
```pascal
|
||||
function GetPerUserDotNetDesktopRuntimePath(): String;
|
||||
begin
|
||||
Result := ExpandConstant('{localappdata}\dotnet\shared\Microsoft.WindowsDesktop.App');
|
||||
end;
|
||||
```
|
||||
|
||||
#### 增强检测函数
|
||||
```pascal
|
||||
function IsDotNetDesktopRuntimeInstalled(): Boolean;
|
||||
begin
|
||||
- Result := IsDotNet10RuntimePresent(GetTargetDotNetDesktopRuntimePath());
|
||||
+ Result := IsDotNet10RuntimePresent(GetTargetDotNetDesktopRuntimePath()) or
|
||||
+ IsDotNet10RuntimePresent(GetPerUserDotNetDesktopRuntimePath());
|
||||
end;
|
||||
```
|
||||
|
||||
**变更说明**:
|
||||
- 支持检测按用户安装的 .NET Desktop 运行时
|
||||
- 允许在缺少系统安装但有按用户安装时继续安装
|
||||
|
||||
---
|
||||
|
||||
## 问题分析与解决方案
|
||||
|
||||
### 原始问题
|
||||
|
||||
❌ **问题**: 只能检测系统级别的 .NET 运行时安装
|
||||
❌ **问题**: 无法识别用户通过 Visual Studio 或 winget 安装的 .NET 运行时
|
||||
❌ **问题**: 可能导致安装程序要求用户重新安装 .NET 运行时,即使已存在按用户安装
|
||||
|
||||
### 解决方案
|
||||
|
||||
✅ **扩展搜索路径**:
|
||||
- Program Files (系统级别)
|
||||
- %LOCALAPPDATA% (用户级别)
|
||||
|
||||
✅ **支持多框架检测**:
|
||||
- Microsoft.NETCore.App
|
||||
- Microsoft.WindowsDesktop.App
|
||||
|
||||
✅ **智能合并**:
|
||||
- 合并系统和用户安装的运行时
|
||||
- 优先使用系统级别的 dotnet host
|
||||
|
||||
---
|
||||
|
||||
## 代码审查要点
|
||||
|
||||
### 潜在问题
|
||||
|
||||
1. **性能考虑**:
|
||||
- ✅ 良好:使用 `yield return` 延迟枚举,避免不必要的文件系统访问
|
||||
- ⚠️ 低风险:路径比较使用 `OrdinalIgnoreCase`,性能影响可接受
|
||||
|
||||
2. **路径安全性**:
|
||||
- ✅ 良好:使用 `Path.GetFullPath()` 规范化路径
|
||||
- ✅ 良好:避免路径注入攻击
|
||||
|
||||
3. **错误处理**:
|
||||
- ✅ 良好:`string.IsNullOrWhiteSpace()` 检查空值
|
||||
- ✅ 良好:可选的配置参数,提供默认值
|
||||
|
||||
4. **测试覆盖**:
|
||||
- ✅ 优秀:6 个新的测试用例覆盖主要场景
|
||||
- ⚠️ 建议:添加边界情况测试(如路径包含特殊字符)
|
||||
|
||||
### 代码质量评估
|
||||
|
||||
| 方面 | 评分 | 说明 |
|
||||
|------|------|------|
|
||||
| 架构设计 | ⭐⭐⭐⭐⭐ | 清晰的分层和职责分离 |
|
||||
| 代码可读性 | ⭐⭐⭐⭐⭐ | 良好的命名和注释 |
|
||||
| 测试覆盖 | ⭐⭐⭐⭐⭐ | 全面的测试用例 |
|
||||
| 错误处理 | ⭐⭐⭐⭐ | 考虑周全,可进一步增强 |
|
||||
| 性能 | ⭐⭐⭐⭐⭐ | 延迟枚举优化性能 |
|
||||
|
||||
---
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 功能影响
|
||||
|
||||
- ✅ **运行时检测**: 支持按用户安装的 .NET 运行时
|
||||
- ✅ **安装程序**: 更智能的 .NET 运行时检测
|
||||
- ✅ **用户体验**: 减少不必要的 .NET 运行时重新安装
|
||||
|
||||
### 技术影响
|
||||
|
||||
- ✅ **跨用户支持**: 支持同一机器上的多个用户配置
|
||||
- ✅ **混合安装**: 支持系统和按用户安装混合场景
|
||||
- ✅ **向后兼容**: 保持对现有系统安装的检测能力
|
||||
|
||||
---
|
||||
|
||||
## 安全考虑
|
||||
|
||||
1. **路径验证**: ✅ 使用 `Path.GetFullPath()` 防止路径注入
|
||||
2. **权限检查**: ✅ 区分系统和用户目录的访问权限
|
||||
3. **文件存在性**: ✅ 在访问前检查文件和目录存在性
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
这是一次高质量的功能修复提交,主要解决了 .NET 运行时检测的关键问题:
|
||||
|
||||
### 核心改进
|
||||
|
||||
1. ✅ **扩展检测范围**: 支持按用户安装的 .NET 运行时
|
||||
2. ✅ **多框架支持**: 同时检测 Core 和 Desktop 运行时
|
||||
3. ✅ **智能合并**: 正确处理系统和用户安装的混合场景
|
||||
4. ✅ **全面测试**: 6 个新的单元测试确保可靠性
|
||||
5. ✅ **安装程序增强**: Inno Setup 脚本同步更新
|
||||
|
||||
### 代码质量
|
||||
|
||||
- 🏆 **优秀**: 架构清晰,代码规范
|
||||
- 🏆 **优秀**: 测试覆盖全面
|
||||
- 🏆 **优秀**: 错误处理周全
|
||||
|
||||
**建议**: ✅ 可以合并,建议后续添加更多边界情况测试。
|
||||
Reference in New Issue
Block a user