如何判断一个volume是否已经被mount?(回复就给分)

时间:2021-02-27 09:00:04
我的代码是这样的:
uDiskName=_T("\\\\.\\C:");
m_hUDisk=CreateFile(LPCTSTR(uDiskName),0,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,
0,NULL);
bResult = DeviceIoControl(m_hUDisk,
                                   FSCTL_IS_VOLUME_MOUNTED,
                              NULL, 0, 
                          NULL, 0,      
                                   &junk,  
                                   (LPOVERLAPPED) NULL);  
         LastError=GetLastError();

运行后得到的结果:bResult为0,但是LastError却为1.
MSDN中关于返回值是这样说的:
If the volume is currently mounted, DeviceIoControl returns zero.
Otherwise, DeviceIoControl returns an error code.
既然已经判断出c盘已经被mount,那么为什么错误代码却为1(ERROR_FUNCTION)?


11 个解决方案

#1


如果control code为FSCTL_IS_VOLUME_MOUNTED,那么返回结果以及错误代码和上面的一样,按msdn的说法:If the operation succeeds, DeviceIoControl returns a nonzero value.If the operation fails, DeviceIoControl returns zero.也就是说不成功,那么应该如何将一个已经mount的volume dismount?

#2


不好意思,刚才的回复里应该是"如果control code为FSCTL_DISMOUNT_VOLUME".
另外,我试了一下,如果CreateFile时第二个参数为GENERIC_READ或者GENERIC_WRITE时,对U盘执行dismount操作,那么得到的bResult为1,LastError为0,这样的结果好象是对的.而且我在执行时正在往U盘里面写文件,一执行,系统就提示说copy过程被中断,说明的确是已经强行dismount了.但是执行了以后U盘的灯怎么还是亮着?如果这样是对的,那么为什么要加GENERIC_READ或者GENERIC_WRITE?

#3


我觉得msdn关于用DeviceIoControl发送FSCTL_IS_VOLUME_MOUNTED的返回值说明有错,发送其他的FSCTL_XX_XXX请求返回值一律是成功为非0而不成功为0,独独这个FSCTL_IS_VOLUME_MOUNTED的说明相反.事实上,我调试的结果也支持我的看法.
    还有个问题令我很困惑:用DeviceIoControl发送FSCTL_IS_VOLUME_MOUNTED请求之前,必须先调用CreateFile得到对应volume的handle,那岂不是说每次检查volume是否被mount一定会显示已经mount(因为如果原来没mount,调用了CreateFile之后,windows的I/O Manager也会mount)?

#4


确实应该是成功返回非0值,大概是MSDN的版本问题,你到MSDN的网站在查一下就知道成功时返回非0值。

你在调用 CreateFile 时指定了OPEN_EXISTING 就不会自动mount了,如果volume不存在的话,直接返回一个无效的句柄。

#5


看了你的回复,这个问题我知道了.谢谢回答.
但是前面还有个问题:CreateFile时为什么要加GENERIC_READ或者GENERIC_WRITE才能正常调用?请指教,分数一定会给.

#6


seaquester: 

  我觉得你说的"调用 CreateFile 时指定了OPEN_EXISTING 就不会自动mount"好象有问题,我试了一下,我发送dismount请求后立即发送FSCTL_IS_VOLUME_MOUNTED请求,结果返回是0,error code是21(The device is not ready),这是对的,说明已经成功dismount了.
    但是我结束本次debug,然后再次开始debug(此时应该没有volume,因为我在两次调试之间没有对U盘进行任何操作),调用 CreateFile (指定了OPEN_EXISTING)的结果是得到了有效handle,而且接着发送FSCTL_IS_VOLUME_MOUNTED请求返回1,说明已经mount.这怎么解释呢? 

#7


下面是我的代码,在Win2000下面试过了,没有问题。



#include <windows.h>
#include <stdio.h>


//----------------------------------------------------------------------
//
// PrintWin32Error
//
// Takes the win32 error code and prints the text version.
//
//----------------------------------------------------------------------
void PrintWin32Error( PCHAR Message, DWORD ErrorCode )
{
   LPVOID lpMsgBuf;

   FormatMessage(
      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
      NULL,
      ErrorCode,
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
      (PCHAR) &lpMsgBuf,
      0,
      NULL
      );
   fprintf(stderr, "%s: %s\n", Message, lpMsgBuf );
   LocalFree( lpMsgBuf );
}


void main()
{
   HANDLE   hDevice;
   BOOL     bResult;
   DWORD    dwBytesReturned;
   DWORD    dwError;
   char     s[64];


   //
   // Getting a handle to a volume.
   //
   LPCTSTR szDiskName = "\\\\.\\F:";
   hDevice = CreateFile(
      szDiskName,
      GENERIC_READ,
      FILE_SHARE_READ | FILE_SHARE_WRITE,
      NULL,
      OPEN_EXISTING,
      0,
      NULL
      );
   if ((hDevice == NULL) || (hDevice == INVALID_HANDLE_VALUE))
   {
      sprintf(s, "The volume %s is not mounted!", szDiskName);
      PrintWin32Error(s, GetLastError());
      return;
   }

   // Check if The volume is mounted or not.
   bResult = DeviceIoControl(
      hDevice,
      FSCTL_IS_VOLUME_MOUNTED,
      NULL,
      0,
      NULL,
      0,
      &dwBytesReturned,
      NULL
      );
   dwError = GetLastError();
   if (bResult)
   {
      printf("The volume %s is mounted!\n", szDiskName);
   }
   else
   {
      sprintf(s, "The volume %s is not mounted!", szDiskName);
      PrintWin32Error(s, GetLastError());
   }

   CloseHandle(hDevice);
}

#8


我明白你的意思,你是说如果没有插入U盘,或者使用系统提供的"安全删除硬件"程序,则volume肯定是不存在的,CreateFile肯定是返回无效handle,这样的情况下肯定不可能自动mount.
    但是我还有个问题,还想麻烦大侠指点一下,我自己在程序里面dismount的结果是U盘的灯还是亮的,而且还是可以在"我的电脑"中看到盘符;而使用系统提供的"安全删除硬件"程序的结果是灯不亮而且盘符已经消失了.这两种方法的区别在哪里?(我想,这应该就是我dismount以后再CreateFile时又自动mount的原因,可能volume并没有真正被删除?)
    真想把这个问题搞懂,觉得分数不够可以另开贴给你加.谢谢!

#9


只的dismount达不到安全删除的效果,MSDN里面提供了一种实现方案(我没试过,你自己试一下):

Knowledge Base  

HOWTO: Ejecting Removable Media in Windows NT/Windows 2000/Windows XPPSS ID Number:Q165721
Article Last Modified on 01-20-2002
--------------------------------------------------------------------------------
The information in this article applies to: 
Microsoft Win32 Application Programming Interface (API)
the operating system: Microsoft Windows NT 3.5, 3.51, 4.0 
the operating system: Microsoft Windows 2000 
the operating system: Microsoft Windows XP

