Jump to content

Displaying contents of Windows Directory


Recommended Posts

I am about 3 hours into working with AutoIt, and I've got to say it's quite the powerful tool.

I downloaded the software because I want to create a simple program to move files from a directory in Windows to an SD card. I'm able to create the GUI, menus, and lists, but I haven't seen anywhere that can auto-populate the lists (with the contents of the removable media or a folder). I've been through many of the tutorials, and lessons, but I haven't seen this implemented anywhere.

Any pointers would be appreciated.

Thanks

Link to comment
Share on other sites

Look at FileListToArray, or _FileListToArrayRec to get files in subfolders.

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

15 hours ago, Earthshine said:

i don't think you want to move files from windows, copy maybe, move, not a good idea

Thanks for the concern Earthshine. I am going to include an import feature that will copy files to a temp directory and then move. I need to ensure that all files are accounted for and that none are accidentally duplicated. Imagine that I need to place a single .jpg onto an SD card, and no two cards can have the same image. Copy could work from the native drive, but I would have to build in a method to avoid making duplicate.

Link to comment
Share on other sites

  • 1 month later...

I'm finally able to make it back to this project, and I've run into another road block. One of the features I want to do is provide the user an option to choose the removable drive for which to move files onto. I've got that part. But now I need to update a list when the user changes the Drive. I can use the "GUICtrlRead" to retrieve the selected drive, then I can use the "_FileListToArray" to pull the contents, but I'm not sure how to force the list to refresh when the user changes the state of the Combo Box. I hope this all makes sense.

Here is a portion of the script with all of the essentails. Any help would be appreciated.

#include <GUIConstantsEx.au3>
#include <File.au3>
#include <MsgBoxConstants.au3>

GuiCreate("SD Card Manager", 600, 400)
GuiSetIcon("C:\Program Files (x86)\AutoIt3\Icons\au3.ico", 0)

GUISetState(@SW_SHOW)

Local $idMySDList = GUICtrlCreateList("", 50, 64, 200, 125)
Local $idButton_Close = GUICtrlCreateButton("Exit", 50, 200, 75, 25)
Local $aDriveArray = DriveGetDrive($DT_REMOVABLE)
Local $idDriveCombo = GUICtrlCreateCombo("", 50, 32, 100, 25)
_DisplayArray($aDriveArray,$idDriveCombo)
Local $iSDMenuState = GUICtrlRead($idDriveCombo)
Local $aSDFiles = _FileListToArray ($iSDMenuState&"\", "*.*", $FLTA_FILES)

;;;This is what I expect would change the List, but it doesn't push a change
GUICtrlSetOnEvent ($idDriveCombo, _DisplayArray($aSDFiles,$idMySDList))
;;;

While 1
      Switch GUIGetMsg()
         Case $GUI_EVENT_CLOSE
            GUIDelete()
            Exit
         Case $idButton_Close
            Exit
      EndSwitch

    WEnd

Func _DisplayArray($iFuncArray,$iFuncVariable)
   If @error Then
         ; An error occurred when retrieving the drives.
         MsgBox($MB_SYSTEMMODAL, "", "It appears an error occurred.")
      Else
         For $i = 1 To $iFuncArray[0]
            ; Show all the drives found and convert the drive letter to uppercase.
            GUICtrlSetData($iFuncVariable, StringUpper($iFuncArray[$i]))
         Next
      EndIf
EndFunc

 

Link to comment
Share on other sites

That's unfortunate, however there's more going on here.

If I change the GUICtrlSetOnEvent to 

GUICtrlSetOnEvent ($idDriveCombo, "_DisplayDrive")

and the function to

Func _DisplayDrive()
   MsgBox($MB_SYSTEMMODAL, "" , "You changed drives")
   EndFunc

It "should" display a simple message box each time a new drive is chosen, but it does not.

 

I did just try to put the new function in the GUIGetMsg() Switch, and it works there. Unfortunately my original function keeps returning the root directoy, so I'm going to look there and see if I can get it resolved.

Link to comment
Share on other sites

  • Developers

Did you also notice this part in the helpfile for GUICtrlSetOnEvent  ?:

Quote

Remarks

OnEvent functions are only called when the option GUIOnEventMode is set to 1 - when in this mode GUIGetMsg() is NOT used at all.

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Thank you all for your help. I am almost complete with my project, but I have one final hurdle.

I want to add in an "Auto Eject" when the script is complete and an "Auto Run" when removable media is added.

I found this old post about AutoEjectIt v 1.0, but I'm certain there is an easier way to eject a drive, and I haven't found any conversation on the forums that would help detect added drives.

Edit* I was able to find the User Function "_WinAPI_EjectMedia ()" that can handle the first task of ejecting the drive. I initially thought it was CDROM only, but I tried it and it worked. I'm still working on the second feature to run a function when a removable drive is added, but if you could help I appreciate it.

Edited by ShawnBlackPDM
Answered part of my own question
Link to comment
Share on other sites

You could do it handling WM_DEVICECHANGE Windows Message, or do it by WMI :)
Maybe this could help you:

Spoiler
#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.5
 Author........: FrancescoDiMuro
 Date Created..: 12/09/2018
 Resources:
    - WM_DEVICECHANGE            : https://docs.microsoft.com/en-us/windows/desktop/devio/wm-devicechange
    - $DBT_DEVICEARRIVAL         : https://docs.microsoft.com/en-us/windows/desktop/devio/dbt-devicearrival
    - $DBT_DEVICEREMOVECOMPLETE  : https://docs.microsoft.com/en-us/windows/desktop/devio/dbt-deviceremovecomplete

 Script Function:
    Get the connected Drives to the PC ( with automatic refresh ).

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here

#include <Date.au3>
#include <GUIConstantsEx.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>

Opt("GUIOnEventMode", 1)

Global Const $DBT_DEVICEARRIVAL = 0x8000, _
             $DBT_DEVICEREMOVECOMPLETE = 0x8004


Global $frmMainForm = GUICreate("frmMainForm", 800, 462, 192, 124)
Global $lvwDrives = GUICtrlCreateListView("Drive|Label|Type|Status|File System|Space Free|Total Space|Serial Number", 8, 8, 782, 446, $LVS_REPORT, BitOR($WS_EX_CLIENTEDGE, $LVS_EX_FULLROWSELECT, $LVS_EX_GRIDLINES))
Global $hdlDrives = GUICtrlGetHandle($lvwDrives)
GUISetOnEvent($GUI_EVENT_CLOSE, "ExitApplication")
GUISetState(@SW_SHOW, $frmMainForm)

GetConnectedDrives()

GUIRegisterMsg($WM_DEVICECHANGE, "WM_DEVICECHANGE")

While 1
    Sleep(100)
WEnd


Func ExitApplication()
    Exit
EndFunc

Func WM_DEVICECHANGE($hWnd, $iMsg, $wParam, $lParam)

    Switch $wParam
        Case $DBT_DEVICEARRIVAL
            ConsoleWrite("[" & _Now() & "]: Event Fired = " & $DBT_DEVICEARRIVAL & " ( $DBT_DEVICEARRIVAL )" & @CRLF)
            GetConnectedDrives()
        Case $DBT_DEVICEREMOVECOMPLETE
            ConsoleWrite("[" & _Now() & "]: Event Fired = " & $DBT_DEVICEREMOVECOMPLETE & " ( $DBT_DEVICEREMOVECOMPLETE )" & @CRLF)
            GetConnectedDrives()
    EndSwitch

EndFunc

Func GetConnectedDrives()

    Local $arrDrives, _
          $strListViewItem

    $arrDrives = DriveGetDrive($DT_ALL)
    If @error Then
        ConsoleWrite("Error while getting all drives! Error: " & @error & @CRLF)
    Else
        _GUICtrlListView_DeleteAllItems($lvwDrives)

        For $i = 1 To UBound($arrDrives) - 1 Step 1

            $strListViewItem = StringUpper($arrDrives[$i]) & "|" & _
                               DriveGetLabel($arrDrives[$i]) & "|" & _
                               DriveGetType($arrDrives[$i]) & "|" & _
                               DriveStatus($arrDrives[$i]) & "|" & _
                               DriveGetFileSystem($arrDrives[$i]) & "|" & _
                               MBToGB(DriveSpaceFree($arrDrives[$i])) & " GB" & "|" & _
                               MBToGB(DriveSpaceTotal($arrDrives[$i])) & " GB" & "|" & _
                               DriveGetSerial($arrDrives[$i])

            GUICtrlCreateListViewItem($strListViewItem, $lvwDrives)
        Next
    EndIf

EndFunc

Func MBToGB($fltBytes)
    Return Round($fltBytes/1024, 3)
EndFunc

 

Cheers :)

Edited by FrancescoDiMuro

Click here to see my signature:

Spoiler

ALWAYS GOOD TO READ:

 

Link to comment
Share on other sites

Thanks FrancescoDiMuro. I've been looking at AutoIt for about a month in my free time, and though I'm picking it up, it's like drinking from a fire hydrant.

I understand all of your Functions, but I couldn't get the WM_DEVICECHANGE to run (or more precisely it only ran once). I did some troubleshooting and found it has to do with the Card Reader I am using. If I plug the Card Reader with SD Card into the USB port, it works correctly. If I remove the SD Card from the Reader, but leave the Reader plugged in, it doesn't trigger.

Windows is able to detect the insertion of a card into the reader and Auto-Run, but it doesn't trigger the DBT_DEVICEARRIVAL. Is there by chance a way to see the parameter Windows calls during an event? If so, I could capture the parameter setting and add a new variable for it.

Edited by ShawnBlackPDM
Link to comment
Share on other sites

@ShawnBlackPDM
You could put in the Switch all the different Events which are captured by WM_DEVICECHANGE Message...
If one of the other Events are fired, then work on it; else, you have to unplug and plug again the USB Card Reader, in order to get it captured by DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE Events.
Try that, and let us know ;)

Edited by FrancescoDiMuro

Click here to see my signature:

Spoiler

ALWAYS GOOD TO READ:

 

Link to comment
Share on other sites

For anyone who is curious, or who has helped me this past month. Here is a copy of the script I have been working on. Any feedback, positive or negative would be appreciated.

Background. In my business we have *.bin files that need loaded onto SD cards. 1 file per card. It takes significant time to transfer the files. For the purpose of testing I have changed all *.bin files to *jpg. It will not remove any *.jpg from your computer, but will wipe your removable media to ensure there is only one file on each card.

I am not a programmer, and I've likely spent 30 hours at most learning AutoIt language. I'm happy with it so far, but tell me if it's crap.

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.5
 Author: Shawn Black
 Resources:
    - WM_DEVICECHANGE            : https://docs.microsoft.com/en-us/windows/desktop/devio/wm-devicechange
    - $DBT_DEVICEARRIVAL         : https://docs.microsoft.com/en-us/windows/desktop/devio/dbt-devicearrival
    - $DBT_DEVICEREMOVECOMPLETE  : https://docs.microsoft.com/en-us/windows/desktop/devio/dbt-deviceremovecomplete
 Script Function:
    Summary: Loads ".bat" file onto SD Cards.
    Load the Removable media (SD Card) into the drive and refresh
    Load your data files for transfer
    Data files are stored to a temporary directory
    Once Transfer is pressed the first file (alphebetically) is transfered to the Removable Media
    The drive is ejected.
    A new SD Card is inserted

    ;Not yet functioning;
    the next file Auto transfers and the media ejects
    Transfering repeats until all files are moved.
    ;Not yet functioning;

#ce ----------------------------------------------------------------------------
#include <AutoItConstants.au3>
#include <GuiConstants.au3>
#include <GUIConstantsEx.au3>
#include <File.au3>
#include <AVIConstants.au3>
#include <GuiConstantsEx.au3>
#include <TreeViewConstants.au3>
#include <FileConstants.au3>
#include <MsgBoxConstants.au3>
#include <WinAPIFiles.au3>


Global Const $DBT_DEVICEARRIVAL = 0x8000, _
             $DBT_DEVICEREMOVECOMPLETE = 0x8004

GuiCreate("SD Card Manager", 600, 400)
GuiSetIcon("C:\Program Files (x86)\AutoIt3\Icons\au3.ico", 0)

GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_DEVICECHANGE, "WM_DEVICECHANGE")

; Create a MENU Control.
Local $idFileMenu, $idFileItem, $idSeparator1
Local $idExitItem, $idHelpMenu, $idAboutItem, $idOkButton, $idCancelButton
Local $iMsg
Local $aFileList
Local $sAboutMessage = 'This is still in developement, but when complete will be a tool to quickly load ".bin" files onto SD cards.'
$idFileMenu = GUICtrlCreateMenu("File")
$idFileItem = GUICtrlCreateMenuItem("Open...", $idFileMenu)
$idSeparator1 = GUICtrlCreateMenuItem("", $idFileMenu)
$idExitItem = GUICtrlCreateMenuItem("Exit", $idFileMenu)
$idHelpMenu = GUICtrlCreateMenu("Help")
$idAboutItem = GUICtrlCreateMenuItem("About", $idHelpMenu)
GUICtrlSetLimit(-1, 200) ; to limit horizontal scrolling
GUICtrlSetData(-1, $sAboutMessage)

