IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

API, COM et SDKs Delphi Discussion :

[USB] Ejection d'un disque [FAQ]


Sujet :

API, COM et SDKs Delphi

  1. #1
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut [USB] Ejection d'un disque
    Avant de réinventer la roue, et apres avoir chercher dans FAQ et FORUMS
    quelqu'un a t'il réussi de façon fiable (WINDOWS version Diverses) à éjecter un disque USB sans qu'il y-ait opération d'un utilisateur ?

    Shell Command s'abstenir

    Merci pour toute piste , avant de m'y atteler sérieusement

    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  2. #2
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 74
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut
    Salut

    Je n'ai pas de lecteur USB, mais pour un lecteur interne, ce qui suit fonctionne.

    Pour ouvrir le lecteur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mciSendString('Set cdaudio door open wait', nil, 0, handle);
    Pour fermer le lecteur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mciSendString('Set cdaudio door closed wait', nil, 0, handle);
    NB : Ne pas oublier d'ajouter MMSystem dans la clause Use

  3. #3
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut suite de mes cogitations
    j'ai décidé de m'y attelé

    pour éjecter un CD pas de problème par contre pour un disque USB

    en cherchant à droite et à gauche forums VB,C etc ... tous les codes que je trouve font en gros la même chose , et ceux que j'ai transposé aussi
    le lecteur USB est peut-être déconnecté mais WIN XP (ma machine de test)
    le connait toujours si je clique sur l'icone de retrait du périhérique donc

    toutefois pour faire bonne mesure voici une partie de mon code
    constantes trouvé dans l'excellente Win32 API de JEDI
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
     
    TYPE
      PPREVENT_MEDIA_REMOVAL = ^PREVENT_MEDIA_REMOVAL;
      PREVENT_MEDIA_REMOVAL = RECORD
        PreventMediaRemoval: WordBool;
      END;
     
    CONST
    FILE_DEVICE_FILE_SYSTEM = $00000009;
    FILE_ANY_ACCESS = 0;
    FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS;
    FILE_READ_ACCESS    = $0001;           // file & pipe
    FILE_WRITE_ACCESS   = $0002;           // file & pipe
     
    METHOD_BUFFERED = 0;
     
    FILE_DEVICE_DISK                = $00000007;
    FILE_DEVICE_MASS_STORAGE        = $0000002d;
     
    IOCTL_STORAGE_BASE = FILE_DEVICE_MASS_STORAGE;
    FSCTL_LOCK_VOLUME = ((FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (6 shl 2) or METHOD_BUFFERED);
    FSCTL_UNLOCK_VOLUME =((FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (7 shl 2) or METHOD_BUFFERED);
    FSCTL_DISMOUNT_VOLUME =((FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (8 shl 2) or METHOD_BUFFERED);
    IOCTL_STORAGE_MEDIA_REMOVAL = ((IOCTL_STORAGE_BASE shl 16) or (FILE_READ_ACCESS shl 14) or ($0201 shl 2) or METHOD_BUFFERED);
    IOCTL_STORAGE_EJECT_MEDIA = ((IOCTL_STORAGE_BASE shl 16) or (FILE_READ_ACCESS shl 14) or ($0202 shl 2) or METHOD_BUFFERED);
    IOCTL_DISK_BASE = FILE_DEVICE_DISK;
    IOCTL_DISK_EJECT_MEDIA = (
        (IOCTL_DISK_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
        ($0202 shl 2) or METHOD_BUFFERED);
    IOCTL_DISK_MEDIA_REMOVAL = (
        (IOCTL_DISK_BASE shl 16) or (FILE_READ_ACCESS shl 14) or
        ($0201 shl 2) or METHOD_BUFFERED);
    Partie de Code Test (Lecteur = 'G:');
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    R:=GetDriveType(lecteur);
    Case R of
      DRIVE_UNKNOWN : ShowMessage('Inconnu');
      DRIVE_NO_ROOT_DIR : ShowMessage('Inconnu');
      DRIVE_REMOVABLE :begin
     
                        {C'est ici que ça se passe}
     
                       H:=CreateFile('\\.\'+Lecteur,GENERIC_READ,FILE_SHARE_READ OR FILE_SHARE_WRITE,
                                      nil,OPEN_EXISTING,0,0);
                       if H= INVALID_HANDLE_VALUE then ShowMessage('Erreur Handle')
                       else begin
                          DeviceIoControl(H,FSCTL_LOCK_VOLUME,nil,0,nil,0,cb,nil);
    DeviceIoControl(H,FSCTL_DISMOUNT_VOLUME,nil,0,nil,0,cb,nil);
    MRBuffer.PreventMediaRemoval := False; //<- a ne pas oublier :oops: 
    PMRBuffer:=@MRBuffer;                   
    DeviceIoControl(H,IOCTL_DISK_MEDIA_REMOVAL,nil,0,nil,0,cb,nil);
     
                          DeviceIoControl(H,IOCTL_DISK_EJECT_MEDIA , nil, 0,nil,0, cb, nil);
                          CloseHandle(H);
                       end;
                       end;
      DRIVE_FIXED : ShowMessage('Fixe');
      DRIVE_REMOTE : ShowMessage('Réseau');
      DRIVE_CDROM : begin
                       H:=CreateFile('\\.\'+Lecteur,GENERIC_READ,FILE_SHARE_READ OR FILE_SHARE_WRITE,
                                      nil,OPEN_EXISTING,0,0);
                       if H= INVALID_HANDLE_VALUE then ShowMessage('Erreur Handle')
                       else begin
                          DeviceIoControl(H,FSCTL_LOCK_VOLUME,nil,0,nil,0,cb,nil);
                          DeviceIoControl(H,FSCTL_DISMOUNT_VOLUME,nil,0,nil,0,cb,nil);
                          DeviceIoControl(H,IOCTL_STORAGE_EJECT_MEDIA , nil, 0,nil,0, cb, nil);
                          CloseHandle(H);
                       end;
                    end;
      DRIVE_RAMDISK : ShowMessage('RAM');
    else showmessage('Erreur : ');
    end;

    si quelqu'un à une idée je suis preneur
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  4. #4
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut je savais bien qu'il ne fallait pas réinventer la roue
    Eureka !! j'étais parti sur une 'mauvaise piste'

    en fouillant bien dans "l'excellente Win32 API de JEDI" (je me répete ? )
    tout y était . En fait c'est dans la partie Setup&ConfigManager qu'il fallait chercher.

    je ne sais pas si j'aurais le temps de faire un tri dans tout ça pour faire un code
    suffisamment concis et ne nécessitant pas tous les sources de JEDI

    toutefois si d'autres personnes veulent obtenir le résultat je me ferais un plaisir
    de laisser le code de mon test

    et bon devpt
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  5. #5
    Rédacteur
    Avatar de evarisnea
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Juin 2005
    Messages
    1 957
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : Transports

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 957
    Points : 4 384
    Points
    4 384
    Par défaut


    Citation Envoyé par SergioMaster
    toutefois si d'autres personnes veulent obtenir le résultat je me ferais un plaisir
    de laisser le code de mon test
    moi je suis preneur
    et si en plus tu écrivais un joli tuto là dessus ce serait nickel !

  6. #6
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par evarisnea
    si en plus tu écrivais un joli tuto là dessus ce serait nickel !
    Ouais, bon je suis pas très écrivain pour l'instant .

    le code est certainement à toiletter !!! et là pour l'instant je n'ai pas vraiment le temps . Il vient de me tomber 3 demandes sérieuses et urgentes (pour hier)

    voilà pour l'instant mes cogitations tests (clé en 'H:')


    la form ne contient qu' un bouton

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    unit EjectUSBOk;
     
    interface
     
    uses Windows, Classes, Graphics, Forms, Controls, StdCtrls;
     
    type
      TMainForm = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      MainForm: TMainForm;
     
    implementation
     
    uses   Cfg, CfgMgr32, SetupApi, JwaWinBase;
     
    {$R *.dfm}
     
    procedure TMainForm.Button1Click(Sender: TObject);
    var
      VetoType: PNP_VETO_TYPE;
      DriveName,DriveInstance : String;
      inst : DEVINST;
      function GetVolumeNameForVolumeMountPointString(Name: string): string;
      var
        Volume: array [0..MAX_PATH] of Char;
      begin
        FillChar(Volume[0], SizeOf(Volume), 0);
        GetVolumeNameForVolumeMountPoint(PChar(Name), @Volume[0], SizeOf(Volume));
      Result := Volume;
      end;
      function GetDeviceID(Inst: DEVINST): string;
      var
        Buffer: PChar;
        Size: ULONG;
      begin
        CM_Get_Device_ID_Size(Size, Inst, 0);
      // Required! See DDK help for CM_Get_Device_ID
        Inc(Size);
        Buffer := AllocMem(Size * SizeOf(WCHAR));
        CM_Get_Device_ID(Inst, Buffer, Size, 0);
        Result := Buffer;
        FreeMem(Buffer);
      end;
      function GetDriveInstanceID(MountPointName: string; var DeviceInst: DEVINST): Boolean;
      const
        GUID_DEVINTERFACE_VOLUME: TGUID = '{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}';
      var
        StorageGUID: TGUID;
        PnPHandle: HDEVINFO;
        DevData: TSPDevInfoData;
        DeviceInterfaceData: TSPDeviceInterfaceData;
        FunctionClassDeviceData: PSPDeviceInterfaceDetailData;
        Success: LongBool;
        Devn: Integer;
        BytesReturned: DWORD;
        Inst: DEVINST;
        S, FileName, MountName, DevID: string;
      begin
        Result := False;
        DeviceInst := 0;
       // enumerate all volumes
       StorageGUID := GUID_DEVINTERFACE_VOLUME;
       PnPHandle := SetupDiGetClassDevs(@StorageGUID, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
       if PnPHandle = Pointer(INVALID_HANDLE_VALUE) then
         Exit;
       Devn := 0;
       repeat
        DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);
        Success := SetupDiEnumDeviceInterfaces(PnPHandle, nil, StorageGUID, Devn, DeviceInterfaceData);
        if Success then
        begin
          DevData.cbSize := SizeOf(DevData);
          BytesReturned := 0;
          SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, nil, 0, BytesReturned, @DevData);
          if (BytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
          begin
            FunctionClassDeviceData := AllocMem(BytesReturned);
            try
              FunctionClassDeviceData.cbSize := SizeOf(TSPDeviceInterfaceDetailData);
              if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData,
                FunctionClassDeviceData, BytesReturned, BytesReturned, @DevData) then
              begin
                FileName := PChar(@FunctionClassDeviceData.DevicePath[0]);
                // get the grandparent DevNode which is the "bus" device
                // like "USB". This is the DevNode for CM_Request_Device_Eject and
                // several other useful operations
                Inst := DevData.DevInst;
                CM_Get_Parent(Inst, Inst, 0);
                CM_Get_Parent(Inst, Inst, 0);
                DevID := GetDeviceID(Inst);
     
                // no need in this example to check for USB only
                // if ExtractBus(DevID) = 'USB' then
                begin
                  S := '\';
                  S := Pchar(@FunctionClassDeviceData.DevicePath) + S;
                  MountName := GetVolumeNameForVolumeMountPointString(S);
                  if MountName = MountPointName then
                  begin
                    DeviceInst := Inst;
                    Result := True;
                    Exit;
                  end;
                end;
              end;
            finally
              FreeMem(FunctionClassDeviceData);
            end;
          end;
        end;
        Inc(Devn);
        until not Success;
        SetupDiDestroyDeviceInfoList(PnPHandle);
      end;
    begin
    DriveName:='H:\';
    if GetDriveType(Pchar(DriveName)) = DRIVE_REMOVABLE then
     begin
      DriveInstance:=GetVolumeNameForVolumeMountPointString(DriveName);
      GetDriveInstanceID(DriveInstance, Inst);
      VetoType := 0;
      CM_Request_Device_Eject(inst,@VetoType, nil, 0, 0);
     end;
    end;
     
    procedure TMainForm.FormCreate(Sender: TObject);
    begin
    LoadSetupApi;
    LoadConfigManagerApi;
    end;
     
    procedure TMainForm.FormDestroy(Sender: TObject);
    begin
    UnloadConfigManagerApi;
    UnloadSetupApi;
    end;
     
    end.
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3
    Points : 4
    Points
    4
    Par défaut
    Salut, J'ai récupéré ton code, ça marche jusqu'à la procédure :
    GetDriveInstanceID qui me retourne toujours 0 (zero).
    As tu rencontré un problème de ce type?

  8. #8
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Salut,
    on a une entrée de prévue sur le sujet pour la prochaine FAQ, on pourra la compléter avec ton code ou l'utiliser directement.


  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par bob64
    Salut, J'ai récupéré ton code, ça marche jusqu'à la procédure :
    GetDriveInstanceID qui me retourne toujours 0 (zero).
    As tu rencontré un problème de ce type?
    non pas de pbs


    Laurent

    comme je l'ai spécifié y'a certainement un peu de nettoyage à faire, et transferer des morceaux de la JVCL . par contre ça fonctionne nickel chrome

    en fait la seule chose qui me gene c'est ma non compréhension de la constante

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    GUID_DEVINTERFACE_VOLUME: TGUID = '{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}';
    j'en ai fait un petit programme (non documenté cause urgence) si besoin
    je suis prêt à le poster
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  10. #10
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    582
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mai 2003
    Messages : 582
    Points : 915
    Points
    915
    Par défaut
    Citation Envoyé par SergioMaster
    en fait la seule chose qui me gene c'est ma non compréhension de la constante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    GUID_DEVINTERFACE_VOLUME: TGUID = '{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}';
    Il s'agit du nom unique (GUID) de la classe Plug and Play
    pour les interfaces de volume...

    on en parle ici..

    MSDN...(en anglais)
    Comment dupliquer un disque...ça vous intéresse?
    Tutoriel et code source delphi ici

  11. #11
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut
    merci pour le lien .

    la gêne c'est plutôt introduire une constante que savoir à quoi elle correspond.
    Qui nous dit que MS ne vas pas la changer dans son nouveau hyper super absolument indispensable système d'exploitation ? et de plus est-ce portable vers LINUX mon pingouin préféré mais pas utilisé
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  12. #12
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut Code D'une Unite Independante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
     
    //
    //La plupart du code se trouve dans les exemples 
    //  Win32 API de JEDI nécessaire
    //
    //  jedi-apilib.sourceforge.net/ 
    //
     
     
    unit Ejection;
     
    interface
     
    uses Windows, StdCtrls, SysUtils,
         Cfg, CfgMgr32, SetupApi, JwaWinBase;   // viennent de Win32API 
     
    function Ejecter(lecteur : String) : boolean;
     
    implementation
     
     
    function Ejecter(Lecteur : String) : Boolean;
    var
      VetoType: PNP_VETO_TYPE;
      DriveName,DriveInstance : String;
      inst : DEVINST;
     
      function GetVolumeNameForVolumeMountPointString(Name: string): string;
      var
        Volume: array [0..MAX_PATH] of Char;
      begin
        FillChar(Volume[0], SizeOf(Volume), 0);
        GetVolumeNameForVolumeMountPoint(PChar(Name), @Volume[0], SizeOf(Volume));
        Result := Volume;
      end;
     
      function GetDeviceID(Inst: DEVINST): string;
      var
        Buffer: PChar;
        Size: ULONG;
      begin
        CM_Get_Device_ID_Size(Size, Inst, 0);
        Inc(Size);
        Buffer := AllocMem(Size * SizeOf(WCHAR));
        CM_Get_Device_ID(Inst, Buffer, Size, 0);
        Result := Buffer;
        FreeMem(Buffer);
      end;
     
      function GetDriveInstanceID(MountPointName: string; var DeviceInst: DEVINST): Boolean;
      const
        GUID_DEVINTERFACE_VOLUME: TGUID = '{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}';
      var
        StorageGUID: TGUID;
        PnPHandle: HDEVINFO;
        DevData: TSPDevInfoData;
        DeviceInterfaceData: TSPDeviceInterfaceData;
        FunctionClassDeviceData: PSPDeviceInterfaceDetailData;
        Success: LongBool;
        Devn: Integer;
        BytesReturned: DWORD;
        Inst: DEVINST;
        S, FileName, MountName, DevID: string;
      begin
        Result := False;
        DeviceInst := 0;
        StorageGUID := GUID_DEVINTERFACE_VOLUME;
        PnPHandle := SetupDiGetClassDevs(@StorageGUID, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
        if PnPHandle = Pointer(INVALID_HANDLE_VALUE) then
          Exit;
        Devn := 0;
        repeat
        DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);
        Success := SetupDiEnumDeviceInterfaces(PnPHandle, nil, StorageGUID, Devn, DeviceInterfaceData);
        if Success then
        begin
          DevData.cbSize := SizeOf(DevData);
          BytesReturned := 0;
          SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, nil, 0, BytesReturned, @DevData);
          if (BytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
          begin
            FunctionClassDeviceData := AllocMem(BytesReturned);
            try
              FunctionClassDeviceData.cbSize := SizeOf(TSPDeviceInterfaceDetailData);
              if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData,
                FunctionClassDeviceData, BytesReturned, BytesReturned, @DevData) then
              begin
                FileName := PChar(@FunctionClassDeviceData.DevicePath[0]);
                // get the grandparent DevNode which is the "bus" device
                // like "USB". This is the DevNode for CM_Request_Device_Eject and
                // several other useful operations
                Inst := DevData.DevInst;
                CM_Get_Parent(Inst, Inst, 0);
                CM_Get_Parent(Inst, Inst, 0);
                DevID := GetDeviceID(Inst);
     
                // no need in this example to check for USB only
                // if ExtractBus(DevID) = 'USB' then
                begin
                  S := '\';
                  S := Pchar(@FunctionClassDeviceData.DevicePath) + S;
                  MountName := GetVolumeNameForVolumeMountPointString(S);
                  if MountName = MountPointName then
                  begin
                    DeviceInst := Inst;
                    Result := True;
                    Exit;
                  end;
                end;
              end;
            finally
              FreeMem(FunctionClassDeviceData);
            end;
          end;
        end;
        Inc(Devn);
        until not Success;
        SetupDiDestroyDeviceInfoList(PnPHandle);
      end;
     
    begin
    LoadSetupApi;
    LoadConfigManagerApi;
    DriveName:=ExtractFileDrive(Lecteur)+'\';
    if GetDriveType(Pchar(DriveName)) = DRIVE_REMOVABLE then
     begin
      DriveInstance:=GetVolumeNameForVolumeMountPointString(DriveName);
      GetDriveInstanceID(DriveInstance, Inst);
      VetoType := 0;
      CM_Request_Device_Eject(inst,@VetoType, nil, 0, 0);
      result:=true;
     end
    else result:=False;
    UnloadConfigManagerApi;
    UnloadSetupApi;
    end;
     
    end.
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  13. #13
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 964
    Points
    6 964
    Par défaut
    Quand j'essais, il me dit :
    Identificateur non déclaré : PNP_VETO_TYPE
    DEVINST
    CM_Get_Device_ID_Size
    ...
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  14. #14
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut
    PNP_VETO_TYPE est pourtant bien déclaré dans l'unité Cfg

    dont voici le début

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    unit Cfg;
     
    interface
     
    uses
      JwaWinType;
     
    {$WEAKPACKAGEUNIT ON}
     
    {$HPPEMIT '#include "cfg.h"'}
     
    //
    // The following definitions are also used by kernel mode code to
    // set up the registry.
    //
    //
    // VetoType used in
    //      CM_Disable_DevNode
    //      CM_Uninstall_DevNode
    //      CM_Query_And_Remove_SubTree
    //
    const
      PNP_VetoTypeUnknown          = 0;   // Name is unspecified
      {$EXTERNALSYM PNP_VetoTypeUnknown}
      PNP_VetoLegacyDevice         = 1;   // Name is an Instance Path
      {$EXTERNALSYM PNP_VetoLegacyDevice}
      PNP_VetoPendingClose         = 2;   // Name is an Instance Path
      {$EXTERNALSYM PNP_VetoPendingClose}
      PNP_VetoWindowsApp           = 3;   // Name is a Module
      {$EXTERNALSYM PNP_VetoWindowsApp}
      PNP_VetoWindowsService       = 4;   // Name is a Service
      {$EXTERNALSYM PNP_VetoWindowsService}
      PNP_VetoOutstandingOpen      = 5;   // Name is an Instance Path
      {$EXTERNALSYM PNP_VetoOutstandingOpen}
      PNP_VetoDevice               = 6;   // Name is an Instance Path
      {$EXTERNALSYM PNP_VetoDevice}
      PNP_VetoDriver               = 7;   // Name is a Driver Service Name
      {$EXTERNALSYM PNP_VetoDriver}
      PNP_VetoIllegalDeviceRequest = 8;   // Name is an Instance Path
      {$EXTERNALSYM PNP_VetoIllegalDeviceRequest}
      PNP_VetoInsufficientPower    = 9;   // Name is unspecified
      {$EXTERNALSYM PNP_VetoInsufficientPower}
      PNP_VetoNonDisableable       = 10;  // Name is an Instance Path
      {$EXTERNALSYM PNP_VetoNonDisableable}
      PNP_VetoLegacyDriver         = 11;  // Name is a Service
      {$EXTERNALSYM PNP_VetoLegacyDriver}
      PNP_VetoInsufficientRights   = 12;  // Name is unspecified
      {$EXTERNALSYM PNP_VetoInsufficientRights}
    type
      PPNP_VETO_TYPE = ^PNP_VETO_TYPE;
      {$EXTERNALSYM PPNP_VETO_TYPE}
      PNP_VETO_TYPE = DWORD;
      {$EXTERNALSYM PNP_VETO_TYPE}
    j'ai oublié de notifier que j'ai utilisé D2006 pour le prog mais je ne pense pas que cela ai d'importance
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  15. #15
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 964
    Points
    6 964
    Par défaut
    En insistant un peu, il a finit par me dire que Cfg, CfgMgr32, SetupApi n'étaient pas connu.
    C'est pas des bibliothèques standard ?

    J'utilise Delphi 6#2.

    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  16. #16
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut
    [lung]C'est pas des bibliothèques standard ?[/lung]
    non !

    je crois avoir déjà indiquer au cours des Post mais bon ça fait rien de le rappeler
    qu'il est nécessaire de télécharger les win32API de JEDI

    http://jedi-apilib.sourceforge.net/
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  17. #17
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 964
    Points
    6 964
    Par défaut
    Citation Envoyé par SergioMaster
    qu'il est nécessaire de télécharger les win32API de JEDI

    http://jedi-apilib.sourceforge.net/
    Je l'ai téléchargé (http://jedi-apilib.sourceforge.net/win32api_current.zip), mais ces bibliothèques ni sont pas.
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  18. #18
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut
    ah , oui , bien sur,

    après avoir fait une recherche dans mes packages la réponse est simple

    cfg, cfgMgr32, setupApi viennent de la JVCL (rep common)

    seul jwawinbase est dans Win32API de JEDI
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  19. #19
    Membre régulier Avatar de fs999
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 62
    Localisation : Luxembourg

    Informations forums :
    Inscription : Avril 2004
    Messages : 99
    Points : 111
    Points
    111
    Par défaut
    Bonjour,

    J'ai essayé la superbe routine d'éjection de SergioMaster, qui fonctionne bien sous XP mais pas sous Vista. Il n'y a pas de message d'erreur, la fonction renvoie True, mais le lecteur est toujours connecté...

    J'ai juste modifié la ligne du Result pour indiquer si il y eu une erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
        ...
        VetoType := 0;
        CfgMgr32.CM_Request_Device_Eject(inst, @VetoType, nil, 0, 0);
        Result := VetoType < 8; '<-- ! 
        ...
    Si quelqu'un a une idée...

    Frédéric
    On ne me la fait pas à moi !

  20. #20
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 035
    Points : 40 940
    Points
    40 940
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par fs999 Voir le message
    J'ai essayé la superbe routine d'éjection de SergioMaster
    Si quelqu'un a une idée...
    Merci pour le superbe mais il n'y a vraiment pas de quoi, c'est surtout le travail de l'équipe JEDI dans lequel j'ai pioché sans vergogne , voir plutôt le travail de Ero-Sennin dans le forum .

    Je ne peux pas confirmer que la routine fonctionne sous Vista aussi bien que sous XP (je vais faire un test) . Ce que je peux dire en revanche c'est qu'elle ne fonctionne pas sous XP si la clé est occupé, exemples :
    • le programme d'éjection est sur la clé
    • un explorateur est ouvert
    • un programme en cours sur la clé
    • un fichier ouvert sur la clé
    • etc...


    ce sont les cas que j'ai découverts lors de la mise en place de l'application que je qualifierais de "velonet" (transfert Econome "AVARICIEL" de données d'un site à un autre par l'intermédiaire d'une clé USB ) avec deux postes XP . L'application étant sur la clé , détecte le site, traite les fichiers (selon le site) puis passe la main au programme d'ejection situé lui sur les deux postes .

    Modification
    Je confirme , Helas , cela ne fonctionne PAS sous VISTA
    1° piste l'UAC ? // testé à 8h31 ce n'est pas ça
    2° piste la constante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    GUID_DEVINTERFACE_VOLUME: TGUID = '{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}';
    est peut être différent sous VISTA //
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 4 1234 DernièreDernière

Discussions similaires

  1. Réponses: 1
    Dernier message: 01/09/2009, 16h31
  2. Ejecter disque dur usb
    Par maloups dans le forum Composants
    Réponses: 4
    Dernier message: 27/08/2007, 13h52
  3. Réponses: 2
    Dernier message: 29/03/2007, 15h45
  4. Quel est le nom des dIsques dur usb dans /dev
    Par MrEddy dans le forum Administration système
    Réponses: 5
    Dernier message: 19/10/2004, 21h06
  5. Monter un disque dur USB
    Par Iced Earth dans le forum Matériel
    Réponses: 5
    Dernier message: 13/01/2003, 22h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo