using System.Diagnostics;
using System.IO.Compression;
namespace LanMountainDesktop.AirAppDevServer;
///
/// AirApp 打包工具
/// 将 AirApp 项目打包为 .laapp 文件
///
public sealed class AirAppPackager
{
private readonly string _projectPath;
public AirAppPackager(string projectPath)
{
_projectPath = Path.GetFullPath(projectPath);
}
public async Task PackageAsync(string? outputPath)
{
Console.WriteLine("🔨 构建项目...");
if (!await BuildProjectAsync())
{
throw new InvalidOperationException("构建失败");
}
var binPath = Path.Combine(_projectPath, "bin", "Release", "net10.0");
if (!Directory.Exists(binPath))
{
binPath = Path.Combine(_projectPath, "bin", "Debug", "net10.0");
if (!Directory.Exists(binPath))
{
throw new InvalidOperationException("未找到构建输出");
}
}
Console.WriteLine($"📁 输出目录: {binPath}");
// 确定输出文件名
var projectName = Path.GetFileNameWithoutExtension(
Directory.GetFiles(_projectPath, "*.csproj").FirstOrDefault() ?? "AirApp");
if (string.IsNullOrEmpty(outputPath))
{
outputPath = Path.Combine(binPath, $"{projectName}.laapp");
}
else
{
outputPath = Path.GetFullPath(outputPath);
if (Directory.Exists(outputPath))
{
outputPath = Path.Combine(outputPath, $"{projectName}.laapp");
}
}
// 删除旧的包
if (File.Exists(outputPath))
{
File.Delete(outputPath);
}
Console.WriteLine($"📦 打包到: {outputPath}");
// 创建 ZIP 包
using (var archive = ZipFile.Open(outputPath, ZipArchiveMode.Create))
{
var filesToPackage = Directory.GetFiles(binPath, "*.*", SearchOption.AllDirectories)
.Where(f => !f.Contains(".pdb") && !f.EndsWith(".laapp"))
.ToList();
Console.WriteLine($"📄 打包 {filesToPackage.Count} 个文件...");
foreach (var file in filesToPackage)
{
var relativePath = Path.GetRelativePath(binPath, file);
archive.CreateEntryFromFile(file, relativePath);
}
}
Console.WriteLine($"✅ 包大小: {new FileInfo(outputPath).Length / 1024} KB");
return outputPath;
}
private async Task BuildProjectAsync()
{
var projectFile = Directory.GetFiles(_projectPath, "*.csproj").FirstOrDefault();
if (projectFile == null)
{
Console.WriteLine("❌ 未找到项目文件");
return false;
}
var startInfo = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = $"build \"{projectFile}\" -c Release --nologo",
WorkingDirectory = _projectPath,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};
using var process = Process.Start(startInfo);
if (process == null) return false;
await process.WaitForExitAsync();
if (process.ExitCode != 0)
{
var error = await process.StandardError.ReadToEndAsync();
Console.WriteLine($"❌ 构建错误:\n{error}");
return false;
}
return true;
}
}