--------------------------------------------------------------------------------

   #include <windows.h>
   #include <winioctl.h>
   #include <tchar.h>
   #include <stdio.h>

   // Prototypes
   BOOL EjectVolume(TCHAR cDriveLetter);
   HANDLE OpenVolume(TCHAR cDriveLetter);
   BOOL LockVolume(HANDLE hVolume);
   BOOL DismountVolume(HANDLE hVolume);
   BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent);
   BOOL AutoEjectVolume(HANDLE hVolume);
   BOOL CloseVolume(HANDLE hVolume);

   LPTSTR szVolumeFormat = TEXT("\\\\.\\%c:");
   LPTSTR szRootFormat = TEXT("%c:\\");
   LPTSTR szErrorFormat = TEXT("Error %d: %s\n");

   void ReportError(LPTSTR szMsg)
   {
       _tprintf(szErrorFormat, GetLastError(), szMsg);
   }

   HANDLE OpenVolume(TCHAR cDriveLetter)
   {
       HANDLE hVolume;
       UINT uDriveType;
       TCHAR szVolumeName[8];
       TCHAR szRootName[5];
       DWORD dwAccessFlags;

       wsprintf(szRootName, szRootFormat, cDriveLetter);

       uDriveType = GetDriveType(szRootName);
       switch(uDriveType) {
       case DRIVE_REMOVABLE:
           dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
           break;
       case DRIVE_CDROM:
           dwAccessFlags = GENERIC_READ;
           break;
       default:
           _tprintf(TEXT("Cannot eject.  Drive type is incorrect.\n"));
           return INVALID_HANDLE_VALUE;
       }

       wsprintf(szVolumeName, szVolumeFormat, cDriveLetter);

       hVolume = CreateFile(   szVolumeName,
                               dwAccessFlags,
                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                               NULL,
                               OPEN_EXISTING,
                               0,
                               NULL );
       if (hVolume == INVALID_HANDLE_VALUE)
           ReportError(TEXT("CreateFile"));

       return hVolume;
   }

   BOOL CloseVolume(HANDLE hVolume)
   {
       return CloseHandle(hVolume);
   }

   #define LOCK_TIMEOUT        10000       // 10 Seconds
   #define LOCK_RETRIES        20

   BOOL LockVolume(HANDLE hVolume)
   {
       DWORD dwBytesReturned;
       DWORD dwSleepAmount;
       int nTryCount;

       dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;

       // Do this in a loop until a timeout period has expired
       for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
           if (DeviceIoControl(hVolume,
                               FSCTL_LOCK_VOLUME,
                               NULL, 0,
                               NULL, 0,
                               &dwBytesReturned,
                               NULL))
               return TRUE;

           Sleep(dwSleepAmount);
       }

       return FALSE;
   }

   BOOL DismountVolume(HANDLE hVolume)
   {
       DWORD dwBytesReturned;

       return DeviceIoControl( hVolume,
                               FSCTL_DISMOUNT_VOLUME,
                               NULL, 0,
                               NULL, 0,
                               &dwBytesReturned,
                               NULL);
   }

   BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
   {
       DWORD dwBytesReturned;
       PREVENT_MEDIA_REMOVAL PMRBuffer;

       PMRBuffer.PreventMediaRemoval = fPreventRemoval;

       return DeviceIoControl( hVolume,
                               IOCTL_STORAGE_MEDIA_REMOVAL,
                               &PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
                               NULL, 0,
                               &dwBytesReturned,
                               NULL);
   }

   AutoEjectVolume(HANDLE hVolume)
   {
       DWORD dwBytesReturned;

       return DeviceIoControl( hVolume,
                               IOCTL_STORAGE_EJECT_MEDIA,
                               NULL, 0,
                               NULL, 0,
                               &dwBytesReturned,
                               NULL);
   }

   BOOL EjectVolume(TCHAR cDriveLetter)
   {
       HANDLE hVolume;

       BOOL fRemoveSafely = FALSE;
       BOOL fAutoEject = FALSE;

       // Open the volume.
       hVolume = OpenVolume(cDriveLetter);
       if (hVolume == INVALID_HANDLE_VALUE)
           return FALSE;

       // Lock and dismount the volume.
       if (LockVolume(hVolume) && DismountVolume(hVolume)) {
           fRemoveSafely = TRUE;

           // Set prevent removal to false and eject the volume.
           if (PreventRemovalOfVolume(hVolume, FALSE) &&
               AutoEjectVolume(hVolume))
               fAutoEject = TRUE;
       }

       // Close the volume so other processes can use the drive.
       if (!CloseVolume(hVolume))
           return FALSE;

       if (fAutoEject)
           printf("Media in Drive %c has been ejected safely.\n",
                  cDriveLetter);
       else {
           if (fRemoveSafely)
               printf("Media in Drive %c can be safely removed.\n",
               cDriveLetter);
       }

       return TRUE;
   }

   void Usage()
   {
       printf("Usage: Eject <drive letter>\n\n");
       return ;
   }

   void main(int argc, char * argv[])
   {
       if (argc != 2) {
           Usage();
           return ;
       }

       if (!EjectVolume(argv[1][0]))
           printf("Failure ejecting drive %c.\n", argv[1][0]);

       return ;
   }

#10


seaquester:
    非常感谢你提供的代码!
    但是我按照你提供的方法试了一下,发现还是跟原来的结果差不多,即使EjectVolume函数中的fAutoEject为TRUE,最后执行完以后盘符依然存在,而且仍然可以打开里面的文件,还是不能得到如系统"安全删除硬件"的效果(盘符消失).
    如果你不介意,我还想向你继续请教.IOCTL_STORAGE_EJECT_MEDIA与FSCTL_DISMOUNT_VOLUME有什么区别?上面所说的现象应如何解释?

