I want to ask you a question regarding Shell.Application COM Object. The programming language I work in is AutoIT. I would like to know, how can I open a folder in the exact same Window a previous folder has been opened.
For instance, if I open the C:\Folder in a Window and it has a subfolder, then how can I make the Script open that subfolder in the same window the "parent folder" has been opened, without creating a new window for that. The only way I can open a Folder is like this:
global $ShellApplication = ObjCreate("Shell.Application")
$ShellApplication.Explore("C:\Folder")
Sleep(100)
$ShellApplication.Explore("C:\Folder\Subfolder")
but this way is the wrong way. I hope someone has got any idea about how this could be achieved.
I don't know whether this is what you want, but you can automate the current window like this:
#include <Array.au3>
Opt("SendKeyDelay", 1) ;5 milliseconds
Opt("SendKeyDownDelay", 1) ;1 millisecond
$pid = ShellExecute("explorer.exe ", #DesktopDir)
Sleep(300)
;~ $aWinList=WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]")
;~ _ArrayDisplay($aWinList)
ConsoleWrite($pid & #CRLF)
$handle = _WinGetHandleByPID($pid)
Sleep(2000)
SendKeepActive($handle)
Send('{F4}')
Send('^a')
Send(#AppDataCommonDir & "{ENTER}")
Func _WinGetHandleByPID($vProcess, $nShow = 1)
; Get Window Handle by PID
; Author Hubertus
; derived from Smoke_N's script with the same name,
; but to handle more than one process with the same name
; and to return handle of newest window ($nShow = 2).
;
; $vProcess = Processname(e.g. "Notepad.exe") or Processnumber(e.g. 4711 )
; $nShow = -1 "All (Visble or not)", $nShow = 0 "Not Visible Only", $nShow = 1 "Visible Only", $nShow = 2 "return handle of newest window "
; #error = 0 Returns array of matches. Array[0][0] and #extended shows number of matches.
; #error = 0 and $nShow = 2 return handle of newest window
; Array[n][0] shows windows title. Array[n][1] shows windows handle. n = 1 to #extended
; #error = 1 Process not found.
; #error = 2 Window not found.
If Not ProcessExists($vProcess) Then Return SetError(1, 0, 0) ; no matching process
Local $iWinList, $aWinList = WinList()
Local $iResult, $aResult[UBound($aWinList)][2]
Local $iProcessList, $aProcessList = ProcessList($vProcess)
If $aProcessList[0][0] = 0 Then Local $aProcessList[2][2] = [[1, 0], ["", $vProcess]]
For $iWinList = 1 To $aWinList[0][0]
For $iProcessList = 1 To $aProcessList[0][0]
If WinGetProcess($aWinList[$iWinList][1]) = $aProcessList[$iProcessList][1] Then
If $nShow > -1 And Not $nShow = (2 = BitAND(WinGetState($aWinList[$iWinList][1]), 2)) Then ContinueLoop
$iResult += 1
$aResult[$iResult][0] = $aWinList[$iWinList][0]
$aResult[$iResult][1] = $aWinList[$iWinList][1]
EndIf
Next
Next
If $iResult = 0 Then Return SetError(2, 0, 0) ; no window found
ReDim $aResult[$iResult + 1][2]
$aResult[0][0] = $iResult
If $nShow = 2 Then Return SetError(0, $iResult, $aResult[1][1])
Return SetError(0, $iResult, $aResult)
EndFunc ;==>_WinGetHandleByPID
Related
It is possible, in AU3, use WinHttp.WinHttpRequest.5.1 with a progress bar? Actually what I need is to know how many MB have already been downloaded.
I need to use "WinHttp.WinHttpRequest.5.1" because I have to use the parameter "Referer" in the header.
Of course it is
#include "WinHttp.au3"
; Download some gif
;~ http://33.media.tumblr.com/dd3ffab90cc338666f192fd86f6a4f8f/tumblr_n0pefhIpss1swyb6ao1_500.gif
; Initialize and get session handle
$hOpen = _WinHttpOpen()
; Get connection handle
$hConnect = _WinHttpConnect($hOpen, "http://33.media.tumblr.com")
; Specify the reguest
$hRequest = _WinHttpOpenRequest($hConnect, Default, "dd3ffab90cc338666f192fd86f6a4f8f/tumblr_n0pefhIpss1swyb6ao1_500.gif")
; Send request
_WinHttpSendRequest($hRequest)
; Wait for the response
_WinHttpReceiveResponse($hRequest)
;~ ConsoleWrite(_WinHttpQueryHeaders($hRequest) & #CRLF)
ProgressOn("Downloading", "In Progress...")
Progress(_WinHttpQueryHeaders($hRequest, $WINHTTP_QUERY_CONTENT_LENGTH))
Local $sData
; Check if there is data available...
If _WinHttpQueryDataAvailable($hRequest) Then
While 1
$sChunk = _WinHttpReadData_Ex($hRequest, Default, Default, Default, Progress)
If #error Then ExitLoop
$sData &= $sChunk
Sleep(20)
WEnd
Else
MsgBox(48, "Error", "Site is experiencing problems (or you).")
EndIf
Sleep(1000)
ProgressOff()
; Close handles
_WinHttpCloseHandle($hRequest)
_WinHttpCloseHandle($hConnect)
_WinHttpCloseHandle($hOpen)
; Do whatever with data, write to some file or whatnot. I'll just print it to console here:
ConsoleWrite($sData & #CRLF)
Local $hFile = FileOpen(#DesktopDir & "\test.gif", 26)
FileWrite($hFile, $sData)
FileClose($hFile)
Func Progress($iSizeAll, $iSizeChunk = 0)
Local Static $iMax, $iCurrentSize
If $iSizeAll Then $iMax = $iSizeAll
$iCurrentSize += $iSizeChunk
Local $iPercent = Round($iCurrentSize / $iMax * 100, 0)
ProgressSet($iPercent, $iPercent & " %")
EndFunc
Func _WinHttpReadData_Ex($hRequest, $iMode = Default, $iNumberOfBytesToRead = Default, $pBuffer = Default, $vFunc = Default)
__WinHttpDefault($iMode, 0)
__WinHttpDefault($iNumberOfBytesToRead, 8192)
__WinHttpDefault($vFunc, 0)
Local $tBuffer, $vOutOnError = ""
If $iMode = 2 Then $vOutOnError = Binary($vOutOnError)
Switch $iMode
Case 1, 2
If $pBuffer And $pBuffer <> Default Then
$tBuffer = DllStructCreate("byte[" & $iNumberOfBytesToRead & "]", $pBuffer)
Else
$tBuffer = DllStructCreate("byte[" & $iNumberOfBytesToRead & "]")
EndIf
Case Else
$iMode = 0
If $pBuffer And $pBuffer <> Default Then
$tBuffer = DllStructCreate("char[" & $iNumberOfBytesToRead & "]", $pBuffer)
Else
$tBuffer = DllStructCreate("char[" & $iNumberOfBytesToRead & "]")
EndIf
EndSwitch
Local $sReadType = "dword*"
If BitAND(_WinHttpQueryOption(_WinHttpQueryOption(_WinHttpQueryOption($hRequest, $WINHTTP_OPTION_PARENT_HANDLE), $WINHTTP_OPTION_PARENT_HANDLE), $WINHTTP_OPTION_CONTEXT_VALUE), $WINHTTP_FLAG_ASYNC) Then $sReadType = "ptr"
Local $aCall = DllCall($hWINHTTPDLL__WINHTTP, "bool", "WinHttpReadData", _
"handle", $hRequest, _
"struct*", $tBuffer, _
"dword", $iNumberOfBytesToRead, _
$sReadType, 0)
If #error Or Not $aCall[0] Then Return SetError(1, 0, "")
If Not $aCall[4] Then Return SetError(-1, 0, $vOutOnError)
If IsFunc($vFunc) Then $vFunc(0, $aCall[4])
If $aCall[4] < $iNumberOfBytesToRead Then
Switch $iMode
Case 0
Return SetExtended($aCall[4], StringLeft(DllStructGetData($tBuffer, 1), $aCall[4]))
Case 1
Return SetExtended($aCall[4], BinaryToString(BinaryMid(DllStructGetData($tBuffer, 1), 1, $aCall[4]), 4))
Case 2
Return SetExtended($aCall[4], BinaryMid(DllStructGetData($tBuffer, 1), 1, $aCall[4]))
EndSwitch
Else
Switch $iMode
Case 0, 2
Return SetExtended($aCall[4], DllStructGetData($tBuffer, 1))
Case 1
Return SetExtended($aCall[4], BinaryToString(DllStructGetData($tBuffer, 1), 4))
EndSwitch
EndIf
EndFunc
You here find the WinHTTP.au3 here: https://github.com/dragana-r/autoit-winhttp/releases.
It is my favorite UDF!
I have comments all around the code to explain you the process.
My AutoIt script compiles but doesn't do what it's supposed to do. Code:
HotKeySet(+"{G}","gather")
While 1
sleep(100)
WEnd
Global $charRunTimeS = 2;
Global $collectKey = "{LWIN}";
Global $vehicleInvKey = "{T}";
Global $charRunTimeMS = $charRunTimeS * 1000
Global $posItemX = 820;
Global $posItem1Y = 300;
Global $posItem2Y = 340;
Global $posItem3Y = 365;
Global $posItem4Y = 397;
Global $posBtnStore = 678;
Global $posItemSelectedY = $posItem4Y
Func gather()
$counter = 0;
While $counter <= 2
Send("{s down}")
Sleep($charRunTimeMS)
Send("{s up}")
$counter1 = 0;
While $counter1 <= 4
Send($collectKey)
Sleep(100)
Send($collectKey)
Sleep(30000)
$counter1 = $counter1 + 1
WEnd
Send("{w down}")
Sleep($charRunTimeMS)
Send("{w up}")
Send($vehicleInvKey)
MouseClick("primary", $posItemX, $posItemSelectedY)
$counter2 = 0;
While $counter2 <= 30
MouseClick($posItemX, $posBtnStore)
$counter2 = $counter2 + 1
WEnd
Send("{ESC}")
$counter = $counter + 1
WEnd
EndFunc
Output from de-bug. First line is when compiling and running, the second line is when I stop the code:
"C:\Program Files (x86)\AutoIt3\SciTE..\autoit3.exe" /ErrorStdOut "C:\Users\RichusX\Desktop\AltisGatherScript.au3"
Process failed to respond; forcing abrupt termination...
Exit code: 1 Time: 14.39
I guess all you need to do is write the call like this:
HotKeySet("G", "gather")
You do not need the +, because of the capital G. If you want to then you have to put it into to "". Have a look at the send function.
I'm in the process of making a small program to tell me on the fly how many employees are currently punched in via AvayaCMS Reporting.
Right now, the way that it is setup is that I have an Avaya script to take a quick report and export it in a CSV that is used by my Autoit script.
In terms of debugging it, I feel like I missing something and need another set of eyes.
launching the Staffing.au3 triggers the CSV script I'm using against the report. Even having the exact same data my message box still reports "0"
#include <Array.au3>
#include <CSV.au3>
$i_AgentCount = AvayaData(#ScriptDir & '\Report.csv', #ScriptDir & '\Name List.csv')
MsgBox(0x40, "", $i_AgentCount)
Func AvayaData($s_ReportSource, $s_NameList)
$av_LiveData = _ParseCSV($s_ReportSource)
If #error Then Return -1
$av_NameList = _ParseCSV($s_NameList)
If #error Then Return -1
Local $i_AgentCount = 0
For $i_RowCnt = 1 To (UBound($av_LiveData, 1) - 1) Step +1
For $i_AgtLst = 1 To (UBound($av_NameList) - 1) Step +1
If StringStripWS($av_LiveData[$i_RowCnt][1], 3) = StringStripWS($av_NameList[$i_AgtLst][0], 3) Then
$i_AgentCount += 1
EndIf
Next
Next
;Return the Agent Count
Return $i_AgentCount
EndFunc
Name List.csv
Agent Name
"Doe, Jane"
"Doe, John"
Report.csv
,Agent Name,Login ID,Extn,AUX Reason,State,Split/Skill,Time,VDN Name
5,"Doe, John",5930001,1000001,7,AUXOUT,999,51:32:00,
2,"Doe, Jane",5930002,1000002,7,AUXOUT,999,52:32:00,
Tested! It works well with the files supplied (copied them and names them as in your script)
please note the followings
_ParseCsv() has been rewritten add parameters like $Dchar as delimeter etc. (see script)
Note how I locate the names in the file (you can easily add feature to extend search but it won't be becessary)
msgboxes are for explanatory purposes; comment them out if not need them anymore
array.au3 is not needed
and the code:
$i_AgentCount = AvayaData(#ScriptDir & '\Report.csv', #ScriptDir & '\Name List.csv')
MsgBox(0x40, "", $i_AgentCount)
Func AvayaData($s_ReportSource, $s_NameList)
$av_LiveData = _ParseCSV($s_ReportSource,",","oops...",True)
If #error Then Return -1
$av_NameList = _ParseCSV($s_NameList,",","oops: 2",True)
If #error Then Return -1
MsgBox(0,default,"$av_NameList (Number of lines) -> " & $av_NameList[0][0])
MsgBox(0,default,"$av_NameList (Number of data in each line) -> " & $av_NameList[0][1])
MsgBox(0,default,"$av_LiveData (Number of lines) -> " & $av_LiveData[0][0])
MsgBox(0,default,"$av_LiveData (Number of data in each line) -> " & $av_LiveData[0][1])
Local $i_AgentCount = 0
for $i = 1 to $av_NameList[0][0] Step 1
For $j= 1 To $av_LiveData[0][0] Step 1
;we can have names from $av_NameList as well from $av_LiveData but in Live Data 2nd abd 3rd values are the names
MsgBox(0,default,$av_NameList[$i][1] & $av_NameList[$i][2] & " <------------> " & $av_LiveData[$j][2] & $av_LiveData[$j][3])
;~ let's compare them if matched with any of the liveData lines
If StringCompare($av_NameList[$i][1] & $av_NameList[$i][2],$av_LiveData[$j][2] & $av_LiveData[$j][3]) == 0 Then
$i_AgentCount += 1
MsgBox(0,default,"Match found: counter: " & $i_AgentCount)
EndIf
Next
Next
;Return the Agent Count
Return $i_AgentCount
EndFunc
Func _ParseCSV($f,$Dchar,$error,$skip)
Local $array[500][500]
Local $line = ""
$i = 0
$file = FileOpen($f,0)
If $file = -1 Then
MsgBox(0, "Error", $error)
Return False
EndIf
;skip 1st line (since it is the header)
If $skip Then $line = FileReadLine($file)
While 1
$i = $i + 1
Local $line = FileReadLine($file)
If #error = -1 Then ExitLoop
;skip 1st line
$row_array = StringSplit($line,$Dchar)
If $i == 1 Then $row_size = UBound($row_array)
If $row_size <> UBound($row_array) Then MsgBox(0, "Error", "Row: " & $i & " has different size ")
$row_size = UBound($row_array)
$array = _arrayAdd_2d($array,$i,$row_array,$row_size)
WEnd
FileClose($file)
$array[0][0] = $i-1 ;stores number of lines
$array[0][1] = $row_size -1 ; stores number of data in a row (data corresponding to index 0 is the number of data in a row actually that's way the -1)
Return $array
EndFunc
Func _arrayAdd_2d($array,$inwhich,$row_array,$row_size)
For $i=1 To $row_size -1 Step 1
$array[$inwhich][$i] = $row_array[$i]
Next
Return $array
EndFunc
#region ;************ Includes ************
#include "csv.au3"
#include <Array.au3>
#endregion ;************ Includes ************
$i_AgentCount = AvayaData(#ScriptDir & '\Report.csv', #ScriptDir & '\Name List.csv')
MsgBox(0x40, "", $i_AgentCount)
Func AvayaData($s_ReportSource, $s_NameList)
Local $i_AgentCount = 0
Local $s = FileRead($s_NameList)
Local $loggedInNames = FileRead($s_ReportSource)
$av_NameList = _ParseCSV($s_NameList)
If #error Then Return -1
;~ _ArrayDisplay($av_NameList)
ConsoleWrite($s & #CRLF)
For $i = 1 To UBound($av_NameList) - 1
ConsoleWrite($i & " " & $av_NameList[$i][0] & #CRLF)
If StringInStr($s, $av_NameList[$i][0]) <> 0 Then
$i_AgentCount += 1
EndIf
Next
Return $i_AgentCount
EndFunc ;==>AvayaData
Func OpenSHK()
global $Loginx = 0, $Loginy = 0, $Playx = 0, $Playy = 0
Run(#ProgramFilesDir & "\Stronghold Kingdoms\StrongholdKingdoms.exe")
WinWaitActive("Stronghold Kingdoms")
If WinExists("Stronghold Kingdoms") Then
SendKeepActive("Stronghold Kingdoms")
Else
WinWait("Stronghold Kingdoms")
SendKeepActive("Stronghold Kingdoms")
EndIf
Sleep(5000)
Send("testphrase")
Local $search = _ImageSearch('pics/LoginButton.bmp', 0, $Loginx, $Loginy, 0)
If $search = 1 Then
MouseMove($Loginx, $Loginy, 20)
MouseClick("left")
Else
Do
$search = _ImageSearch('pics/LoginButton.bmp', 0, $Loginx, $Loginy, 0)
sleep(5000)
Until $search = 1
MouseMove($Loginx, $Loginy, 20)
MouseClick("left")
EndIf
Sleep(5000)
Local $search = _ImageSearch('pics/PlayButton.bmp', 0, $Playx, $Playy, 0)
If $search = 1 Then
MouseMove($Playx, $Playy, 20)
MouseClick("left")
Else
Do
$search = _ImageSearch('pics/PlayButton.bmp', 0, $Playx, $Playy, 0)
sleep(5000)
Until $search = 1
MouseMove($Playx, $Playy, 20)
MouseClick("left")
EndIf
WinWaitActive("Stronghold Kingdoms - World 8")
sleep(10000)
EndFunc
The function works fine, until it reaches line 6. It does not send the test phrase, and I cannot seem to figure out why.
Thanks.
There are many errors in your code:
Run("#ProgramFilesDir\Stronghold Kingdoms\StrongholdKingdoms.exe")
should be Run(#ProgramFilesDir & "\Stronghold Kingdoms\StrongholdKingdoms.exe")
That's why winwaitactive probably gets never passed. Try a loop instead to see if the window exists, rather than if it's active.
If the window exists you can activate it then or use SendKeepActive (I think that's what it's called.)
When I was working with AutoIt and having a similar problem (for the same program :) ), I think I ended up using controlsend, sometimes, and send at other times.
I also ended up going into the handles, and telling autoit to make specific text boxes active.
I have test.csv file need to read all the data using autoit
As TeamKiller said your question is quite vague but here is a sample code that should give you an idea of how to read a CSV file.
#include <GUIConstants.au3>
#include <Array.au3>
#include <File.au3>
#include <String.au3>
Opt("MustDeclareVars", 1)
Global Const $CSVFILE = "C:\Temp\test.csv"
Global Const $DELIM = ";" ;the delimiter in the CSV file
Global $i, $arrContent, $arrLine, $res = 0
$res = _FileReadToArray($CSVFILE, $arrContent)
If $res = 1 Then
For $i = 1 To $arrContent[0]
$arrLine = StringSplit($arrContent[$i], $DELIM)
If IsArray($arrLine) And $arrLine[0]<>0 Then
_ArrayDisplay($arrLine)
; do something with the elements of the line
Else
MsgBox(48, "", "Error splitting line!")
EndIf
Next
Else
MsgBox(48, "", "Error opening file!")
EndIf
return value of _ParseCSV() is 2D array like
$array[1][1] first line first data
$array[1][2] first line second data
$array[3][5] 3rd line 5th data
$array[0][0] gives number of lines
$array[0][1] gives number of data in each line
no need for includes
params:
filename
delimeter
message display if cannot open file
logical true/false to skip the first line of the file
;_ParseCSV("filename",",","message if error happens",true)
Func _ParseCSV($f,$Dchar,$error,$skip)
Local $array[500][500]
Local $line = ""
$i = 0
$file = FileOpen($f,0)
If $file = -1 Then
MsgBox(0, "Error", $error)
Return False
EndIf
;skip 1st line
If $skip Then $line = FileReadLine($file)
While 1
$i = $i + 1
Local $line = FileReadLine($file)
If #error = -1 Then ExitLoop
$row_array = StringSplit($line,$Dchar)
If $i == 1 Then $row_size = UBound($row_array)
If $row_size <> UBound($row_array) Then MsgBox(0, "Error", "Row: " & $i & " has different size ")
$row_size = UBound($row_array)
$array = _arrayAdd_2d($array,$i,$row_array,$row_size)
WEnd
FileClose($file)
$array[0][0] = $i-1 ;stores number of lines
$array[0][1] = $row_size -1 ; stores number of data in a row (data corresponding to index 0 is the number of data in a row actually that's way the -1)
Return $array
EndFunc
Func _arrayAdd_2d($array,$inwhich,$row_array,$row_size)
For $i=1 To $row_size -1 Step 1
$array[$inwhich][$i] = $row_array[$i]
Next
Return $array
EndFunc
As for parsing a CSV file, you are likely better off using a library (called user-defined functions in AutoIt), especially if you e.g. have complex CSVs with quoted strings (commas inside of the "cell"/string) or line breaks, which are hard to handle.
The best I can recommend is CSVSplit.
Basically you have a function _CSVSplit that takes a whole CSV file (content, i.e. string!) and returns you a two-dimensional array:
Local $sCSV = FileRead($sFilePath)
If #error Then ; ....
$aSplitArray = _CSVSplit($sCSV, ",")
You can then do everything you want with this array. Obviously, CSVSplit also provides the "reverse" function for turning an array into a CSV string again, _ArrayToCSV.
Originally posted as an answer here, which I consider a duplicate of this question.