using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace AIK.Service.Interop
{
///
/// P/Invoke 方法实现 Windows 卷弹出功能
///
internal static class WindowsVolumeEjector
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
uint nInBufferSize,
IntPtr lpOutBuffer,
uint nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
private static extern bool CloseHandle(IntPtr hObject);
private const uint GENERIC_READ = 0x80000000;
private const uint FILE_SHARE_READ = 0x1;
private const uint FILE_SHARE_WRITE = 0x2;
private const uint OPEN_EXISTING = 3;
private const uint FSCTL_DISMOUNT_VOLUME = 0x00090020;
private const uint IOCTL_STORAGE_EJECT_MEDIA = 0x2D4808;
public static async Task EjectVolumeAsync(string driveLetter)
{
return await Task.Run(() =>
{
if (string.IsNullOrEmpty(driveLetter))
return false;
// 标准化输入:确保是 "X:" 或 "X:\"
string cleanDrive = driveLetter.TrimEnd('\\');
if (!cleanDrive.EndsWith(":"))
return false;
string devicePath = @"\\.\" + cleanDrive + @"\";
IntPtr handle = IntPtr.Zero;
try
{
handle = CreateFile(devicePath, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
if (handle == IntPtr.Zero || handle == new IntPtr(-1))
{
var errorCode = Marshal.GetLastWin32Error();
// 可记录日志:$"CreateFile failed with error {errorCode}"
return false;
}
// 尝试卸载卷(可选,提高成功率)
DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME,
IntPtr.Zero, 0, IntPtr.Zero, 0, out _, IntPtr.Zero);
// 弹出介质
bool result = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA,
IntPtr.Zero, 0, IntPtr.Zero, 0, out _, IntPtr.Zero);
return result;
}
catch (Exception ex)
{
// 可记录异常
return false;
}
finally
{
if (handle != IntPtr.Zero && handle != new IntPtr(-1))
{
CloseHandle(handle);
}
}
});
}
}
}