#11


安全删除U盘代码:
ftp://ftp.heise.de/pub/ct/listings/0316-208.zip  

比如E盘是U盘,要删除它,可以这样:
Deveject.exe -EjectDrive:E:

具体怎么作看代码。

#1


如果control code为FSCTL_IS_VOLUME_MOUNTED,那么返回结果以及错误代码和上面的一样,按msdn的说法:If the operation succeeds, DeviceIoControl returns a nonzero value.If the operation fails, DeviceIoControl returns zero.也就是说不成功,那么应该如何将一个已经mount的volume dismount?

#2


不好意思,刚才的回复里应该是"如果control code为FSCTL_DISMOUNT_VOLUME".
另外,我试了一下,如果CreateFile时第二个参数为GENERIC_READ或者GENERIC_WRITE时,对U盘执行dismount操作,那么得到的bResult为1,LastError为0,这样的结果好象是对的.而且我在执行时正在往U盘里面写文件,一执行,系统就提示说copy过程被中断,说明的确是已经强行dismount了.但是执行了以后U盘的灯怎么还是亮着?如果这样是对的,那么为什么要加GENERIC_READ或者GENERIC_WRITE?

#3


我觉得msdn关于用DeviceIoControl发送FSCTL_IS_VOLUME_MOUNTED的返回值说明有错,发送其他的FSCTL_XX_XXX请求返回值一律是成功为非0而不成功为0,独独这个FSCTL_IS_VOLUME_MOUNTED的说明相反.事实上,我调试的结果也支持我的看法.
    还有个问题令我很困惑:用DeviceIoControl发送FSCTL_IS_VOLUME_MOUNTED请求之前,必须先调用CreateFile得到对应volume的handle,那岂不是说每次检查volume是否被mount一定会显示已经mount(因为如果原来没mount,调用了CreateFile之后,windows的I/O Manager也会mount)?

#4


确实应该是成功返回非0值,大概是MSDN的版本问题,你到MSDN的网站在查一下就知道成功时返回非0值。

你在调用 CreateFile 时指定了OPEN_EXISTING 就不会自动mount了,如果volume不存在的话,直接返回一个无效的句柄。

#5


看了你的回复,这个问题我知道了.谢谢回答.
但是前面还有个问题:CreateFile时为什么要加GENERIC_READ或者GENERIC_WRITE才能正常调用?请指教,分数一定会给.

#6


seaquester: 

  我觉得你说的"调用 CreateFile 时指定了OPEN_EXISTING 就不会自动mount"好象有问题,我试了一下,我发送dismount请求后立即发送FSCTL_IS_VOLUME_MOUNTED请求,结果返回是0,error code是21(The device is not ready),这是对的,说明已经成功dismount了.
    但是我结束本次debug,然后再次开始debug(此时应该没有volume,因为我在两次调试之间没有对U盘进行任何操作),调用 CreateFile (指定了OPEN_EXISTING)的结果是得到了有效handle,而且接着发送FSCTL_IS_VOLUME_MOUNTED请求返回1,说明已经mount.这怎么解释呢? 

#7


下面是我的代码,在Win2000下面试过了,没有问题。



#include <windows.h>
#include <stdio.h>


//----------------------------------------------------------------------
//
// PrintWin32Error
//
// Takes the win32 error code and prints the text version.
//
//----------------------------------------------------------------------
void PrintWin32Error( PCHAR Message, DWORD ErrorCode )
{
   LPVOID lpMsgBuf;

   FormatMessage(
      FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
      NULL,
      ErrorCode,
      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
      (PCHAR) &lpMsgBuf,
      0,
      NULL
      );
   fprintf(stderr, "%s: %s\n", Message, lpMsgBuf );
   LocalFree( lpMsgBuf );
}