; Create Button Controls
Local $idButton_Transfer = GUICtrlCreateButton("Transfer", 50, 200, 115, 25)
Local $idButton_Close = GUICtrlCreateButton("Exit", 175, 200, 75, 25)
Local $idButton_Add = GUICtrlCreateButton("Load", 300, 32, 75, 25)
Local $idButton_Clear = GUICtrlCreateButton("Clear", 425, 32, 75, 25)
Global $idMySDList = GUICtrlCreateList("", 50, 64, 200, 125)
Global $idMyBINList = GUICtrlCreateList("", 300, 64, 200, 300)
Local $idDriveCombo = GUICtrlCreateCombo("", 50, 32, 100, 25)
Local $idButton_Refresh = GUICtrlCreateButton("Refresh", 175, 32, 75, 25)

Global Const $sTempPath = @TempDir & "\SDCardManager\"
_GetDrives()

While 1
      Switch GUIGetMsg()
         Case $GUI_EVENT_CLOSE
            GUIDelete()
            Exit
         Case $idButton_Add
            _Load($idMyBINList,$aFileList)
         Case $idButton_Clear
            GUICtrlSetData($idMyBINList, "")
         Case $idButton_Close
            Exit
         Case $idFileItem
            _Load($idMyBINList,$aFileList)
         Case $idExitItem
            GUIDelete()
            Exit
         Case $idAboutItem
            MsgBox($MB_SYSTEMMODAL, "", $sAboutMessage)
         Case $idDriveCombo
            $iSDMenuState = GUICtrlRead($idDriveCombo)&"\"
            $iSDDrive = GUICtrlRead($idDriveCombo)
            if DriveGetFileSystem ($iSDMenuState)="" Then ;;Error handling if the Drive is not active.
                ;MsgBox($MB_SYSTEMMODAL, "", "The Drive is not Active") ;Don't need the message box
                GUICtrlSetData($idMySDList, "")
            Else
               $aSDFiles = _FileListToArray ($iSDMenuState, "*.*", $FLTA_FILES);If the dive is active, the contents will load into an array
               _DisplayArray($aSDFiles,$idMySDList)
            EndIf
         Case $idButton_Refresh
            GUICtrlSetData($idDriveCombo, "")
            GUICtrlSetData($idMySDList, "")
            _GetDrives()
         Case $idButton_Transfer
            ;_ArrayDisplay($aFileList, "Array")
            _Xfer($sTempPath,$aFileList,$iSDMenuState)
            _WinAPI_EjectMedia ($iSDDrive)
            ;MsgBox($MB_SYSTEMMODAL, "", "Did "&$iSDMenuState&" unmount?")
         ;Case ;Placeholder for the Device Arrival Event
            ;MsgBox($MB_SYSTEMMODAL, "", "Did "&$iSDMenuState&" unmount?")
            ;_Xfer next file in list if $iArray[0]>0 Else MsgBox("Complete")
      EndSwitch

    WEnd

