Что нового

Как при обнаружении флешки запустить метод один раз

djasup

Новичок
Сообщения
64
Репутация
1
К примеру есть код
Код:
#include <file.au3>
#include <array.au3>
#include <FileOperations.au3>
HotKeySet("{ESC}", "Terminate")
While 1 
$aArray = DriveGetDrive("REMOVABLE")
   If @error Then 
	  ExitLoop
   Else
	  For $i = 1 To $aArray[0]
	  $FileList=_FO_FileSearch($aArray[$i], 'txt', True, 125, 1,1,2)
		 For $z = 1 To $FileList[0]
			   FileCopy($FileList[$z],'C:\',1)
		 Next	  
	  Next   
   EndIf	
Sleep(100)
WEnd

Func Terminate()
    Exit 0
EndFunc

В таком случае как видите копирование файлов будет бесконечно пока флешка вставлена, это не хорошо. Как можно проверить что эти файлы скопированы, да конечно можно проверить на наличие файлов, но что если файлы были модифицированы ? В общем подытожим как сделать, чтобы после того как вставлена флешка копирование произошло только один раз?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Автор
D

djasup

Новичок
Сообщения
64
Репутация
1
Re: Как узнать проверялась ли флешка

делаю так

Код:
#include <GUIConstantsEx.au3>
#include <file.au3>
#include <array.au3>
#include <FileOperations.au3>

Global Const $WM_DEVICECHANGE = 0x0219
Global Const $DBT_DEVICEARRIVAL = 0x8000 ; Найдено новое устройство
Global Const $DBT_DEVICEREMOVECOMPLETE = 0x8004 ; Устройство отключено
Global Const $DBT_DEVTYP_VOLUME = 0x00000002 ; Логический диск

Global $k = 0

$Gui = GUICreate("WM_DEVICECHANGE", 370, 140)
GUICtrlCreateLabel('Функция WM_DEVICECHANGE выполняется при подключении или отключении устройств к системе. Попробуйте вставить флешку', 5, 5, 360, 70)

GUISetState()
GUIRegisterMsg($WM_DEVICECHANGE, "WM_DEVICECHANGE")

Do
Until GUIGetMsg() = -3

Func WM_DEVICECHANGE($hWnd, $Msg, $wParam, $lParam)
   
     If ($wParam = $DBT_DEVICEARRIVAL) Or ($wParam = $DBT_DEVICEREMOVECOMPLETE) Then
        Local $DEV_BROADCAST_VOLUME = DllStructCreate("int dbcvsize;int dbcvdevicetype;int dbcvreserved;int dbcvunitmask;" & _
                "ushort dbcvflags", $lParam)
        Local $iDriveType = DllStructGetData($DEV_BROADCAST_VOLUME, "dbcvdevicetype")
    Else
        Return $GUI_RUNDEFMSG
    EndIf
    
    ; Если устройство не является логическим диском, то выход из функции
    If $iDriveType <> $DBT_DEVTYP_VOLUME Then Return $GUI_RUNDEFMSG
    
    Local $iMask = DllStructGetData($DEV_BROADCAST_VOLUME, "dbcvunitmask")
    $iMask = Log($iMask) / Log(2)
    
    Local $iDrive = Chr(65 + $iMask) & ":"
    
    Switch $wParam
        Case $DBT_DEVICEARRIVAL ; обнаружение устройства
            CopyFlash()
            
        Case $DBT_DEVICEREMOVECOMPLETE ; отключение устройства
            TrayTip("WM_DEVICECHANGE", "Устройство отключено", 5, 2)
    EndSwitch
    
    Return $GUI_RUNDEFMSG
 EndFunc
 
 
 Func  CopyFlash()
	$aArray = DriveGetDrive("REMOVABLE")
   If @error Then 
	  
   Else
	  For $i = 1 To $aArray[0]
	  $FileList=_FO_FileSearch($aArray[$i], 'txt', True, 125, 1,1,2)
		 For $z = 1 To $FileList[0]
			   FileCopy($FileList[$z],'C:\',1)
		 Next	  
	  Next   
   EndIf	
EndFunc


То все ок работает, стоит убрать мне

Код:
$Gui = GUICreate("WM_DEVICECHANGE", 370, 140)
GUICtrlCreateLabel('Функция WM_DEVICECHANGE выполняется при подключении или отключении устройств к системе. Попробуйте вставить флешку', 5, 5, 360, 70)


то перестает работать, обьясните как это может быть связанно, я чет ваще не догоняю?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Re: Как узнать проверялась ли флешка

не убирай ничего просто запиши это
Код:
GUISetState(@SW_HIDE)

вместо этого
Код:
GUISetState()

ну или так
Код:
#Include <WinAPIEx.au3>
Opt('MustDeclareVars', 1)
Opt('TrayAutoPause', 0)

Global Const $DBT_DEVICEARRIVAL = 0x00008000
Global Const $DBT_DEVICEREMOVECOMPLETE = 0x00008004
Global Const $DBT_DEVTYP_VOLUME = 0x00000002
Global Const $IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x002D1080
Global Const $DRIVE_BUS_TYPE_USB = 0x07
Global Const $WM_DEVICECHANGE = 0x0219

Global $hForm = GUICreate('')
Global $Drives, $Volume = _WinAPI_GetLogicalDrives()
Global $Device = 1

GUIRegisterMsg($WM_DEVICECHANGE, 'WM_DEVICECHANGE')

While 1
    Sleep(100)
    If $Device Then
        $Drives = _GetDriveLetter($Volume)
        $Device = 0
        $Volume = 0
        For $j = 1 To $Drives[0]
         _USBCheck($Drives[$j])
		 If Not @error Then
			FileCopy('test.txt',$Drives[$j]); здесь функция копирования
			EndIf
        Next
    EndIf
WEnd

Func _GetDriveLetter($iMask)

    Local $Drive[27] = [0]

    If $iMask Then
        For $i = 0 To 25
            If BitAND(BitShift($iMask, $i), 1) Then
                $Drive[$Drive[0] + 1] = Chr(65 + $i) & ':'
                $Drive[0] += 1
            EndIf
        Next
    EndIf
    ReDim $Drive[$Drive[0] + 1]
    Return $Drive
EndFunc   ;==>_GetDriveLetter

Func _USBCheck($sVolume)

    Local $hDrive, $tData, $iBus, $iRes, $Fs

    $iBus = _WinAPI_GetDriveBusType($sVolume)
    Switch $iBus
        Case $DRIVE_BUS_TYPE_USB
            $hDrive = _WinAPI_CreateFileEx('\\.\' & $sVolume, 3, 0, 0)
            If Not $hDrive Then
                Return
            EndIf
            $tData = DllStructCreate('dword DeviceType;ulong DeviceNumber;ulong PartitionNumber')
            $iRes = _WinAPI_DeviceIoControl($hDrive, $IOCTL_STORAGE_GET_DEVICE_NUMBER, 0, 0, DllStructGetPtr($tData), DllStructGetSize($tData))
            _WinAPI_CloseHandle($hDrive)
            If (Not $iRes) Or (Not (DllStructGetData($tData, 'DeviceType') = 7)) Then
                Return
            EndIf
        Case Else
            Return
    EndSwitch
EndFunc   ;==>_USBCheck

Func WM_DEVICECHANGE($hWnd, $iMsg, $wParam, $lParam)
    Switch $hWnd
        Case $hForm
            Switch $wParam
                Case $DBT_DEVICEARRIVAL, $DBT_DEVICEREMOVECOMPLETE

                    Local $tDBV = DllStructCreate('dword Size;dword DeviceType;dword Reserved;dword Mask;ushort Flags', $lParam)
                    Local $Type = DllStructGetData($tDBV, 'DeviceType')
                    Local $Item

                    Switch $Type
                        Case $DBT_DEVTYP_VOLUME
                            If Not DllStructGetData($tDBV, 'Flags') Then
                                Switch $wParam
                                    Case $DBT_DEVICEARRIVAL
                                        $Volume = BitOR($Volume, DllStructGetData($tDBV, 'Mask'))
                                        $Device = 1
                                    Case Else

                                EndSwitch
                            EndIf
                        Case Else

                    EndSwitch
            EndSwitch
    EndSwitch
    Return 'GUI_RUNDEFMSG'
EndFunc   ;==>WM_DEVICECHANGE
да, и тему переименуй , так как задача у тебя
djasup [?]
копирование произошло только один раз
 

Medic84

Омега
Команда форума
Администратор
Сообщения
1,590
Репутация
341
Re: Как узнать проверялась ли флешка

Код:
Do
Until GUIGetMsg() = -3

Советую сделать:
Код:
Do
Sleep(1)
Until GUIGetMsg() = -3

Иначе программа в ожидании будет грузить процессор.
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
Re: Как узнать проверялась ли флешка

Medic84
Функция GUIGetMsg уже создаёт задержку Sleep(10), о чём многократно указано в справке. Не нужно добавлять лишнее.

djasup
обьясните как это может быть связанно
Любое WM сообщение (window message) отправляется окну.
 

Ganibal95

GreenBytes
Сообщения
877
Репутация
240
Re: Как узнать проверялась ли флешка

может так:
Код:
#include <file.au3>
#include <array.au3>
#include <FileOperations.au3>
HotKeySet("{ESC}", "Terminate")

$Copy = 0

While 1 
$aArray = DriveGetDrive("REMOVABLE")
If @error Then 
	ExitLoop
Else
	if $Copy == 0 Then
		For $i = 1 To $aArray[0]
			$FileList=_FO_FileSearch($aArray[$i], 'txt', True, 125, 1,1,2)
			For $z = 1 To $FileList[0]
				FileCopy($FileList[$z],'C:\',1)
			Next     
		Next
		$Copy = 1
	EndIf
EndIf
Sleep(100)
WEnd
 
Верх