void main()
{
   HANDLE   hDevice;
   BOOL     bResult;
   DWORD    dwBytesReturned;
   DWORD    dwError;
   char     s[64];


   //
   // Getting a handle to a volume.
   //
   LPCTSTR szDiskName = "\\\\.\\F:";
   hDevice = CreateFile(
      szDiskName,
      GENERIC_READ,
      FILE_SHARE_READ | FILE_SHARE_WRITE,
      NULL,
      OPEN_EXISTING,
      0,
      NULL
      );
   if ((hDevice == NULL) || (hDevice == INVALID_HANDLE_VALUE))
   {
      sprintf(s, "The volume %s is not mounted!", szDiskName);
      PrintWin32Error(s, GetLastError());
      return;
   }

   // Check if The volume is mounted or not.
   bResult = DeviceIoControl(
      hDevice,
      FSCTL_IS_VOLUME_MOUNTED,
      NULL,
      0,
      NULL,
      0,
      &dwBytesReturned,
      NULL
      );
   dwError = GetLastError();
   if (bResult)
   {
      printf("The volume %s is mounted!\n", szDiskName);
   }
   else
   {
      sprintf(s, "The volume %s is not mounted!", szDiskName);
      PrintWin32Error(s, GetLastError());
   }

   CloseHandle(hDevice);
}

#8


我明白你的意思,你是说如果没有插入U盘,或者使用系统提供的"安全删除硬件"程序,则volume肯定是不存在的,CreateFile肯定是返回无效handle,这样的情况下肯定不可能自动mount.
    但是我还有个问题,还想麻烦大侠指点一下,我自己在程序里面dismount的结果是U盘的灯还是亮的,而且还是可以在"我的电脑"中看到盘符;而使用系统提供的"安全删除硬件"程序的结果是灯不亮而且盘符已经消失了.这两种方法的区别在哪里?(我想,这应该就是我dismount以后再CreateFile时又自动mount的原因,可能volume并没有真正被删除?)
    真想把这个问题搞懂,觉得分数不够可以另开贴给你加.谢谢!

#9


只的dismount达不到安全删除的效果,MSDN里面提供了一种实现方案(我没试过,你自己试一下):

Knowledge Base  

HOWTO: Ejecting Removable Media in Windows NT/Windows 2000/Windows XPPSS ID Number:Q165721
Article Last Modified on 01-20-2002
--------------------------------------------------------------------------------
The information in this article applies to: 
Microsoft Win32 Application Programming Interface (API)
the operating system: Microsoft Windows NT 3.5, 3.51, 4.0 
the operating system: Microsoft Windows 2000 
the operating system: Microsoft Windows XP