; Function to load data from Dialogue
Func _Load($idListField,$aListArray)
   GUICtrlSetData($idListField, "")
   Local Const $sMessage = "Select a folder"
   ;Global $sFolderPath = FileSelectFolder ($sMessage, "\\pdm05\Desktop\Current Jobs nw comp\"); Path for production
   Global $sFolderPath = FileSelectFolder ($sMessage, @DesktopDir); Path for testing

   ;FileDelete ($sTempPath&"*.bin"); Code for Production
   ;FileCopy ($sFolderPath&"\*.bin", $sTempPath,$FC_OVERWRITE + $FC_CREATEPATH); Code for Production
   FileDelete ($sTempPath&"*.jpg"); Code for Testing
   FileCopy ($sFolderPath&"\*.jpg", $sTempPath,$FC_OVERWRITE + $FC_CREATEPATH); Code for Testing


   ;Local $sFolderPath = FileSelectFolder ($sMessage, @DesktopDir)
    If @error Then
        ; Display the error message.
        MsgBox($MB_SYSTEMMODAL, "", "No folder was selected.")
    Else
      ;MsgBox($MB_SYSTEMMODAL, "", $sFolderPath & "\")
      ;$aListArray = _FileListToArray ($sTempPath, "*.bin", $FLTA_FILES); Code for Production
      $aListArray = _FileListToArray ($sTempPath, "*.jpg", $FLTA_FILES); Code for Testing
      ;_ArrayDisplay($aListArray, "")
      _DisplayArray($aListArray,$idMyBINList)
    EndIf
    $aFileList = $aListArray
 EndFunc   ;==>_Load

; This displays files and drives to the GUI from an array of contents.
 Func _DisplayArray($iFuncArray,$iFuncVariable)
   If $iFuncArray = 0 Then
         ; An error occurred when retrieving the drives.
         GUICtrlSetData($iFuncVariable, "")
   Else
     For $i = 1 To $iFuncArray[0]
        ; Show all the drives found and convert the drive letter to uppercase.
        GUICtrlSetData($iFuncVariable, StringUpper($iFuncArray[$i]))
     Next
   EndIf
EndFunc   ;==>_DisplayArray

; This function scans your computer for removable media to display in the combo box
Func _GetDrives()
    Local $aDriveArray = DriveGetDrive($DT_REMOVABLE)
    Local $Counter = $aDriveArray[0]
    Local $i = $aDriveArray[0]
    Do
      if DriveGetFileSystem ($aDriveArray[$i]&"\")="" Then
            _ArrayDelete($aDriveArray, $i)
            $aDriveArray[0] = $aDriveArray[0]-1
            $i = $i - 1
            $Counter = $Counter - 1
      Else
            $i = $i - 1
            $Counter = $Counter - 1
      EndIf
    Until $Counter = 0

    _DisplayArray($aDriveArray,$idDriveCombo)
    Local $iSDMenuState = ""
    Global $aSDFiles[] = _FileListToArray ($iSDMenuState, "*.*", $FLTA_FILES)
 EndFunc   ;==> _GetDrives

; This function transfers the first file from the @TempDir, and moves the first file to the Removable drive selected.
Func _Xfer($FPath,$FName,$FDrive)
   if $FPath&$FName = "" Then
      MsgBox($MB_SYSTEMMODAL,"","There are no files to transfer")
   Else
      FileDelete ($iSDMenuState&"*.*")
      FileMove($FPath&$FName[1], $FDrive)
      ;$aFileList = _FileListToArray ($FPath, "*.bin", $FLTA_FILES); Code for Production
      $aFileList = _FileListToArray ($FPath, "*.jpg", $FLTA_FILES); Code for Testing
      GUICtrlSetData($idMyBINList, "")
      _DisplayArray($aFileList,$idMyBINList)
      $aSDFiles = _FileListToArray ($iSDMenuState, "*.*", $FLTA_FILES)
      GUICtrlSetData($idMySDList, "")
      _DisplayArray($aSDFiles,$idMySDList)
   EndIf
EndFunc   ;==>_Xfer

Func WM_DEVICECHANGE($hWnd, $iMsg, $wParam, $lParam)

    Switch $wParam
        Case $DBT_DEVICEARRIVAL
            ConsoleWrite("[" & _Now() & "]: Event Fired = " & $DBT_DEVICEARRIVAL & " ( $DBT_DEVICEARRIVAL )" & @CRLF)
            GetConnectedDrives()
        Case $DBT_DEVICEREMOVECOMPLETE
            ConsoleWrite("[" & _Now() & "]: Event Fired = " & $DBT_DEVICEREMOVECOMPLETE & " ( $DBT_DEVICEREMOVECOMPLETE )" & @CRLF)
            GetConnectedDrives()
    EndSwitch

EndFunc

 

Link to comment
Share on other sites

I think I have the monitor event working. It took some digging, but hopefully if I can find a couple hours tomorrow and post the final resolution. I searched Stackoverflow for a combined usage of DBT_DEVICEARRIVAL and Reader and came across the SHChangeNotifyRegister function. @RetroComp created a script years ago that was able to watch for the specific event of inserting an SD card into the reader as well as many other events. I have integrated pieces of his work and can write to the console when necessary. I just need to finalize everything.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...