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); } } }); } } }