Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi USB Stick sicher entfernen unter Vista (https://www.delphipraxis.net/120716-usb-stick-sicher-entfernen-unter-vista.html)

TurboMartin 5. Nov 2009 14:49

Re: USB Stick sicher entfernen unter Vista
 
Probier mal Folgendes:

Delphi-Quellcode:
function OpenVolume(ADrive: char): THandle;
var
  RootName, VolumeName: string;
  AccessFlags: DWORD;
  DriveType:Cardinal;
begin
  RootName := ADrive + ':\';
  DriveType := GetDriveType(PChar(RootName));
  case DriveType of
    DRIVE_REMOVABLE:
      AccessFlags := GENERIC_READ or GENERIC_WRITE;
    DRIVE_CDROM:
      AccessFlags := GENERIC_READ;
//    DRIVE_FIXED:
//      AccessFlags := GENERIC_READ or GENERIC_WRITE;
  else
    Result := INVALID_HANDLE_VALUE;
    exit;
  end;
  VolumeName := Format('\\.\%s:', [ADrive]);
  Result := CreateFile(PChar(VolumeName), AccessFlags,
    FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
  if Result = INVALID_HANDLE_VALUE then
    RaiseLastWin32Error;
end;
 
function LockVolume(AVolumeHandle: THandle): boolean;
const
  LOCK_TIMEOUT = 10 * 1000; // 10 Seconds
  LOCK_RETRIES = 20;
  LOCK_SLEEP = LOCK_TIMEOUT div LOCK_RETRIES;
  FSCTL_LOCK_VOLUME = (9 shl 16) or (0 shl 14) or (6 shl 2) or 0;
var
  Retries: integer;
  BytesReturned: Cardinal;
begin
  for Retries := 1 to LOCK_RETRIES do begin
    Result := DeviceIoControl(AVolumeHandle, FSCTL_LOCK_VOLUME, nil, 0,
      nil, 0, BytesReturned, nil);
    if Result then
      break;
    Sleep(LOCK_SLEEP);
  end;
end;
 
function DismountVolume(AVolumeHandle: THandle): boolean;
const
  FSCTL_DISMOUNT_VOLUME = (9 shl 16) or (0 shl 14) or (8 shl 2) or 0;
var
  BytesReturned: Cardinal;
begin
  Result := DeviceIoControl(AVolumeHandle, FSCTL_DISMOUNT_VOLUME, nil, 0,
    nil, 0, BytesReturned, nil);
  if not Result then
    RaiseLastWin32Error;
end;
 
function PreventRemovalOfVolume(AVolumeHandle: THandle;
  APreventRemoval: boolean): boolean;
const
  IOCTL_STORAGE_MEDIA_REMOVAL = ($2d shl 16) or (1 shl 14) or ($201 shl 2) or 0;
type
  TPreventMediaRemoval = record
    PreventMediaRemoval: BOOL;
  end;
var
  BytesReturned: Cardinal;
  PMRBuffer: TPreventMediaRemoval;
begin
  PMRBuffer.PreventMediaRemoval := APreventRemoval;
  Result := DeviceIoControl(AVolumeHandle, IOCTL_STORAGE_MEDIA_REMOVAL,
    @PMRBuffer, SizeOf(TPreventMediaRemoval), nil, 0, BytesReturned, nil);
  if not Result then
    RaiseLastWin32Error;
end;
 
function AutoEjectVolume(AVolumeHandle: THandle): boolean;
const
  IOCTL_STORAGE_EJECT_MEDIA = ($2d shl 16) or (1 shl 14) or ($202 shl 2) or 0;
var
  BytesReturned: Cardinal;
begin
  Result := DeviceIoControl(AVolumeHandle, IOCTL_STORAGE_EJECT_MEDIA, nil, 0,
    nil, 0, BytesReturned, nil);
  if not Result then
    RaiseLastWin32Error;
end;
 
function EjectVolume(ADrive: char): boolean;
var
  VolumeHandle: THandle;
begin
  Result := FALSE;
  // Open the volume
  VolumeHandle := OpenVolume(ADrive);
  if VolumeHandle = INVALID_HANDLE_VALUE then
    exit;
  try
    // Lock and dismount the volume
    if LockVolume(VolumeHandle) and DismountVolume(VolumeHandle) then begin
      // Set prevent removal to false and eject the volume
      if PreventRemovalOfVolume(VolumeHandle, FALSE) then
        AutoEjectVolume(VolumeHandle);
    end;
  finally
    // Close the volume so other processes can use the dr
     CloseHandle(VolumeHandle);
  end;
end;
Aufruf mit z.B. EjectVolume('J');

worker.db 6. Nov 2009 11:59

Re: USB Stick sicher entfernen unter Vista
 
Vielen Dank für Ihre Antworten.

worker.db 6. Nov 2009 13:53

Re: USB Stick sicher entfernen unter Vista
 
Wie bekomme ich 'angeschlossenen USB-Info "(Geräte-Instanz-ID, Fahrerairbag, Schlüsselnamen ..) aus der Registry in Vista oder Windows 7 mit Delphi?
Wo ist diese Information in Windows Registry?
Ich habe einen Code es funktioniert unter XP, aber nicht in Vista.
Warum wird der Code funktioniert nicht auf Vista?
Ich bin Stack wirklich darüber. Bitte helfen Sie.

Alter Mann 6. Nov 2009 14:33

Re: USB Stick sicher entfernen unter Vista
 
Hallo TurboMartin,

unter Win 7 und als Admin geht es, unter Vista nicht.

Keine Meldung, nix.

Gruß

Pichel 6. Nov 2009 20:33

Re: USB Stick sicher entfernen unter Vista
 
Zitat:

Zitat von TurboMartin
Probier mal Folgendes:
Delphi-Quellcode:
function DismountVolume(AVolumeHandle: THandle): boolean;
const
  FSCTL_DISMOUNT_VOLUME = (9 shl 16) or (0 shl 14) or (8 shl 2) or 0;
var
  BytesReturned: Cardinal;
begin
  Result := DeviceIoControl(AVolumeHandle, FSCTL_DISMOUNT_VOLUME, nil, 0,
    nil, 0, BytesReturned, nil);

Habs jetzt mal getestet und es kracht genau bei obigem Aufruf in der "kernel32".

worker.db 8. Nov 2009 16:51

Re: USB Stick sicher entfernen unter Vista
 
Für Vista und Win7:
GetDriveInstanceID () except alles korrekt funktioniert.
So GetDriveInstanceID(DriveMountPoints[I], Inst) returned from 'Inst' ist falsch.

Ergebnisse für den gleichen USB:

----------------XP-----------Win7
-----------------------------------
Inst--------2788----------3908
Key---------1924-----------0

Was hat sich in Vista Registry geändert?

Uwe Sieber 8. Nov 2009 23:00

Re: USB Stick sicher entfernen unter Vista
 
Zitat:

Zitat von worker.db
Für Vista und Win7:
GetDriveInstanceID () except alles korrekt funktioniert.
So GetDriveInstanceID(DriveMountPoints[I], Inst) returned from 'Inst' ist falsch.

Ergebnisse für den gleichen USB:

----------------XP-----------Win7
-----------------------------------
Inst--------2788----------3908
Key---------1924-----------0

Was hat sich in Vista Registry geändert?


Nochmal: Die Funktion setzt eine Parent/Child-Beziehung zwischen Volume und Disk voraus.
Das war schon unter XP nur für Wechseldatenträger und CDROMs ok, aber nicht für Festplatten.
Ab Vista ist das nur noch für CDROMs und USB-Floppys der Fall, sonst ist der Volume-Manager im Spiel.

Hier habe ich in C++ gezeigt, wie es geht:
http://www.codeproject.com/KB/system...eByLetter.aspx


Gruß Uwe

Bomberbb 13. Nov 2009 12:30

Re: USB Stick sicher entfernen unter Vista
 
Ich hänge mich hier mal an mit meinem Problem:

Ich nutze folgenden Quelltext:
Delphi-Quellcode:
Function EjectVolume(ADrive: char): Boolean;

    Function OpenVolume(ADrive: char): THandle;
    Var
      RootName, VolumeName        : String;
      AccessFlags                 : DWORD;
      DriveType                   : Cardinal;
    Begin
      RootName := ADrive + ':\';
      DriveType := GetDriveType(pChar(RootName));
      Case DriveType Of
        DRIVE_REMOVABLE:
          AccessFlags := GENERIC_READ Or GENERIC_WRITE;
        DRIVE_CDROM:
          AccessFlags := GENERIC_READ;
        //    DRIVE_FIXED:
        //      AccessFlags := GENERIC_READ or GENERIC_WRITE;
      Else
        Result := INVALID_HANDLE_VALUE;
        Exit;
      End;
      VolumeName := Format('\\.\%s:', [ADrive]);
      Result := CreateFile(pChar(VolumeName), AccessFlags,
        FILE_SHARE_READ Or FILE_SHARE_WRITE, Nil, OPEN_EXISTING, 0, 0);
      If Result = INVALID_HANDLE_VALUE Then
        RaiseLastWin32Error;
    End;

    Function LockVolume(AVolumeHandle: THandle): Boolean;
    Const
      LOCK_TIMEOUT                = 10 * 1000; // 10 Seconds
      LOCK_RETRIES                = 20;
      LOCK_SLEEP                  = LOCK_TIMEOUT Div LOCK_RETRIES;
      FSCTL_LOCK_VOLUME           = (9 Shl 16) Or (0 Shl 14) Or (6 Shl 2) Or 0;
    Var
      Retries                     : Integer;
      BytesReturned               : Cardinal;
    Begin
      For Retries := 1 To LOCK_RETRIES Do
      Begin
        Result := DeviceIoControl(AVolumeHandle, FSCTL_LOCK_VOLUME, Nil, 0,
          Nil, 0, BytesReturned, Nil);
        If Result Then
          Break;
        Sleep(LOCK_SLEEP);
      End;
    End;

    Function DismountVolume(AVolumeHandle: THandle): Boolean;
    Const
      FSCTL_DISMOUNT_VOLUME       = (9 Shl 16) Or (0 Shl 14) Or (8 Shl 2) Or 0;
    Var
      BytesReturned               : Cardinal;
    Begin
      Result := DeviceIoControl(AVolumeHandle, FSCTL_DISMOUNT_VOLUME, Nil, 0,
        Nil, 0, BytesReturned, Nil);
      If Not Result Then
        RaiseLastWin32Error;
    End;

    Function PreventRemovalOfVolume(AVolumeHandle: THandle;
      APreventRemoval: Boolean): Boolean;
    Const
      IOCTL_STORAGE_MEDIA_REMOVAL = ($2D Shl 16) Or (1 Shl 14) Or ($201 Shl 2) Or 0;
    Type
      TPreventMediaRemoval = Record
        PreventMediaRemoval: BOOL;
      End;
    Var
      BytesReturned               : Cardinal;
      PMRBuffer                   : TPreventMediaRemoval;
    Begin
      PMRBuffer.PreventMediaRemoval := APreventRemoval;
      Result := DeviceIoControl(AVolumeHandle, IOCTL_STORAGE_MEDIA_REMOVAL,
        @PMRBuffer, SizeOf(TPreventMediaRemoval), Nil, 0, BytesReturned, Nil);
      If Not Result Then
        RaiseLastWin32Error;
    End;

    Function AutoEjectVolume(AVolumeHandle: THandle): Boolean;
    Const
      IOCTL_STORAGE_EJECT_MEDIA   = ($2D Shl 16) Or (1 Shl 14) Or ($202 Shl 2) Or 0;
    Var
      BytesReturned               : Cardinal;
    Begin
      Result := DeviceIoControl(AVolumeHandle, IOCTL_STORAGE_EJECT_MEDIA, Nil, 0,
        Nil, 0, BytesReturned, Nil);
      If Not Result Then
        RaiseLastWin32Error;
    End;

  Var
    VolumeHandle                  : THandle;
    str                           : String;
  Begin
    Result := False;

    // Open the volume
    VolumeHandle := OpenVolume(ADrive);
    If VolumeHandle = INVALID_HANDLE_VALUE Then
      Exit;
    Try
      // Lock and dismount the volume
      If LockVolume(VolumeHandle) And DismountVolume(VolumeHandle) Then
      Begin
        // Set prevent removal to false and eject the volume
        If PreventRemovalOfVolume(VolumeHandle, False) Then
          Result := AutoEjectVolume(VolumeHandle);
      End;
    Finally
      // Close the volume so other processes can use the dr
      CloseHandle(VolumeHandle);
    End;
    If Result Then
    Begin
      str := ADrive + '\';
      ShChangeNotify(
        SHCNE_MEDIAREMOVED,
        SHCNF_PATH,
        pChar(str),
        Nil);
    End;
  End;
Der USB-Stick wird ausgehängt, aber irgendwie scheint ShChangeNotify zu scheitern. Das Symbol in der Taskleiste bleibt erhalten, ebendso wird im Explorer noch das Laufwerk angezeigt. Wie sag ich Windows nun, dass ich den Stick ausgehängt habe?

Gruß

Sascha

Uwe Sieber 13. Nov 2009 12:47

Re: USB Stick sicher entfernen unter Vista
 
Zitat:

Zitat von Bomberbb
Der USB-Stick wird ausgehängt, aber irgendwie scheint ShChangeNotify zu scheitern. Das Symbol in der Taskleiste bleibt erhalten, ebendso wird im Explorer noch das Laufwerk angezeigt. Wie sag ich Windows nun, dass ich den Stick ausgehängt habe?

IOCTL_STORAGE_EJECT_MEDIA meldet nicht das Laufwerk ab, es wirft das Medium aus - daher der Name.
Bei einem CD-Laufwerk ginge Schublade auf, mehr nicht. Bei einem Kartenleser könnte man die
Karte entnehmen und wieder einlegen -> geht wieder. Einem USB-Stick kann man nach dem Auswerfen
beruhigt abziehen, Wiederbeleben geht nur durch erneutes Anschließen.


Gruß Uwe

p80286 13. Nov 2009 15:31

Re: USB Stick sicher entfernen unter Vista
 
Zitat:

Zitat von Uwe Sieber

IOCTL_STORAGE_EJECT_MEDIA meldet nicht das Laufwerk ab, es wirft das Medium aus - daher der Name.
Bei einem CD-Laufwerk ginge Schublade auf, mehr nicht. Bei einem Kartenleser könnte man die
Karte entnehmen und wieder einlegen -> geht wieder. Einem USB-Stick kann man nach dem Auswerfen
beruhigt abziehen, Wiederbeleben geht nur durch erneutes Anschließen.

Was ist mit "Anschließen" gemeint?

Ein IOCTL_STORAGE_LOAD_MEDIA nach IOCTL_STORAGE_EJECT_MEDIA scheint Windows (Unter Vista auf jeden Fall! unter XP geht's nicht!) ein erneutes Einstecken des Sticks vorzugaukeln. Ob das Entfernen "sicher" ist kann ich nicht beurteilen.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:16 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz