first commit
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
name: Build VHD Mounter
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
pull_request:
|
||||
branches: [ main, master ]
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: '6.0.x'
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build
|
||||
run: dotnet build --configuration Release --no-restore
|
||||
|
||||
- name: Test
|
||||
run: dotnet test --no-build --verbosity normal
|
||||
continue-on-error: true
|
||||
|
||||
- name: Publish Windows x64
|
||||
run: dotnet publish --configuration Release --runtime win-x64 --self-contained true --output ./publish/win-x64
|
||||
|
||||
- name: Publish Windows x86
|
||||
run: dotnet publish --configuration Release --runtime win-x86 --self-contained true --output ./publish/win-x86
|
||||
|
||||
- name: Upload Windows x64 artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: VHDMounter-win-x64
|
||||
path: ./publish/win-x64/
|
||||
|
||||
- name: Upload Windows x86 artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: VHDMounter-win-x86
|
||||
path: ./publish/win-x86/
|
||||
|
||||
- name: Create Release Assets
|
||||
if: github.event_name == 'release'
|
||||
run: |
|
||||
Compress-Archive -Path ./publish/win-x64/* -DestinationPath VHDMounter-win-x64.zip
|
||||
Compress-Archive -Path ./publish/win-x86/* -DestinationPath VHDMounter-win-x86.zip
|
||||
|
||||
- name: Upload Release Assets
|
||||
if: github.event_name == 'release'
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ github.event.release.upload_url }}
|
||||
asset_path: ./VHDMounter-win-x64.zip
|
||||
asset_name: VHDMounter-win-x64.zip
|
||||
asset_content_type: application/zip
|
||||
|
||||
- name: Upload Release Assets x86
|
||||
if: github.event_name == 'release'
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ github.event.release.upload_url }}
|
||||
asset_path: ./VHDMounter-win-x86.zip
|
||||
asset_name: VHDMounter-win-x86.zip
|
||||
asset_content_type: application/zip
|
||||
@@ -0,0 +1,78 @@
|
||||
<Window x:Class="VHDMounter.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="VHD Mounter"
|
||||
WindowState="Maximized"
|
||||
WindowStyle="None"
|
||||
Topmost="True"
|
||||
Background="White"
|
||||
KeyDown="Window_KeyDown">
|
||||
|
||||
<Grid>
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,100">
|
||||
<!-- 状态显示 -->
|
||||
<TextBlock x:Name="StatusText"
|
||||
Text="正在初始化..."
|
||||
FontSize="24"
|
||||
FontWeight="Bold"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,0,0,30"
|
||||
Foreground="Black"/>
|
||||
|
||||
<!-- VHD选择器 -->
|
||||
<StackPanel x:Name="VHDSelector" Visibility="Collapsed">
|
||||
<TextBlock Text="发现多个VHD文件,请选择一个:"
|
||||
FontSize="18"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,0,0,20"
|
||||
Foreground="Black"/>
|
||||
|
||||
<ListBox x:Name="VHDListBox"
|
||||
Width="600"
|
||||
Height="300"
|
||||
FontSize="14"
|
||||
SelectionMode="Single"
|
||||
Background="#F0F0F0"
|
||||
BorderBrush="#CCCCCC"
|
||||
BorderThickness="1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding}" Padding="10,5" Foreground="Black"/>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
|
||||
<TextBlock Text="使用上下键选择,回车确认"
|
||||
FontSize="14"
|
||||
HorizontalAlignment="Center"
|
||||
Margin="0,10,0,0"
|
||||
Foreground="Gray"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 进度指示器 -->
|
||||
<ProgressBar x:Name="ProgressBar"
|
||||
Width="400"
|
||||
Height="20"
|
||||
Margin="0,30,0,0"
|
||||
IsIndeterminate="True"
|
||||
Visibility="Visible"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 关闭按钮 -->
|
||||
<Button x:Name="CloseButton"
|
||||
Content="×"
|
||||
Width="40"
|
||||
Height="40"
|
||||
FontSize="24"
|
||||
FontWeight="Bold"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Top"
|
||||
Margin="0,10,10,0"
|
||||
Background="Transparent"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
Foreground="Gray"
|
||||
Click="CloseButton_Click"
|
||||
Cursor="Hand"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,210 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace VHDMounter
|
||||
{
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private VHDManager vhdManager;
|
||||
private List<string> availableVHDs;
|
||||
private bool isProcessing = false;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
vhdManager = new VHDManager();
|
||||
vhdManager.StatusChanged += OnStatusChanged;
|
||||
vhdManager.VHDFilesFound += OnVHDFilesFound;
|
||||
|
||||
// 注册开机启动
|
||||
if (!StartupManager.IsRegisteredForStartup())
|
||||
{
|
||||
StartupManager.RegisterForStartup();
|
||||
}
|
||||
|
||||
// 开始主流程
|
||||
_ = StartMainProcess();
|
||||
}
|
||||
|
||||
private void OnStatusChanged(string status)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
StatusText.Text = status;
|
||||
});
|
||||
}
|
||||
|
||||
private void OnVHDFilesFound(List<string> vhdFiles)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
availableVHDs = vhdFiles;
|
||||
ShowVHDSelector(vhdFiles);
|
||||
});
|
||||
}
|
||||
|
||||
private async Task StartMainProcess()
|
||||
{
|
||||
try
|
||||
{
|
||||
isProcessing = true;
|
||||
|
||||
// 扫描VHD文件
|
||||
var vhdFiles = await vhdManager.ScanForVHDFiles();
|
||||
|
||||
if (vhdFiles.Count == 0)
|
||||
{
|
||||
OnStatusChanged("未找到符合条件的VHD文件");
|
||||
await Task.Delay(3000);
|
||||
Application.Current.Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
string selectedVHD;
|
||||
|
||||
if (vhdFiles.Count == 1)
|
||||
{
|
||||
selectedVHD = vhdFiles[0];
|
||||
await ProcessSelectedVHD(selectedVHD);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 显示选择器
|
||||
availableVHDs = vhdFiles;
|
||||
ShowVHDSelector(vhdFiles);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnStatusChanged($"发生错误: {ex.Message}");
|
||||
await Task.Delay(5000);
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowVHDSelector(List<string> vhdFiles)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
VHDListBox.ItemsSource = vhdFiles.Select(f => System.IO.Path.GetFileName(f)).ToList();
|
||||
VHDListBox.SelectedIndex = 0;
|
||||
VHDSelector.Visibility = Visibility.Visible;
|
||||
ProgressBar.Visibility = Visibility.Collapsed;
|
||||
OnStatusChanged("请选择要挂载的VHD文件");
|
||||
});
|
||||
}
|
||||
|
||||
private async Task ProcessSelectedVHD(string vhdPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
VHDSelector.Visibility = Visibility.Collapsed;
|
||||
ProgressBar.Visibility = Visibility.Visible;
|
||||
});
|
||||
|
||||
// 挂载VHD
|
||||
bool mounted = await vhdManager.MountVHD(vhdPath);
|
||||
if (!mounted)
|
||||
{
|
||||
OnStatusChanged("VHD挂载失败");
|
||||
await Task.Delay(3000);
|
||||
Application.Current.Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
// 查找package文件夹
|
||||
string packagePath = await vhdManager.FindPackageFolder();
|
||||
if (string.IsNullOrEmpty(packagePath))
|
||||
{
|
||||
OnStatusChanged("未找到package文件夹");
|
||||
await Task.Delay(3000);
|
||||
Application.Current.Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
// 启动start.bat
|
||||
bool started = await vhdManager.StartBatchFile(packagePath);
|
||||
if (!started)
|
||||
{
|
||||
OnStatusChanged("启动start.bat失败");
|
||||
await Task.Delay(3000);
|
||||
Application.Current.Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
OnStatusChanged("程序启动成功,开始监控...");
|
||||
|
||||
// 隐藏窗口并开始监控
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
this.WindowState = WindowState.Minimized;
|
||||
this.ShowInTaskbar = false;
|
||||
});
|
||||
|
||||
// 开始监控和重启循环
|
||||
await vhdManager.MonitorAndRestart(packagePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnStatusChanged($"处理过程中发生错误: {ex.Message}");
|
||||
await Task.Delay(5000);
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private async void Window_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (isProcessing || VHDSelector.Visibility != Visibility.Visible)
|
||||
return;
|
||||
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Up:
|
||||
if (VHDListBox.SelectedIndex > 0)
|
||||
VHDListBox.SelectedIndex--;
|
||||
break;
|
||||
|
||||
case Key.Down:
|
||||
if (VHDListBox.SelectedIndex < VHDListBox.Items.Count - 1)
|
||||
VHDListBox.SelectedIndex++;
|
||||
break;
|
||||
|
||||
case Key.Enter:
|
||||
if (VHDListBox.SelectedIndex >= 0 && availableVHDs != null)
|
||||
{
|
||||
isProcessing = true;
|
||||
string selectedVHD = availableVHDs[VHDListBox.SelectedIndex];
|
||||
await ProcessSelectedVHD(selectedVHD);
|
||||
}
|
||||
break;
|
||||
|
||||
case Key.Escape:
|
||||
Application.Current.Shutdown();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Application.Current.Shutdown();
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
// 程序关闭时卸载VHD
|
||||
try
|
||||
{
|
||||
_ = vhdManager.UnmountDrive();
|
||||
}
|
||||
catch { }
|
||||
|
||||
base.OnClosed(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace VHDMounter
|
||||
{
|
||||
class Program
|
||||
{
|
||||
[STAThread]
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// 检查是否已有实例运行
|
||||
using (var mutex = new System.Threading.Mutex(true, "VHDMounterApp", out bool createdNew))
|
||||
{
|
||||
if (!createdNew)
|
||||
{
|
||||
return; // 已有实例运行,退出
|
||||
}
|
||||
|
||||
var app = new Application();
|
||||
var mainWindow = new MainWindow();
|
||||
app.Run(mainWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
# VHD Mounter - VHD自动挂载工具
|
||||
|
||||
## 功能描述
|
||||
|
||||
这是一个Windows桌面应用程序,用于自动挂载包含特定关键词的VHD文件并管理相关进程。
|
||||
|
||||
### 主要功能
|
||||
|
||||
1. **开机自启动** - 程序会自动注册到Windows开机启动项
|
||||
2. **VHD文件扫描** - 自动扫描所有磁盘驱动器,查找文件名包含SDEZ/SDHD/SDDT的VHD文件
|
||||
3. **智能挂载** - 将选中的VHD文件挂载为M盘
|
||||
4. **用户选择界面** - 当发现多个符合条件的VHD文件时,提供全屏选择界面
|
||||
5. **自动启动** - 在挂载的VHD中查找package文件夹并启动其中的start.bat
|
||||
6. **进程监控** - 监控sinmai/chusanapp/mu3相关进程,如果进程停止则自动重启start.bat
|
||||
7. **全屏状态显示** - 在操作过程中显示全屏白色界面,实时显示当前任务状态
|
||||
|
||||
## 系统要求
|
||||
|
||||
- Windows 10/11
|
||||
- .NET 6.0 Runtime
|
||||
- 管理员权限(用于VHD挂载操作)
|
||||
|
||||
## 编译和运行
|
||||
|
||||
### 编译
|
||||
|
||||
```bash
|
||||
dotnet build --configuration Release
|
||||
```
|
||||
|
||||
### 发布
|
||||
|
||||
```bash
|
||||
dotnet publish --configuration Release --self-contained true --runtime win-x64
|
||||
```
|
||||
|
||||
### 运行
|
||||
|
||||
程序需要以管理员身份运行才能执行VHD挂载操作。
|
||||
|
||||
## 使用说明
|
||||
|
||||
1. **首次运行**:程序会自动注册到开机启动项
|
||||
2. **VHD扫描**:程序启动后会自动扫描所有驱动器查找符合条件的VHD文件
|
||||
3. **文件选择**:
|
||||
- 如果只找到一个VHD文件,会自动挂载
|
||||
- 如果找到多个VHD文件,会显示选择界面
|
||||
- 使用上下键选择,回车确认
|
||||
4. **自动挂载**:选中的VHD文件会被挂载为M盘
|
||||
5. **启动程序**:自动查找并启动M盘中package文件夹内的start.bat
|
||||
6. **后台监控**:程序会在后台持续监控目标进程,必要时重启
|
||||
|
||||
## 界面操作
|
||||
|
||||
- **上下键**:在VHD选择界面中切换选项
|
||||
- **回车键**:确认选择
|
||||
- **ESC键**:退出程序
|
||||
- **右上角×按钮**:关闭程序
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **管理员权限**:程序必须以管理员身份运行
|
||||
2. **VHD文件要求**:文件名必须包含SDEZ、SDHD或SDDT关键词
|
||||
3. **目标驱动器**:VHD文件会被挂载为M盘,如果M盘已被占用会先卸载
|
||||
4. **进程监控**:程序会监控包含sinmai、chusanapp或mu3关键词的进程
|
||||
5. **自动重启**:如果目标进程停止运行,程序会自动重启start.bat
|
||||
|
||||
## 故障排除
|
||||
|
||||
1. **挂载失败**:确保以管理员身份运行程序
|
||||
2. **找不到VHD文件**:检查文件名是否包含必要的关键词
|
||||
3. **start.bat启动失败**:确保package文件夹中存在start.bat文件
|
||||
4. **进程监控异常**:检查目标程序是否正常运行
|
||||
|
||||
## 技术实现
|
||||
|
||||
- **框架**:.NET 6.0 + WPF
|
||||
- **VHD挂载**:使用Windows diskpart命令
|
||||
- **进程监控**:System.Diagnostics.Process
|
||||
- **开机启动**:Windows注册表
|
||||
- **权限管理**:应用程序清单文件
|
||||
@@ -0,0 +1,71 @@
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace VHDMounter
|
||||
{
|
||||
public class StartupManager
|
||||
{
|
||||
private const string APP_NAME = "VHDMounter";
|
||||
private const string REGISTRY_KEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
|
||||
|
||||
public static bool IsRegisteredForStartup()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var key = Registry.CurrentUser.OpenSubKey(REGISTRY_KEY, false))
|
||||
{
|
||||
return key?.GetValue(APP_NAME) != null;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool RegisterForStartup()
|
||||
{
|
||||
try
|
||||
{
|
||||
var exePath = Assembly.GetExecutingAssembly().Location;
|
||||
if (exePath.EndsWith(".dll"))
|
||||
{
|
||||
// 如果是.dll,需要找到对应的.exe
|
||||
exePath = exePath.Replace(".dll", ".exe");
|
||||
}
|
||||
|
||||
using (var key = Registry.CurrentUser.OpenSubKey(REGISTRY_KEY, true))
|
||||
{
|
||||
key?.SetValue(APP_NAME, $"\"{exePath}\"");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"注册开机启动失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool UnregisterFromStartup()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var key = Registry.CurrentUser.OpenSubKey(REGISTRY_KEY, true))
|
||||
{
|
||||
key?.DeleteValue(APP_NAME, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"取消开机启动失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace VHDMounter
|
||||
{
|
||||
public class VHDManager
|
||||
{
|
||||
private const string TARGET_DRIVE = "M:";
|
||||
private readonly string[] TARGET_KEYWORDS = { "SDEZ", "SDHD", "SDDT" };
|
||||
private readonly string[] PROCESS_KEYWORDS = { "sinmai", "chusanapp", "mu3" };
|
||||
|
||||
public event Action<string> StatusChanged;
|
||||
public event Action<List<string>> VHDFilesFound;
|
||||
|
||||
public async Task<List<string>> ScanForVHDFiles()
|
||||
{
|
||||
StatusChanged?.Invoke("正在扫描VHD文件...");
|
||||
var vhdFiles = new List<string>();
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
var drives = DriveInfo.GetDrives().Where(d => d.IsReady && d.DriveType == DriveType.Fixed);
|
||||
|
||||
foreach (var drive in drives)
|
||||
{
|
||||
try
|
||||
{
|
||||
var files = Directory.GetFiles(drive.RootDirectory.FullName, "*.vhd", SearchOption.AllDirectories)
|
||||
.Where(f => TARGET_KEYWORDS.Any(keyword => Path.GetFileName(f).ToUpper().Contains(keyword)))
|
||||
.ToList();
|
||||
|
||||
vhdFiles.AddRange(files);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 忽略无法访问的目录
|
||||
Debug.WriteLine($"扫描驱动器 {drive.Name} 时出错: {ex.Message}");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return vhdFiles;
|
||||
}
|
||||
|
||||
public async Task<bool> MountVHD(string vhdPath)
|
||||
{
|
||||
StatusChanged?.Invoke($"正在挂载VHD文件: {Path.GetFileName(vhdPath)}");
|
||||
|
||||
try
|
||||
{
|
||||
// 先卸载M盘(如果已挂载)
|
||||
await UnmountDrive();
|
||||
|
||||
// 使用diskpart挂载VHD
|
||||
var diskpartScript = $@"select vdisk file=""{vhdPath}""
|
||||
attach vdisk
|
||||
assign letter=M
|
||||
exit";
|
||||
|
||||
var tempScript = Path.GetTempFileName();
|
||||
await File.WriteAllTextAsync(tempScript, diskpartScript);
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "diskpart",
|
||||
Arguments = $"/s \"{tempScript}\"",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
await process.WaitForExitAsync();
|
||||
|
||||
File.Delete(tempScript);
|
||||
|
||||
// 等待挂载完成
|
||||
await Task.Delay(2000);
|
||||
|
||||
return Directory.Exists(TARGET_DRIVE);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusChanged?.Invoke($"挂载失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UnmountDrive()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(TARGET_DRIVE))
|
||||
return true;
|
||||
|
||||
var diskpartScript = "select volume M\nremove\nexit";
|
||||
var tempScript = Path.GetTempFileName();
|
||||
await File.WriteAllTextAsync(tempScript, diskpartScript);
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "diskpart",
|
||||
Arguments = $"/s \"{tempScript}\"",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
await process.WaitForExitAsync();
|
||||
|
||||
File.Delete(tempScript);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> FindPackageFolder()
|
||||
{
|
||||
StatusChanged?.Invoke("正在搜索package文件夹...");
|
||||
|
||||
if (!Directory.Exists(TARGET_DRIVE))
|
||||
return null;
|
||||
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var directories = Directory.GetDirectories(TARGET_DRIVE, "*", SearchOption.AllDirectories)
|
||||
.Where(d => Path.GetFileName(d).ToLower() == "package")
|
||||
.FirstOrDefault();
|
||||
|
||||
return directories;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<bool> StartBatchFile(string packagePath)
|
||||
{
|
||||
var startBatPath = Path.Combine(packagePath, "start.bat");
|
||||
|
||||
if (!File.Exists(startBatPath))
|
||||
{
|
||||
StatusChanged?.Invoke("未找到start.bat文件");
|
||||
return false;
|
||||
}
|
||||
|
||||
StatusChanged?.Invoke("正在启动start.bat...");
|
||||
|
||||
try
|
||||
{
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = startBatPath,
|
||||
WorkingDirectory = packagePath,
|
||||
UseShellExecute = true,
|
||||
CreateNoWindow = false
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusChanged?.Invoke($"启动失败: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsTargetProcessRunning()
|
||||
{
|
||||
try
|
||||
{
|
||||
var processes = Process.GetProcesses();
|
||||
return processes.Any(p => PROCESS_KEYWORDS.Any(keyword =>
|
||||
p.ProcessName.ToLower().Contains(keyword.ToLower())));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task MonitorAndRestart(string packagePath)
|
||||
{
|
||||
StatusChanged?.Invoke("等待15秒后开始监控进程...");
|
||||
await Task.Delay(15000); // 等待15秒
|
||||
|
||||
StatusChanged?.Invoke("开始监控目标进程...");
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!IsTargetProcessRunning())
|
||||
{
|
||||
StatusChanged?.Invoke("目标进程未运行,重新启动start.bat...");
|
||||
await StartBatchFile(packagePath);
|
||||
await Task.Delay(15000); // 重启后等待15秒
|
||||
}
|
||||
|
||||
await Task.Delay(1000); // 每秒检查一次
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Management" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="VHDMounter.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
@@ -0,0 +1,28 @@
|
||||
@echo off
|
||||
echo VHD Mounter 编译脚本
|
||||
echo ==================
|
||||
|
||||
echo 正在编译项目...
|
||||
dotnet build --configuration Release
|
||||
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
echo.
|
||||
echo 编译成功!
|
||||
echo.
|
||||
echo 正在发布自包含版本...
|
||||
dotnet publish --configuration Release --self-contained true --runtime win-x64 --output ./publish
|
||||
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
echo.
|
||||
echo 发布成功!
|
||||
echo 可执行文件位置: ./publish/VHDMounter.exe
|
||||
echo.
|
||||
echo 注意:程序需要以管理员身份运行!
|
||||
) else (
|
||||
echo 发布失败!
|
||||
)
|
||||
) else (
|
||||
echo 编译失败!
|
||||
)
|
||||
|
||||
pause
|
||||
@@ -0,0 +1,34 @@
|
||||
@echo off
|
||||
echo VHD Mounter 管理员运行脚本
|
||||
echo ============================
|
||||
|
||||
REM 检查是否以管理员身份运行
|
||||
net session >nul 2>&1
|
||||
if %errorLevel% == 0 (
|
||||
echo 已以管理员身份运行
|
||||
echo.
|
||||
) else (
|
||||
echo 请求管理员权限...
|
||||
powershell -Command "Start-Process '%~f0' -Verb RunAs"
|
||||
exit /b
|
||||
)
|
||||
|
||||
REM 检查可执行文件是否存在
|
||||
if exist "./publish/VHDMounter.exe" (
|
||||
echo 启动 VHD Mounter...
|
||||
cd publish
|
||||
VHDMounter.exe
|
||||
) else if exist "./bin/Release/net6.0-windows/VHDMounter.exe" (
|
||||
echo 启动 VHD Mounter (Debug版本)...
|
||||
cd bin/Release/net6.0-windows
|
||||
VHDMounter.exe
|
||||
) else (
|
||||
echo 错误:找不到可执行文件!
|
||||
echo 请先运行 build.bat 编译项目
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo 程序已退出
|
||||
pause
|
||||
Reference in New Issue
Block a user