程序工作流程:
- 终止XMind进程 → 2. 查找安装路径 → 3. 验证资源 → 4. 备份原文件 → 5. 写入新资源 → 6. 根据结果退出
1. 添加资源文件,并实现替换,资源应用在此处
将app.asar文件以现有文件方式添加到解决方案,并将生成操作修改为嵌入的资源
// 1. 指定要提取的资源名称
string resourceName = "激活XMind.app.asar"; // 替换为你的资源全名
// 2. 获取当前程序集
Assembly assembly = Assembly.GetExecutingAssembly();
// 3. 检查资源是否存在
if (Array.IndexOf(assembly.GetManifestResourceNames(), resourceName) == -1)
{
Console.WriteLine($"错误:找不到资源 '{resourceName}'");
Console.WriteLine("可用的资源有:");
foreach (var name in assembly.GetManifestResourceNames())
{
Console.WriteLine(name);
}
WaitForExitOnError();
return;
}
// 4. 目标文件路径
string targetFile = Path.Combine(xmindPath, "app.asar");
// 5. 备份原有文件(如果存在)
if (File.Exists(targetFile))
{
string backupFile = targetFile + ".bak";
File.Copy(targetFile, backupFile, true);
Console.WriteLine($"已备份原有文件到: {backupFile}");
}
// 6. 读取资源并写入目标文件
using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
using (FileStream fileStream = File.Create(targetFile))
{
resourceStream.CopyTo(fileStream);
}
Console.WriteLine($"文件已成功复制到: {targetFile}");
Console.WriteLine("操作完成!");
operationSuccess = true;
AutoCloseOnSuccess();
2. 权限处理
通过添加应用程序清单文件来请求管理员权限。
- 添加应用程序清单文件:
- 在Visual Studio中,右键点击项目 → 添加 → 新建项
- 选择”应用程序清单文件” (通常名为
app.manifest
) - 如果找不到这个选项,可以手动创建一个XML文件
- 修改清单文件:
找到以下行并取消注释(或添加):<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
替换掉原来的:<requestedExecutionLevel level="asInvoker" uiAccess="false" />
- 设置项目属性:
- 右键项目 → 属性 → 应用程序 → 资源 → 清单 → 选择你创建的清单文件
- VS Studio一般是会自动选择的
3. 将 .NET 程序发布为单个可执行文件
使用 .NET Core/5+ 的单文件发布功能
核心优势
- 无需依赖项:直接生成包含运行时和依赖的独立文件(
SelfContained=true
)或仅包含应用代码(需目标机器安装 .NET 运行时)。 - 跨平台支持:通过指定
RuntimeIdentifier (RID)
支持 Windows、Linux、macOS。
操作步骤
修改项目文件(.csproj),下面是我修改后的
<Project Sdk="Microsoft.NET.Sdk">
<!-- 单文件发布相关配置 -->
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<ApplicationManifest>app.manifest</ApplicationManifest>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
<!-- 启用单文件压缩 -->
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<!-- 启用发布裁剪以减小文件大小 -->
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
<!-- 明确排除不需要的依赖 -->
<TrimmerRootAssembly Include="YourMainAssembly" />
</PropertyGroup>
<!-- 移除 app.asar 作为普通文件 -->
<ItemGroup>
<None Remove="app.asar" />
</ItemGroup>
<!-- 将 app.asar 作为嵌入式资源包含 -->
<ItemGroup>
<EmbeddedResource Include="app.asar" />
</ItemGroup>
<!-- 排除不必要的资源 -->
<ItemGroup>
<Content Remove="path/to/unnecessary/files/*" />
</ItemGroup>
</Project>
打开命令行工具
使用 Windows 的命令提示符(CMD)、PowerShell,或者 macOS、Linux 系统的终端。
导航到项目目录
使用 cd
命令进入包含 .csproj
文件的项目目录。例如,若项目位于 C:\Projects\MyApp
,则在命令行中输入:
cd C:\Projects\MyApp
运行发布命令
在项目目录下,输入以下命令:
dotnet publish -c Release -r win-x64
按下回车键后,.NET CLI 会开始构建并发布项目。在发布过程中,它会编译代码、解析依赖项,并将所有必要的文件打包到一个输出目录中。
dotnet publish
:这是 .NET CLI(命令行接口)提供的一个命令,其作用是将 .NET 项目发布为可部署的输出。-c Release
:-c
是--configuration
的缩写,此参数指定了发布时使用的配置,Release
代表发布版本的配置。通常,Release
配置会对代码进行优化,去除调试信息,从而生成性能更优的应用程序。-r win-x64
:-r
是--runtime
的缩写,该参数指定了目标运行时环境。win-x64
表示针对 64 位 Windows 操作系统进行发布。
查找发布输出
发布完成后,你可以在项目目录下的 bin\Release\net8.0\win-x64\publish
文件夹中找到发布后的文件(这里我的 项目
是 net8.0
)。在这个文件夹中,会有一个单文件可执行程序(根据你的 .csproj
文件配置),将其复制到目标 64 位 Windows 系统上直接运行。
4. 运行结果
5. 源码
using System;
using System.Diagnostics; // 提供进程操作功能
using System.IO; // 提供文件操作功能
using System.Reflection; // 提供程序集和资源操作功能
using System.Threading; // 提供线程操作功能
class Program
{
// 操作成功标志
static bool operationSuccess = false;
// 主程序入口
static void Main(string[] args)
{
/*
* 功能1:关闭XMind进程
* 目的:确保可以安全替换XMind的资源文件
*/
KillXMindProcess();
/*
* 功能2:查找XMind安装路径
* 目的:定位需要替换资源文件的目标位置
*/
string xmindPath = FindXMindInstallationPath();
// 如果未找到安装路径,提示并退出
if (string.IsNullOrEmpty(xmindPath))
{
Console.WriteLine("未找到 XMind 安装路径");
WaitForExitOnError();
return;
}
Console.WriteLine($"找到 XMind 安装路径: {xmindPath}");
try
{
/*
* 功能3:替换资源文件
* 步骤:
* 1. 指定要提取的内嵌资源名称
* 2. 获取当前程序集
* 3. 检查资源是否存在
* 4. 确定目标文件路径
* 5. 备份原有文件
* 6. 写入新资源文件
*/
string resourceName = "激活XMind.app.asar"; // 内嵌资源名称
// 获取当前运行的程序集
Assembly assembly = Assembly.GetExecutingAssembly();
// 检查资源是否存在
if (Array.IndexOf(assembly.GetManifestResourceNames(), resourceName) == -1)
{
Console.WriteLine($"错误:找不到资源 '{resourceName}'");
Console.WriteLine("可用的资源有:");
foreach (var name in assembly.GetManifestResourceNames())
{
Console.WriteLine(name);
}
WaitForExitOnError();
return;
}
// 构建目标文件完整路径
string targetFile = Path.Combine(xmindPath, "app.asar");
// 备份原有文件(如果存在)
if (File.Exists(targetFile))
{
string backupFile = targetFile + ".bak";
File.Copy(targetFile, backupFile, true);
Console.WriteLine($"已备份原有文件到: {backupFile}");
}
// 从程序集资源中读取并写入目标文件
using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
using (FileStream fileStream = File.Create(targetFile))
{
resourceStream.CopyTo(fileStream);
}
Console.WriteLine($"文件已成功复制到: {targetFile}");
Console.WriteLine("操作完成!");
// 标记操作成功
operationSuccess = true;
AutoCloseOnSuccess();
}
catch (UnauthorizedAccessException)
{
// 权限不足异常处理
Console.WriteLine("错误:没有足够的权限写入目标文件夹,请以管理员身份运行此程序");
WaitForExitOnError();
}
catch (Exception ex)
{
// 其他异常处理
Console.WriteLine($"发生错误:{ex.Message}");
WaitForExitOnError();
}
}
// 操作成功时的自动关闭功能
static void AutoCloseOnSuccess()
{
Console.WriteLine("\n操作成功,程序将在5秒后自动关闭...");
// 5秒倒计时显示
for (int i = 5; i > 0; i--)
{
Console.Write($"\r倒计时: {i}秒 ");
Thread.Sleep(1000); // 每秒暂停一次
}
Environment.Exit(0); // 成功退出,返回码0
}
// 操作失败时的等待退出功能
static void WaitForExitOnError()
{
Console.WriteLine("\n按任意键退出...");
Console.ReadKey(); // 等待用户按键
Environment.Exit(1); // 错误退出,返回码1
}
// 关闭XMind进程的方法
static void KillXMindProcess()
{
try
{
// 获取所有名为XMind的进程
Process[] processes = Process.GetProcessesByName("XMind");
if (processes.Length > 0)
{
Console.WriteLine($"找到 {processes.Length} 个 XMind 进程,正在关闭...");
// 遍历并关闭所有XMind进程
foreach (Process process in processes)
{
try
{
process.Kill(); // 强制终止进程
process.WaitForExit(2000); // 等待最多2秒
}
catch (Exception ex)
{
Console.WriteLine($"关闭进程 {process.Id} 时出错: {ex.Message}");
}
}
Console.WriteLine("XMind 进程已关闭");
}
else
{
Console.WriteLine("未找到运行的 XMind 进程");
}
}
catch (Exception ex)
{
Console.WriteLine($"查找或关闭 XMind 进程时出错: {ex.Message}");
}
}
// 查找XMind安装路径的方法
static string FindXMindInstallationPath()
{
// 定义可能的安装路径数组
string[] possiblePaths =
{
@"C:\Program Files\XMind\resources", // 默认64位安装路径
@"C:\Program Files (x86)\XMind\resources", // 默认32位安装路径
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "XMind", "resources"), // 系统ProgramFiles路径
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "XMind", "resources") // 系统ProgramFilesX86路径
};
// 检查每个可能的路径
foreach (string path in possiblePaths)
{
if (Directory.Exists(path)) // 如果目录存在
{
return path; // 返回找到的路径
}
}
return null; // 未找到返回null
}
}