--------------------------------------------------------------------------------

   #include <windows.h>
   #include <winioctl.h>
   #include <tchar.h>
   #include <stdio.h>

   // Prototypes
   BOOL EjectVolume(TCHAR cDriveLetter);
   HANDLE OpenVolume(TCHAR cDriveLetter);
   BOOL LockVolume(HANDLE hVolume);
   BOOL DismountVolume(HANDLE hVolume);
   BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent);
   BOOL AutoEjectVolume(HANDLE hVolume);
   BOOL CloseVolume(HANDLE hVolume);

   LPTSTR szVolumeFormat = TEXT("\\\\.\\%c:");
   LPTSTR szRootFormat = TEXT("%c:\\");
   LPTSTR szErrorFormat = TEXT("Error %d: %s\n");

   void ReportError(LPTSTR szMsg)
   {
       _tprintf(szErrorFormat, GetLastError(), szMsg);
   }

   HANDLE OpenVolume(TCHAR cDriveLetter)
   {
       HANDLE hVolume;
       UINT uDriveType;
       TCHAR szVolumeName[8];
       TCHAR szRootName[5];
       DWORD dwAccessFlags;

       wsprintf(szRootName, szRootFormat, cDriveLetter);

       uDriveType = GetDriveType(szRootName);
       switch(uDriveType) {
       case DRIVE_REMOVABLE:
           dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
           break;
       case DRIVE_CDROM:
           dwAccessFlags = GENERIC_READ;
           break;
       default:
           _tprintf(TEXT("Cannot eject.  Drive type is incorrect.\n"));
           return INVALID_HANDLE_VALUE;
       }

       wsprintf(szVolumeName, szVolumeFormat, cDriveLetter);

       hVolume = CreateFile(   szVolumeName,
                               dwAccessFlags,
                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                               NULL,
                               OPEN_EXISTING,
                               0,
                               NULL );
       if (hVolume == INVALID_HANDLE_VALUE)
           ReportError(TEXT("CreateFile"));

       return hVolume;
   }

   BOOL CloseVolume(HANDLE hVolume)
   {
       return CloseHandle(hVolume);
   }

   #define LOCK_TIMEOUT        10000       // 10 Seconds
   #define LOCK_RETRIES        20

   BOOL LockVolume(HANDLE hVolume)
   {
       DWORD dwBytesReturned;
       DWORD dwSleepAmount;
       int nTryCount;

       dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;

       // Do this in a loop until a timeout period has expired
       for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
           if (DeviceIoControl(hVolume,
                               FSCTL_LOCK_VOLUME,
                               NULL, 0,
                               NULL, 0,
                               &dwBytesReturned,
                               NULL))
               return TRUE;

           Sleep(dwSleepAmount);
       }

       return FALSE;
   }

   BOOL DismountVolume(HANDLE hVolume)
   {
       DWORD dwBytesReturned;

       return DeviceIoControl( hVolume,
                               FSCTL_DISMOUNT_VOLUME,
                               NULL, 0,
                               NULL, 0,
                               &dwBytesReturned,
                               NULL);
   }

   BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
   {
       DWORD dwBytesReturned;
       PREVENT_MEDIA_REMOVAL PMRBuffer;

       PMRBuffer.PreventMediaRemoval = fPreventRemoval;

       return DeviceIoControl( hVolume,
                               IOCTL_STORAGE_MEDIA_REMOVAL,
                               &PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
                               NULL, 0,
                               &dwBytesReturned,
                               NULL);
   }

   AutoEjectVolume(HANDLE hVolume)
   {
       DWORD dwBytesReturned;

       return DeviceIoControl( hVolume,
                               IOCTL_STORAGE_EJECT_MEDIA,
                               NULL, 0,
                               NULL, 0,
                               &dwBytesReturned,
                               NULL);
   }

   BOOL EjectVolume(TCHAR cDriveLetter)
   {
       HANDLE hVolume;

       BOOL fRemoveSafely = FALSE;
       BOOL fAutoEject = FALSE;

       // Open the volume.
       hVolume = OpenVolume(cDriveLetter);
       if (hVolume == INVALID_HANDLE_VALUE)
           return FALSE;

       // Lock and dismount the volume.
       if (LockVolume(hVolume) && DismountVolume(hVolume)) {
           fRemoveSafely = TRUE;

           // Set prevent removal to false and eject the volume.
           if (PreventRemovalOfVolume(hVolume, FALSE) &&
               AutoEjectVolume(hVolume))
               fAutoEject = TRUE;
       }

       // Close the volume so other processes can use the drive.
       if (!CloseVolume(hVolume))
           return FALSE;

       if (fAutoEject)
           printf("Media in Drive %c has been ejected safely.\n",
                  cDriveLetter);
       else {
           if (fRemoveSafely)
               printf("Media in Drive %c can be safely removed.\n",
               cDriveLetter);
       }

       return TRUE;
   }

   void Usage()
   {
       printf("Usage: Eject <drive letter>\n\n");
       return ;
   }

   void main(int argc, char * argv[])
   {
       if (argc != 2) {
           Usage();
           return ;
       }

       if (!EjectVolume(argv[1][0]))
           printf("Failure ejecting drive %c.\n", argv[1][0]);

       return ;
   }

#10


seaquester:
    非常感谢你提供的代码!
    但是我按照你提供的方法试了一下,发现还是跟原来的结果差不多,即使EjectVolume函数中的fAutoEject为TRUE,最后执行完以后盘符依然存在,而且仍然可以打开里面的文件,还是不能得到如系统"安全删除硬件"的效果(盘符消失).
    如果你不介意,我还想向你继续请教.IOCTL_STORAGE_EJECT_MEDIA与FSCTL_DISMOUNT_VOLUME有什么区别?上面所说的现象应如何解释?

#11


安全删除U盘代码:
ftp://ftp.heise.de/pub/ct/listings/0316-208.zip  

比如E盘是U盘,要删除它,可以这样:
Deveject.exe -EjectDrive:E:

具体怎么作看代码。