ShawnBlackPDM Posted August 1, 2018 Share Posted August 1, 2018 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 More sharing options...
BrewManNH Posted August 1, 2018 Share Posted August 1, 2018 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 GudeHow 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 More sharing options...
Earthshine Posted August 1, 2018 Share Posted August 1, 2018 i don't think you want to move files from windows, copy maybe, move, not a good idea My resources are limited. You must ask the right questions Link to comment Share on other sites More sharing options...
ShawnBlackPDM Posted August 2, 2018 Author Share Posted August 2, 2018 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 More sharing options...
ShawnBlackPDM Posted August 2, 2018 Author Share Posted August 2, 2018 15 hours ago, BrewManNH said: Look at FileListToArray, or _FileListToArrayRec to get files in subfolders. Thanks BrewManNH, I'll look into this today. Link to comment Share on other sites More sharing options...
Earthshine Posted August 2, 2018 Share Posted August 2, 2018 oh, i thought you wanted to move files from C:\Windows LOL My resources are limited. You must ask the right questions Link to comment Share on other sites More sharing options...
ShawnBlackPDM Posted September 5, 2018 Author Share Posted September 5, 2018 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. expandcollapse popup#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 More sharing options...
mikell Posted September 5, 2018 Share Posted September 5, 2018 Help file says : GUICtrlSetOnEvent : You can not call a function using parameters. Link to comment Share on other sites More sharing options...
ShawnBlackPDM Posted September 5, 2018 Author Share Posted September 5, 2018 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 More sharing options...
Developers Jos Posted September 5, 2018 Developers Share Posted September 5, 2018 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 Fin 1 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 More sharing options...
mikell Posted September 6, 2018 Share Posted September 6, 2018 15 hours ago, Jos said: Did you also notice this part Morality : read the help file pages twice Fin 1 Link to comment Share on other sites More sharing options...
ShawnBlackPDM Posted September 11, 2018 Author Share Posted September 11, 2018 (edited) 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 September 11, 2018 by ShawnBlackPDM Answered part of my own question Link to comment Share on other sites More sharing options...
FrancescoDiMuro Posted September 12, 2018 Share Posted September 12, 2018 (edited) You could do it handling WM_DEVICECHANGE Windows Message, or do it by WMI Maybe this could help you: Spoiler expandcollapse popup#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 September 12, 2018 by FrancescoDiMuro Click here to see my signature: Spoiler ALWAYS GOOD TO READ: Forum Rules Forum Etiquette Link to comment Share on other sites More sharing options...
ShawnBlackPDM Posted September 12, 2018 Author Share Posted September 12, 2018 (edited) 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 September 12, 2018 by ShawnBlackPDM Link to comment Share on other sites More sharing options...
FrancescoDiMuro Posted September 12, 2018 Share Posted September 12, 2018 (edited) @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 September 12, 2018 by FrancescoDiMuro Click here to see my signature: Spoiler ALWAYS GOOD TO READ: Forum Rules Forum Etiquette Link to comment Share on other sites More sharing options...
ShawnBlackPDM Posted September 12, 2018 Author Share Posted September 12, 2018 I loaded all 12 events provided from the WM_DEVICECHANGE, and none of them triggered when a card was added and removed from the card reader. But because Windows will run the Auto-Run for the media added to the reader there must be a trigger. I'll keep digging. Link to comment Share on other sites More sharing options...
FrancescoDiMuro Posted September 12, 2018 Share Posted September 12, 2018 @ShawnBlackPDM I was looking at this. Maybe that could help you somehow Click here to see my signature: Spoiler ALWAYS GOOD TO READ: Forum Rules Forum Etiquette Link to comment Share on other sites More sharing options...
ShawnBlackPDM Posted September 12, 2018 Author Share Posted September 12, 2018 Thanks, but I don't want to get in to modifying the registry. And from what I saw of the article it looks like it would work exclusively for Windows MEDIA CENTER. I don't think that's a path I'm comfortable traveling. But thanks for your help. Link to comment Share on other sites More sharing options...
ShawnBlackPDM Posted September 12, 2018 Author Share Posted September 12, 2018 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. expandcollapse popup#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 More sharing options...
ShawnBlackPDM Posted September 17, 2018 Author Share Posted September 17, 2018 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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now