最近一个项目需要通过代码来弹出USB外接硬盘设备,经过google找到了下面这个类库:
http://www.codeproject.com/Articles/13530/Eject-USB-disks-using-C
不过这个类库只能在x86下使用,因此需要修改以下内容,使其适用于x64平台
修改DeviceClass为以下代码:
- public List<Device> Devices
- {
- get
- {
- if (_devices == null)
- {
- _devices = new List<Device>();
- int index = 0;
- while (true)
- {
- Native.SP_DEVICE_INTERFACE_DATA interfaceData = new Native.SP_DEVICE_INTERFACE_DATA();
- interfaceData.cbSize = (UInt32)Marshal.SizeOf(interfaceData);
-
- if (!Native.SetupDiEnumDeviceInterfaces(_deviceInfoSet, IntPtr.Zero, ref _classGuid, (UInt32)index, ref interfaceData))
- {
- int error = Marshal.GetLastWin32Error();
- if (error != Native.ERROR_NO_MORE_ITEMS)
- throw new Win32Exception(error);
- break;
- }
- Native.SP_DEVINFO_DATA devData = new Native.SP_DEVINFO_DATA();
- IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(devData));
- Marshal.StructureToPtr(devData, p, true);
- UInt32 size = 0;
- if (!Native.SetupDiGetDeviceInterfaceDetail(_deviceInfoSet, ref interfaceData, IntPtr.Zero, 0, ref size, p))
- {
- int error = Marshal.GetLastWin32Error();
- if (error != Native.ERROR_INSUFFICIENT_BUFFER)
- throw new Win32Exception(error);
- }
- Native.SP_DEVICE_INTERFACE_DETAIL_DATA detailDataBuffer = new Native.SP_DEVICE_INTERFACE_DETAIL_DATA();
- if (IntPtr.Size == 8) // for 64 bit operating systems
- {
- detailDataBuffer.cbSize = 8;
- }
- else
- {
- detailDataBuffer.cbSize = 4 + Marshal.SystemDefaultCharSize; // for 32 bit systems
- }
- IntPtr pBuf = Marshal.AllocHGlobal(Marshal.SizeOf(detailDataBuffer));
-
- Marshal.StructureToPtr(detailDataBuffer, pBuf, true);
-
- if (!Native.SetupDiGetDeviceInterfaceDetail(_deviceInfoSet, ref interfaceData, pBuf, size, ref size, p))
- {
- int error = Marshal.GetLastWin32Error();
- if (error != Native.ERROR_INSUFFICIENT_BUFFER)
- throw new Win32Exception(error);
- }
- devData = (Native.SP_DEVINFO_DATA)Marshal.PtrToStructure(p, typeof(Native.SP_DEVINFO_DATA));
- Marshal.FreeHGlobal(p);
-
- detailDataBuffer = (Native.SP_DEVICE_INTERFACE_DETAIL_DATA)Marshal.PtrToStructure(pBuf, typeof(Native.SP_DEVICE_INTERFACE_DETAIL_DATA));
- Marshal.FreeHGlobal(pBuf);
-
- string devicePath = detailDataBuffer.DevicePath;
- Native.STORAGE_DEVICE_NUMBER storageDeviceNumber = GetDeviceNumber(devicePath);
- Device device = CreateDevice(this, devData, devicePath, storageDeviceNumber.DeviceNumber);
- _devices.Add(device);
-
- index++;
- }
- _devices.Sort();
- }
- return _devices;
- }
- }
添加以下函数到DeviceClass.cs
- internal Native.STORAGE_DEVICE_NUMBER GetDeviceNumber(string devicePath)
- {
- IntPtr hFile = Native.CreateFile(devicePath.TrimEnd('\\'), 0, 0, IntPtr.Zero, Native.OPEN_EXISTING, 0, IntPtr.Zero);
- if (hFile.ToInt32() == Native.INVALID_HANDLE_VALUE)
- throw new Win32Exception(Marshal.GetLastWin32Error());
- int bytesReturned;
- Native.STORAGE_DEVICE_NUMBER storageDeviceNumber = new Native.STORAGE_DEVICE_NUMBER();
- int size = Marshal.SizeOf(storageDeviceNumber);
- IntPtr buffer = Marshal.AllocHGlobal(size);
- try
- {
- if (!Native.DeviceIoControl(hFile, Native.IOCTL_STORAGE_GET_DEVICE_NUMBER, IntPtr.Zero, 0, buffer, size, out bytesReturned, IntPtr.Zero))
- {
- // do nothing here on purpose
- }
- }
- finally
- {
- Native.CloseHandle(hFile);
- }
- if (bytesReturned > 0)
- {
- storageDeviceNumber = (Native.STORAGE_DEVICE_NUMBER)Marshal.PtrToStructure(buffer, typeof(Native.STORAGE_DEVICE_NUMBER));
- }
- Marshal.FreeHGlobal(buffer);
- return storageDeviceNumber;
- }
Native.cs 添加:
- [StructLayout(LayoutKind.Sequential)]
- internal struct STORAGE_DEVICE_NUMBER
- {
- public int DeviceType;
- public int DeviceNumber;
- public int PartitionNumber;
- }
-
- internal const int IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080;
修改Volumn.cs
IntPtr hFile = Native.CreateFile(@"\\.\" + LogicalDrive, Native.GENERIC_READ, Native.FILE_SHARE_READ | Native.FILE_SHARE_WRITE, IntPtr.Zero, Native.OPEN_EXISTING, 0, IntPtr.Zero);
为:
IntPtr hFile = Native.CreateFile(@"\\.\" + LogicalDrive, 0, Native.FILE_SHARE_READ | Native.FILE_SHARE_WRITE, IntPtr.Zero, Native.OPEN_EXISTING, 0, IntPtr.Zero);
修改Native.cs
- [StructLayout(LayoutKind.Sequential)]
- internal class SP_DEVINFO_DATA
- {
- internal int cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
- internal Guid classGuid = Guid.Empty; // temp
- internal int devInst = 0; // dumy
- internal int reserved = 0;
- }
-
- [StructLayout(LayoutKind.Sequential, Pack = 2)]
- internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
- {
- internal int cbSize;
- internal short devicePath;
- }
-
- [StructLayout(LayoutKind.Sequential)]
- internal class SP_DEVICE_INTERFACE_DATA
- {
- internal int cbSize = Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DATA));
- internal Guid interfaceClassGuid = Guid.Empty; // temp
- internal int flags = 0;
- internal int reserved = 0;
- }
为:
- [StructLayout(LayoutKind.Sequential)]
- internal class SP_DEVINFO_DATA
- {
- internal int cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
- internal Guid classGuid = Guid.Empty; // temp
- internal int devInst = 0; // dumy
- internal IntPtr reserved = IntPtr.Zero;
- }
-
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
- {
- internal Int32 cbSize;
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
- internal string DevicePath;
- }
-
-
- [StructLayout(LayoutKind.Sequential)]
- internal struct SP_DEVICE_INTERFACE_DATA
- {
- internal UInt32 cbSize;
- internal Guid interfaceClassGuid;
- internal UInt32 flags;
- internal UIntPtr reserved;
- }
修改Volume.cs
IntPtr extentPtr = new IntPtr(buffer.ToInt32() + Marshal.SizeOf(typeof(long)) + i * Marshal.SizeOf(typeof(Native.DISK_EXTENT)));
为
IntPtr extentPtr = new IntPtr(buffer.ToInt64() + Marshal.SizeOf(typeof(long)) + i * Marshal.SizeOf(typeof(Native.DISK_EXTENT)));
源代码下载