Bonjour,
Pas facile votre question. J'ai testé plein de codes sauf résultats sauf celui-ci
Code : Tout sélectionner
#include <WinApi.au3>
;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);
;StringFormat Output
$szVolumeFormat = "\\\\.\\%s"
$szRootFormat = "%s\\"
$szErrorFormat = "Error %d: %s\n"
;------------------------------------------
;Arbitrary variables
;Global Const $INVALID_HANDLE_VALUE = 0
;------------------------------------------
;DeviceIoControl Contants
;Global Const $FSCTL_LOCK_VOLUME = int(0x090018)
;Global Const $FSCTL_DISMOUNT_VOLUME = int(0x00090020)
;Global Const $IOCTL_STORAGE_EJECT_MEDIA = int(0x002D4808)
;Global Const $IOCTL_STORAGE_MEDIA_REMOVAL = int(0x002D4804)
;------------------------------------------
;Retry Constants
Global Const $LOCK_TIMEOUT = 10000 ; 10 Seconds
Global Const $LOCK_RETRIES = 20
$OpenVolume = InputBox("Ejecting...", "Enter the drive to eject", "G:")
ConsoleWrite("Trying to Eject the drive " & EjectVolume($OpenVolume) & @crlf)
Func ReportError($szMsg)
ConsoleWrite(StringFormat($szErrorFormat, _WinAPI_GetLastErrorMessage (), $szMsg) & @CRLF)
Exit
EndFunc ;==>ReportError
Func OpenVolume($cDriveLetter)
;HANDLE hVolume
;UINT uDriveType
;TCHAR szVolumeName[8]
;TCHAR szRootName[5]
;DWORD dwAccessFlags
$szRootName = StringFormat($szRootFormat, $cDriveLetter)
$uDriveType = DriveGetType($szRootName);
ConsoleWrite($szRootName & @tab & $uDriveType & @crlf)
Switch $uDriveType
Case "Fixed"
$dwAccessFlags = 6
Case "Removable"
$dwAccessFlags = 6
Case "CDROM"
$dwAccessFlags = 2
Case Else
ConsoleWrite("Cannot eject. Drive type is incorrect." & @CRLF)
Return $INVALID_HANDLE_VALUE
EndSwitch
$szVolumeName = StringFormat($szVolumeFormat, $cDriveLetter)
;$szVolumeName = $szVolumeFormat & $cDriveLetter
ConsoleWrite($szVolumeName & @crlf )
$hVolume = _WinAPI_CreateFile ($szVolumeName, 2,$dwAccessFlags, 6)
#cs
hVolume = CreateFile( szVolumeName,
dwAccessFlags,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
#ce
If ($hVolume == $INVALID_HANDLE_VALUE) Then ReportError("CreateFile");
Return $hVolume;
EndFunc ;==>OpenVolume
Func CloseVolume($hVolume)
Return _WinAPI_CloseHandle ($hVolume);
EndFunc ;==>CloseVolume
Func LockVolume($hVolume)
Local $dwBytesReturned
Local $dwSleepAmount
Local $nTryCount
local $iRead
$dwSleepAmount = $LOCK_TIMEOUT / $LOCK_RETRIES;
; Do this in a loop until a timeout period has expired
For $nTryCount = 0 To $nTryCount < $LOCK_RETRIES
If _Device_Control($hVolume, $FSCTL_LOCK_VOLUME, $iRead) Then
Return True
Else
Sleep($dwSleepAmount);
EndIf
Next
Return False;
EndFunc ;==>LockVolume
Func DismountVolume($hVolume)
ConsoleWrite("Dismount " & $hVolume & @crlf)
Local $dwBytesReturned, $iRead
local $aResult = _Device_Control($hVolume, $FSCTL_DISMOUNT_VOLUME, $iRead)
msgbox(0,"",$aResult)
Return $aResult
;Return $dwBytesReturned
EndFunc ;==>DismountVolume
Func PreventRemovalOfVolume($hVolume, $fPreventRemoval)
Local $dwBytesReturned
Local $aResult
Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped
$PMRBUFFER = DllStructCreate("bool PreventMediaRemoval")
DllStructSetData($PMRBUFFER,"PreventMediaRemoval",$fPreventRemoval)
$lpBytesReturned = DllStructCreate("int Read")
$pRead = DllStructGetPtr($lpBytesReturned, "Read")
$aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hVolume,"uint",$IOCTL_STORAGE_MEDIA_REMOVAL,"ptr",DllStructGetPtr($PMRBUFFER),"uint",DllStructGetSize($PMRBUFFER), _
"ptr",$lpOutBuffer,"uint",$nOutBufferSize,"ptr",$pRead,"ptr",$lpOverlapped)
if $aResult = 0 then msgbox(0,"",_WinAPI_GetLastErrorMessage())
Return $aResult <> 0
;& PMRBuffer, sizeof (PREVENT_MEDIA_REMOVAL),
;NULL, 0,
; & dwBytesReturned,
;NULL);
EndFunc ;==>PreventRemovalOfVolume
Func AutoEjectVolume($hVolume)
Local $aResult, $iRead;
$aResult = _Device_Control($hVolume, $IOCTL_STORAGE_EJECT_MEDIA, $iRead)
Return $aResult
EndFunc ;==>AutoEjectVolume
Func EjectVolume($cDriveLetter)
Local $hVolume;
Local $fRemoveSafely = False;
Local $fAutoEject = False;
; Open the volume.
$hVolume = OpenVolume($cDriveLetter);
If $hVolume == $INVALID_HANDLE_VALUE Then Return False
; Lock and dismount the volume.
If LockVolume($hVolume) And DismountVolume($hVolume) Then
$fRemoveSafely = True;
ConsoleWrite("Volume Locked and Dismounted, trying to eject " & @crlf)
; Set prevent removal to false and eject the volume.
If PreventRemovalOfVolume($hVolume, False) And AutoEjectVolume($hVolume) Then
$fAutoEject = True;
EndIf
Else
ConsoleWrite("Volume can't be locked or dismounted, please close possible opened files" & @crlf)
EndIf
; Close the volume so other processes can use the drive.
If CloseVolume($hVolume) = False Then
Return False;
EndIf
If $fAutoEject Then
ConsoleWrite(StringFormat("Media in Drive %s has been ejected safely.\n", $cDriveLetter))
Else
If $fRemoveSafely Then
ConsoleWrite(StringFormat("Media in Drive %s can be safely removed.\n", $cDriveLetter))
EndIf
EndIf
Return True;
EndFunc ;==>EjectVolume
Func _Device_Control($hDevice, $dwIoControlCode, ByRef $iRead)
Local $aResult
Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped
$tRead = DllStructCreate("int Data")
$aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hDevice,"uint",$dwIoControlCode,"ptr",$lpInBuffer,"uint",0, _
"ptr",$lpOutBuffer,"uint",0,"ptr",DllStructGetPtr($tRead),"ptr",$lpOverlapped)
$iRead = DllStructGetData($tRead, "Data")
ConsoleWrite("Device Control " & $iRead & @CRLF)
Return $aResult<>0
EndFunc ;==>_Device_Control
et encore j'ai du le modifier en rajoutant
Case "Fixed"
$dwAccessFlags = 6
Le résultat n'est pas terrible car le disque est désactivé mais pas éjecté (reste visible mais inaccessible)
Dans mes recherches, plusieurs fois a été cité devcon.exe
https://docs.microsoft.com/fr-fr/window ... est/devcon
https://forum.pcastuces.com/commande_de ... s11219.htm
Je n'ai pas poussé plus loin mes recherches avec ce programme. Par contre, USB Disk Ejector semble plus simple d'emploi, programme portable et commandline
https://quickandeasysoftware.net/softwa ... sk-ejector
The following command line options are available:
* /?
Displays a dialog that shows all command line options
. * /NOSAVE
Stops the program from saving any setting
to a file
and ignores any
existing settings file
. * /SILENT
Stops balloon messages from appearing when the program is
run in GUI
mode
. * /SHOWEJECT
Shows the standard
''It is now safe
to now safe
to remove
'' message
when a drive is ejected
. This message is disabled by
default. * /REMOVETHIS
Ejects the drive that the program is running from
. Eg if the program
is
run from a usb stick on drive G
then drive G would be ejected
. * /REMOVELETTER
Ejects the specified drive letter
. Eg /REMOVELETTER G
* /REMOVENAME
Ejects the drive
with the specified name
. Eg /REMOVEDRIVE
"Sandisk
U3 Titanium" Partial name matching is possible
if a wildcard
(*) is used
. Eg /REMOVENAME
"*SANDISK" would eject a drive that had Sandisk
in its name
. * /CLOSEAPPS
If there are any applications running from the drive
, asks them
to close
. If any applications refuse
to close
then the eject will fail
. This switch is considered relatively safe
and should mean that no
unsaved data is lost
. * /CLOSEAPPSFORCE
If there are any applications running from the drive
, force them
to close
. This will mean that any unsaved data
in those programs will
be lost
. This has the same effect as ending a task
/process
.
Fonctionne sur clef ou disque USB.
Je devine que vous préféreriez ne pas passer par un programme intermédiaire, désolé
Je vous joints un bout de code, la première partie liste toutes les connections USB (clef, disque, souris...) et la deuxième partie surveille les connections et déconnections de clefs ou de disque USB
Code : Tout sélectionner
$strComputer = "."
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")
$colDevices = $objWMIService.ExecQuery ("Select * From Win32_USBControllerDevice")
For $objDevice in $colDevices
$strDeviceName = $objDevice.Dependent
$strQuotes = Chr(34)
$strDeviceName = StringReplace($strDeviceName, $strQuotes, "")
$arrDeviceNames = StringSplit($strDeviceName, "=")
$strDeviceName = $arrDeviceNames[2]
$colUSBDevices = $objWMIService.ExecQuery ("Select * From Win32_PnPEntity Where DeviceID = '" & $strDeviceName & "'")
For $objUSBDevice in $colUSBDevices
MsgBox(0,"USB Description",$objUSBDevice.Description)
Next
MsgBox(0,"USB Devices",$strDeviceName)
Next
;===========================================================================================================================================================
$colEvents = $objWMIService.ExecNotificationQuery("Select * From __InstanceOperationEvent Within 5 Where " & "TargetInstance isa 'Win32_LogicalDisk'")
While 1
$objEvent = $colEvents.NextEvent
If $objEvent.TargetInstance.DriveType = 3 Or $objEvent.TargetInstance.DriveType = 2 Then ;2 / Removable Disk, 3 / Local Disk, 4 / Network Drive
Select
Case $objEvent.Path_.Class()="__InstanceCreationEvent"
Consolewrite("Drive " & $objEvent.TargetInstance.DeviceId & "has been added." & @CR)
Case $objEvent.Path_.Class()="__InstanceDeletionEvent"
Consolewrite("Drive " & $objEvent.TargetInstance.DeviceId & "has been removed."& @CR)
EndSelect
EndIf
WEnd
A noter que j'ai essayé Diskpart sans résultat et "RunDll32.exe shell32.dll,Control_RunDLL hotplug.dll" voie sans issue