Jump to content

mistersquirrle

Active Members
  • Posts

    406
  • Joined

  • Last visited

  • Days Won

    7

Reputation Activity

  1. Like
    mistersquirrle got a reaction from philpw99 in headless with AutoItX   
    I have encountered some issues with using AutoIt on a work VM to do some Send and MouseClick while my RDP session was disconnected. The main problem is that when you do not have a monitor connected, or a RDP session, you do not have a... resolution? There's is no desktop 'window', things sort of stop existing in the same context as when you have a monitor or RDP session connected. I don't have a good way to describe it.
    Anyways, my solution to this to allow things to still process and work while I wasn't connected to the RDP myself, was to connect the VM to itself through RDP. Yeah, it's weird, and I haven't automated having it connect to itself when no one else is connected. But before I turn off my computer I start a new RDP session on the VM to the VM, which then disconnects my RDP session because someone else (the VM itself) connected. Since it's connected and the RDP connection is able to create a virtual desktop/monitor/resolution, things like MouseClick, Send, and I assume everything else work.
  2. Like
    mistersquirrle got a reaction from ioa747 in Function "Execute" fails to execute string from STDIN in console mode   
    I think similar to 
    Part of the problem is how the 'Console' works in an uncompiled script. You're running it through the AutoIt.exe process, not through SciTE or its own process. You're not inputting into the 'correct' console window, is basically my thought. 
    So, basically, you cannot do what you want unless you compile the script, and do you things from the console window of the direct .exe file. As for why Execute is not working, that's because of CR/LF/CRLF, basically. I tested your code, and some example code built from the help file entry for Execute, and I got it working:
    #include <MsgBoxConstants.au3> #cs Compile this script to "ConsoleRead.exe". Open a command prompt to the directory where ConsoleRead.exe resides. Type the following on the command line: echo Hello! | ConsoleRead.exe When invoked in a console window, the above command echos the text "Hello!" but instead of displaying it, the | tells the console to pipe it to the STDIN stream of the ConsoleRead.exe process. #ce ; MouseClick("main", 436, 451, 1, 10) ; Copy this and try executing that, or whatever you want Example() Func Example() If Not @Compiled Then MsgBox($MB_SYSTEMMODAL, "", "This script must be compiled in order to run the example.") Exit EndIf Local $sOutput While True Sleep(25) $sOutput = ConsoleRead() ;~ If @error Then ExitLoop If $sOutput <> '' Then MsgBox($MB_SYSTEMMODAL, "", "Received: " & @CRLF & 'Type: ' & VarGetType($sOutput) & @CRLF & $sOutput) Execute(StringStripCR(StringStripWS($sOutput, 1 + 2))) ; $STR_STRIPLEADING + $STR_STRIPTRAILING If @error Then MsgBox($MB_SYSTEMMODAL, "", "Execute $sOutput error: " & @CRLF & @CRLF & @error) EndIf EndIf WEnd MsgBox($MB_SYSTEMMODAL, "", "Received: " & @CRLF & @CRLF & $sOutput) EndFunc ;==>Example Give that a shot (compiled) and see if it works for you, it did for me (sending the MouseClick line in there). Keep in mind then that this will only work for single line things.
     
    Edit: Also take a look at https://www.autoitscript.com/autoit3/docs/intro/running.htm, specifically: AutoIt specific command Line Switches
    And keep in mind that to use AutoIt3ExecuteScript  or AutoIt3ExecuteLine, the file needs to be compiled with this flag: 
    #pragma compile(AutoItExecuteAllowed, true)  
  3. Like
    mistersquirrle got a reaction from Musashi in Function In My Include script Not seen - (Moved)   
    Here's something to consider, all of your includes should be at the top of your script, before you call any functions. Also, the order of your includes could matter. I don't think that the example you gave is something that you've tested, because that does work no problem for everyone here (myself included).
    How sure are you that the "missing" function is in fact included in your file? As long as it's there, there shouldn't be a reason why it would fail and not be able to find the file.
    Here's another topic on include file organization: 
    Keep in mind also that even if you include everything into a script, that only means everything will (or should) work from that main script. You still need to make sure that none of your includes have references to things that exist outside of their own files. Otherwise when you include just a single file or two instead of the whole set of them, you can get undefined functions. I would recommend running the "SyntaxCheck Prod" tool in SciTE (Ctrl + F5) on each of your include files to make sure there's nothing missing in the includes itself.
     
  4. Like
    mistersquirrle got a reaction from Musashi in Converting String Into A Variable name(?)   
    If you're on a roll then you're on a roll. Sometimes just completing the task is better than finding the most optimal way. However that being said, you are definitely doing more typing/work than needed for your X1-Y4 pairs. You're providing each corner of a rectangle, even though you only need opposing corners (like top left and bottom right).
    For example:
    ; https://www.autoitscript.com/forum/topic/210615-converting-string-into-a-variable-name/?do=findComment&comment=1521771 #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <array.au3> Global $id = 0 ; active selection Global $aQuad[][] = [ _ ; Provide coordinates in groups, [Top Left] and [Bottom Right] ["X1", "Y1", "X2", "Y2"], _ [223, 223, 325, 325], _ ;1 [750, 425, 850, 525] _ ;26 ] While 1 Global $sInputBoxAnswer = InputBox("Which quadrant to show?", @CRLF & "Number only, 0 - " & UBound($aQuad) - 1, $id + 1) If @error Then Exit $id = Int($sInputBoxAnswer) If $id < 0 Or $id >= UBound($aQuad) Then ConsoleWrite('Invalid number' & @CRLF) ContinueLoop EndIf For $iY = 1 To 3 Step 2 For $iX = 0 To 2 Step 2 MouseMove($aQuad[$id][$iX], $aQuad[$id][$iY], 1) ToolTip($aQuad[$id][$iX] & ", " & $aQuad[$id][$iY], _ $aQuad[$id][$iX] + 20, _ ; offset so we can see the whole tooltip without the mouse in the way $aQuad[$id][$iY], _ 'X' & ($iX + 2) / 2 & ', Y' & ($iY + 1) / 2) Sleep(250) Next Next ;Sleep(350) ToolTip("") WEnd Here, we're only using X1,Y1 and X2,Y2. These points are the Top Left and Bottom Right coordinates, that's all we need to make a rectangle. That'll save you half the typing for coordinates.
    I also simplified the main loop, and swapped having 4 mouse moves to a couple of loops. If you wanted to keep that part expanded though, here's what that would look like:
    MouseMove($aQuad[$id][0], $aQuad[$id][1], 1) ToolTip($aQuad[$id][0] & ", " & $aQuad[$id][1], $aQuad[$id][0], $aQuad[$id][1], "Top left") Sleep(250) MouseMove($aQuad[$id][2], $aQuad[$id][1], 1) ToolTip($aQuad[$id][2] & ", " & $aQuad[$id][1], $aQuad[$id][2], $aQuad[$id][1], "Top right") Sleep(250) MouseMove($aQuad[$id][0], $aQuad[$id][3], 1) ToolTip($aQuad[$id][0] & ", " & $aQuad[$id][3], $aQuad[$id][0], $aQuad[$id][3], "Bottom left") Sleep(250) MouseMove($aQuad[$id][2], $aQuad[$id][3], 1) ToolTip($aQuad[$id][2] & ", " & $aQuad[$id][3], $aQuad[$id][2], $aQuad[$id][3], "Bottom right") Sleep(250) The nice part with not having each one as its own thing is that if you want to change a part of it, instead of changing it 4 places it's only 1.
    Also I noticed that your coordinates are almost a pattern, at least besides the first 1 or 2 points of the pattern. But, would something like this work?
    ; https://www.autoitscript.com/forum/topic/210615-converting-string-into-a-variable-name/?do=findComment&comment=1521771 #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <array.au3> Global $id = 0 ; active selection Global $sInputBoxAnswer Global $aiCoords[2] While 1 $sInputBoxAnswer = InputBox("Which quadrant to show?", @CRLF & "Number only", $id + 1) If @error Then Exit $id = Int($sInputBoxAnswer) If $id <= 0 Then ConsoleWrite('Invalid number' & @CRLF) ContinueLoop EndIf For $iY = 0 To 1 $aiCoords[1] = 225 + (100 * (Floor($id / 10) + $iY)) For $iX = 0 To 1 $aiCoords[0] = 250 + (100 * Mod(($id - 1) + $iX, 10)) MouseMove($aiCoords[0], $aiCoords[1], 1) ToolTip(String($aiCoords[0]) & ", " & String($aiCoords[1]), _ $aiCoords[0] + 20, _ ; offset so we can see the whole tooltip without the mouse in the way $aiCoords[1], _ 'X' & ($iX + 1) & ', Y' & ($iY + 1)) Sleep(250) If $iX = $iY Then ConsoleWrite('id: ' & $id & ' X' & $iX & ',Y' & $iY & ': ' & _ String($aiCoords[0]) & ", " & String($aiCoords[1]) & @CRLF) Next Next ;Sleep(350) ToolTip("") WEnd This assumes that you start at 250 instead of 223, and also hit 350 instead of 335. Everything else just seems to be multiples of 100, with 10 points in X before moving to a new Y and repeating.
    I think I had some other stuff to say, but then took a work meeting and forgot. Let me know if you have questions.
  5. Like
    mistersquirrle got a reaction from mikell in Converting String Into A Variable name(?)   
    If you're on a roll then you're on a roll. Sometimes just completing the task is better than finding the most optimal way. However that being said, you are definitely doing more typing/work than needed for your X1-Y4 pairs. You're providing each corner of a rectangle, even though you only need opposing corners (like top left and bottom right).
    For example:
    ; https://www.autoitscript.com/forum/topic/210615-converting-string-into-a-variable-name/?do=findComment&comment=1521771 #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <array.au3> Global $id = 0 ; active selection Global $aQuad[][] = [ _ ; Provide coordinates in groups, [Top Left] and [Bottom Right] ["X1", "Y1", "X2", "Y2"], _ [223, 223, 325, 325], _ ;1 [750, 425, 850, 525] _ ;26 ] While 1 Global $sInputBoxAnswer = InputBox("Which quadrant to show?", @CRLF & "Number only, 0 - " & UBound($aQuad) - 1, $id + 1) If @error Then Exit $id = Int($sInputBoxAnswer) If $id < 0 Or $id >= UBound($aQuad) Then ConsoleWrite('Invalid number' & @CRLF) ContinueLoop EndIf For $iY = 1 To 3 Step 2 For $iX = 0 To 2 Step 2 MouseMove($aQuad[$id][$iX], $aQuad[$id][$iY], 1) ToolTip($aQuad[$id][$iX] & ", " & $aQuad[$id][$iY], _ $aQuad[$id][$iX] + 20, _ ; offset so we can see the whole tooltip without the mouse in the way $aQuad[$id][$iY], _ 'X' & ($iX + 2) / 2 & ', Y' & ($iY + 1) / 2) Sleep(250) Next Next ;Sleep(350) ToolTip("") WEnd Here, we're only using X1,Y1 and X2,Y2. These points are the Top Left and Bottom Right coordinates, that's all we need to make a rectangle. That'll save you half the typing for coordinates.
    I also simplified the main loop, and swapped having 4 mouse moves to a couple of loops. If you wanted to keep that part expanded though, here's what that would look like:
    MouseMove($aQuad[$id][0], $aQuad[$id][1], 1) ToolTip($aQuad[$id][0] & ", " & $aQuad[$id][1], $aQuad[$id][0], $aQuad[$id][1], "Top left") Sleep(250) MouseMove($aQuad[$id][2], $aQuad[$id][1], 1) ToolTip($aQuad[$id][2] & ", " & $aQuad[$id][1], $aQuad[$id][2], $aQuad[$id][1], "Top right") Sleep(250) MouseMove($aQuad[$id][0], $aQuad[$id][3], 1) ToolTip($aQuad[$id][0] & ", " & $aQuad[$id][3], $aQuad[$id][0], $aQuad[$id][3], "Bottom left") Sleep(250) MouseMove($aQuad[$id][2], $aQuad[$id][3], 1) ToolTip($aQuad[$id][2] & ", " & $aQuad[$id][3], $aQuad[$id][2], $aQuad[$id][3], "Bottom right") Sleep(250) The nice part with not having each one as its own thing is that if you want to change a part of it, instead of changing it 4 places it's only 1.
    Also I noticed that your coordinates are almost a pattern, at least besides the first 1 or 2 points of the pattern. But, would something like this work?
    ; https://www.autoitscript.com/forum/topic/210615-converting-string-into-a-variable-name/?do=findComment&comment=1521771 #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <array.au3> Global $id = 0 ; active selection Global $sInputBoxAnswer Global $aiCoords[2] While 1 $sInputBoxAnswer = InputBox("Which quadrant to show?", @CRLF & "Number only", $id + 1) If @error Then Exit $id = Int($sInputBoxAnswer) If $id <= 0 Then ConsoleWrite('Invalid number' & @CRLF) ContinueLoop EndIf For $iY = 0 To 1 $aiCoords[1] = 225 + (100 * (Floor($id / 10) + $iY)) For $iX = 0 To 1 $aiCoords[0] = 250 + (100 * Mod(($id - 1) + $iX, 10)) MouseMove($aiCoords[0], $aiCoords[1], 1) ToolTip(String($aiCoords[0]) & ", " & String($aiCoords[1]), _ $aiCoords[0] + 20, _ ; offset so we can see the whole tooltip without the mouse in the way $aiCoords[1], _ 'X' & ($iX + 1) & ', Y' & ($iY + 1)) Sleep(250) If $iX = $iY Then ConsoleWrite('id: ' & $id & ' X' & $iX & ',Y' & $iY & ': ' & _ String($aiCoords[0]) & ", " & String($aiCoords[1]) & @CRLF) Next Next ;Sleep(350) ToolTip("") WEnd This assumes that you start at 250 instead of 223, and also hit 350 instead of 335. Everything else just seems to be multiples of 100, with 10 points in X before moving to a new Y and repeating.
    I think I had some other stuff to say, but then took a work meeting and forgot. Let me know if you have questions.
  6. Thanks
    mistersquirrle got a reaction from JustCallMeAlec in Converting String Into A Variable name(?)   
    If you're on a roll then you're on a roll. Sometimes just completing the task is better than finding the most optimal way. However that being said, you are definitely doing more typing/work than needed for your X1-Y4 pairs. You're providing each corner of a rectangle, even though you only need opposing corners (like top left and bottom right).
    For example:
    ; https://www.autoitscript.com/forum/topic/210615-converting-string-into-a-variable-name/?do=findComment&comment=1521771 #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <array.au3> Global $id = 0 ; active selection Global $aQuad[][] = [ _ ; Provide coordinates in groups, [Top Left] and [Bottom Right] ["X1", "Y1", "X2", "Y2"], _ [223, 223, 325, 325], _ ;1 [750, 425, 850, 525] _ ;26 ] While 1 Global $sInputBoxAnswer = InputBox("Which quadrant to show?", @CRLF & "Number only, 0 - " & UBound($aQuad) - 1, $id + 1) If @error Then Exit $id = Int($sInputBoxAnswer) If $id < 0 Or $id >= UBound($aQuad) Then ConsoleWrite('Invalid number' & @CRLF) ContinueLoop EndIf For $iY = 1 To 3 Step 2 For $iX = 0 To 2 Step 2 MouseMove($aQuad[$id][$iX], $aQuad[$id][$iY], 1) ToolTip($aQuad[$id][$iX] & ", " & $aQuad[$id][$iY], _ $aQuad[$id][$iX] + 20, _ ; offset so we can see the whole tooltip without the mouse in the way $aQuad[$id][$iY], _ 'X' & ($iX + 2) / 2 & ', Y' & ($iY + 1) / 2) Sleep(250) Next Next ;Sleep(350) ToolTip("") WEnd Here, we're only using X1,Y1 and X2,Y2. These points are the Top Left and Bottom Right coordinates, that's all we need to make a rectangle. That'll save you half the typing for coordinates.
    I also simplified the main loop, and swapped having 4 mouse moves to a couple of loops. If you wanted to keep that part expanded though, here's what that would look like:
    MouseMove($aQuad[$id][0], $aQuad[$id][1], 1) ToolTip($aQuad[$id][0] & ", " & $aQuad[$id][1], $aQuad[$id][0], $aQuad[$id][1], "Top left") Sleep(250) MouseMove($aQuad[$id][2], $aQuad[$id][1], 1) ToolTip($aQuad[$id][2] & ", " & $aQuad[$id][1], $aQuad[$id][2], $aQuad[$id][1], "Top right") Sleep(250) MouseMove($aQuad[$id][0], $aQuad[$id][3], 1) ToolTip($aQuad[$id][0] & ", " & $aQuad[$id][3], $aQuad[$id][0], $aQuad[$id][3], "Bottom left") Sleep(250) MouseMove($aQuad[$id][2], $aQuad[$id][3], 1) ToolTip($aQuad[$id][2] & ", " & $aQuad[$id][3], $aQuad[$id][2], $aQuad[$id][3], "Bottom right") Sleep(250) The nice part with not having each one as its own thing is that if you want to change a part of it, instead of changing it 4 places it's only 1.
    Also I noticed that your coordinates are almost a pattern, at least besides the first 1 or 2 points of the pattern. But, would something like this work?
    ; https://www.autoitscript.com/forum/topic/210615-converting-string-into-a-variable-name/?do=findComment&comment=1521771 #AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <array.au3> Global $id = 0 ; active selection Global $sInputBoxAnswer Global $aiCoords[2] While 1 $sInputBoxAnswer = InputBox("Which quadrant to show?", @CRLF & "Number only", $id + 1) If @error Then Exit $id = Int($sInputBoxAnswer) If $id <= 0 Then ConsoleWrite('Invalid number' & @CRLF) ContinueLoop EndIf For $iY = 0 To 1 $aiCoords[1] = 225 + (100 * (Floor($id / 10) + $iY)) For $iX = 0 To 1 $aiCoords[0] = 250 + (100 * Mod(($id - 1) + $iX, 10)) MouseMove($aiCoords[0], $aiCoords[1], 1) ToolTip(String($aiCoords[0]) & ", " & String($aiCoords[1]), _ $aiCoords[0] + 20, _ ; offset so we can see the whole tooltip without the mouse in the way $aiCoords[1], _ 'X' & ($iX + 1) & ', Y' & ($iY + 1)) Sleep(250) If $iX = $iY Then ConsoleWrite('id: ' & $id & ' X' & $iX & ',Y' & $iY & ': ' & _ String($aiCoords[0]) & ", " & String($aiCoords[1]) & @CRLF) Next Next ;Sleep(350) ToolTip("") WEnd This assumes that you start at 250 instead of 223, and also hit 350 instead of 335. Everything else just seems to be multiples of 100, with 10 points in X before moving to a new Y and repeating.
    I think I had some other stuff to say, but then took a work meeting and forgot. Let me know if you have questions.
  7. Like
    mistersquirrle got a reaction from argumentum in Condition question   
    Just because I've had the same question and tested this a bit myself, here's results from a test that I ran in 2018:

    From this, Switch was always the fastest, and if you can, you should set/keep OnEventMode off. Things depend though, and you may not be able to always use Switch, or the different logic needed to get a specific way working may introduce additional slowdowns
    Edit: Just to be clear, the OnEventMode stuff doesn't have any direct connection/impact with Select/Switch/If, it's just something else that I was testing at the same time. In general things are a bit slower with OnEventMode, not just Select/Switch/If
  8. Thanks
    mistersquirrle got a reaction from dtormentedsoul in AutoIT oddly not taking argument on couple of my PCs, but is working on my other one. Exact same code.   
    To add some more information to what @argumentum is saying, check out: https://superuser.com/questions/1456692/how-do-i-set-advance-file-association-in-windows-10-while-passing-app-parameter
    You may need to setup file associations again, or look into the registery for the au3 association and edit it to include the "%1"
    Alternatively in SciTE you can set command line params with Shift + F8 for scripts run from SciTE directly. Or compile to .exe and test with that instead of the .au3 file.
  9. Like
    mistersquirrle got a reaction from _Func in Problem with Number function   
    Here's something to keep in mind regarding data types and comparing them (or even checking if they are a specific type): https://www.autoitscript.com/autoit3/docs/intro/lang_operators.htm#:~:text=Comparing different datatypes
    Another thing to look at is: https://www.autoitscript.com/autoit3/docs/functions/VarGetType.htm
    Maybe not entirely useful here, but it's along the same lines and is important to keep in mind.
  10. Like
    mistersquirrle got a reaction from MichaelCrawley in Always on top feature   
    Another option if it's a GUI that you're creating is to use the ExStyle for $WS_EX_TOPMOST:
    #include <WindowsConstants.au3> #include <GUIConstants.au3> Global $hGui = GUICreate('Au3Gui', 200, 100, -1, -1, -1, $WS_EX_TOPMOST) GUISetState(@SW_SHOW, $hGui) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE GUIDelete($hGui) Exit EndSwitch WEnd  
  11. Thanks
    mistersquirrle got a reaction from Jemboy in Find out CPU (used) Time of processes.   
    Well I thought that it wasn't too hard, however it appears that on my system the normal function of _WinAPI_GetProcessTimes doesn't cut it. I needed to open the process myself (likely with debug enabled) to reliably get CPU time information. Check out this script:
     
    ;~ #RequireAdmin ;~ #AutoIt3Wrapper_UseX64=y #include <WinAPI.au3> #include <ProcessConstants.au3> Global $iNanoSecondsToMilliSeconds = 10000 Global $sProcessName = 'explorer.exe' Global $iProcessId = ProcessExists($sProcessName) If $iProcessId = 0 Or @error Then ConsoleWrite('Process does not exist, or error: ' & @error & @CRLF) Exit EndIf ;~ Global $aProcessTimes = _WinAPI_GetProcessTimes() Global $ghProcess = _WinAPI_OpenProcess($PROCESS_QUERY_LIMITED_INFORMATION, 0, $iProcessId, True) Global $aProcessTimes = __WinAPI_GetProcessTimes($ghProcess) If @error Then ConsoleWrite('Unable to get process times: ' & @error & ', ' & _WinAPI_GetLastError() & ', Msg: ' & _WinAPI_GetLastErrorMessage() & @CRLF) Exit EndIf ;~ For $i = 0 To UBound($aProcessTimes) - 1 ;~ ConsoleWrite('Index: ' & $i & ', type: ' & VarGetType($aProcessTimes[$i]) & ', string data: ' & String($aProcessTimes[$i]) & ', int data: ' & Int($aProcessTimes[$i]) & @CRLF) ;~ Next ConsoleWrite('Process ID: ' & $iProcessId & ', name: ' & $sProcessName & ' times: ' & @CRLF) ConsoleWrite(@TAB & 'Kernel mode: ' & __MillisecondToTimestamp(($aProcessTimes[1] / $iNanoSecondsToMilliSeconds)) & ' (' & $aProcessTimes[1] & ')' & @CRLF) ConsoleWrite(@TAB & ' User mode: ' & __MillisecondToTimestamp(($aProcessTimes[2] / $iNanoSecondsToMilliSeconds)) & ' (' & $aProcessTimes[2] & ')' & @CRLF) ConsoleWrite(@TAB & ' Total: ' & __MillisecondToTimestamp((($aProcessTimes[1] + $aProcessTimes[2]) / $iNanoSecondsToMilliSeconds)) & @CRLF) Exit Func __MillisecondToTimestamp($iMs, $bSeconds = False, $bColonSeparator = True) Local $sTimestamp If $bSeconds Then $iMs *= 1000 $iMs = Int($iMs, 0) ; Auto Int ; Convert the milliseconds to days, hours, minutes, and seconds $iDays = (($iMs >= 86400000) ? Int($iMs / 86400000) : 0) $iHours = Int(Mod($iMs, 86400000) / 3600000) $iMinutes = Int(Mod($iMs, 3600000) / 60000) $iSeconds = Int(Mod($iMs, 60000) / 1000) ; Format the timestamp as [DD ]hh:mm:ss.zzz ; Not using StringFormat here because it's considerably slower when you do it 10K+ times, so probably doesn't matter at all for this $sTimestamp = _ ($iDays > 0 ? String($iDays) & (($bColonSeparator) ? ' ' : 'd') : '') & _ StringRight('0' & String($iHours), 2) & (($bColonSeparator) ? ':' : 'h') & _ StringRight('0' & String($iMinutes), 2) & (($bColonSeparator) ? ':' : 'm') & _ StringRight('0' & String($iSeconds), 2) & _ ((Not $bSeconds) ? _ (($bColonSeparator) ? '.' : 's') & StringRight('00' & String($iMs), 3) & (($bColonSeparator) ? '' : 'ms') : _ (($bColonSeparator) ? '' : 's')) Return $sTimestamp EndFunc ;==>__MillisecondToTimestamp Func __WinAPI_GetProcessTimes($hProcess) ;~ If Not $iPID Then $iPID = @AutoItPID ;~ Local $hProcess = DllCall('kernel32.dll', 'handle', 'OpenProcess', 'dword', ((_WinAPI_GetVersion() < 6.0) ? 0x00000400 : 0x00001000), _ ;~ 'bool', 0, 'dword', $iPID) ;~ If @error Or Not $hProcess[0] Then Return SetError(@error + 20, @extended, 0) Local $tFILETIME = DllStructCreate($tagFILETIME) Local $aCall = DllCall('kernel32.dll', 'bool', 'GetProcessTimes', 'handle', $hProcess, 'struct*', $tFILETIME, 'uint64*', 0, _ 'uint64*', 0, 'uint64*', 0) If __CheckErrorCloseHandle($aCall, $hProcess) Then Return SetError(@error, @extended, 0) Local $aRet[3] $aRet[0] = $tFILETIME $aRet[1] = $aCall[4] $aRet[2] = $aCall[5] Return $aRet EndFunc ;==>__WinAPI_GetProcessTimes It did require a bit of tweaking, as since I mentioned using the default UDF function wasn't working on my system, with or without running as admin.
    Here's the output for explorer.exe:
    Process ID: 29536, name: explorer.exe times: Kernel mode: 01:10:35.937 (42359375000) User mode: 00:17:03.328 (10233281250) Total: 01:27:39.265  
    Sidenote, I am planning on releasing a UDF that makes getting some process information like CPU time very easy and fast. I'm not sure when I'm going to post it, but keep an eye out if interested.
  12. Like
    mistersquirrle reacted to TheXman in Find out CPU (used) Time of processes.   
    For what it's worth, I tend to agree with @AndyG.  Identifying and fixing the root cause of an issue is almost always better than time spent patching or working around the issue.  If you fix (or at least mitigate) the issue, then you hopefully don't have to waste time dealing with it again and again or risk it causing additional problems.
    I have found WMI much more reliable in getting process info than some of the WinAPI UDF's that use Win32 API's.  I haven't dug into why, but when using the WinAPI UDF's, WMI returns some information that the WinAPI UDF's do not.
    Here's a quick script that displays selected process info (including CPU time) for all running processes:
    #AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d #include <Constants.au3> #include <WinAPILocale.au3> #include <Array.au3> list_process_info() ;========================================================================== Func list_process_info() ;========================================================================== Enum $PROCESS_PID, $PROCESS_NAME, $PROCESS_EXE_PATH, $PROCESS_CPU_TIME, $PROCESS_COLS Local $aProcesses[0][$PROCESS_COLS] Local $oComError = ObjEvent("AutoIt.Error", "com_error_handler"), _ $oProcesses = "" Local $sTotalCpuTime = "" With ObjGet("winmgmts:") ;Get list of currently running processes $oProcesses = .ExecQuery("SELECT Handle, Name, ExecutablePath, KernelModeTime, UserModeTime FROM Win32_Process") ;If no processes found, then return with message If $oProcesses.Count = 0 Then Return MsgBox($MB_ICONWARNING, "Warning", "No processes found.") If @error Then Return MsgBox($MB_ICONERROR, "WMI ExecQuery Error", $oComError.Description) ;For each process For $oProcess in $oProcesses With $oProcess ;Calculate total cpu time duration and convert to hh:mm:ss $sTotalCpuTime = _WinAPI_GetDurationFormat($LOCALE_USER_DEFAULT, .KernelModeTime + .UserModeTime, "hh:mm:ss") ;Add process info to the array _ArrayAdd($aProcesses, .Handle & "|" & .Name & "|" & .ExecutablePath & "|" & $sTotalCpuTime) EndWith Next EndWith ;Display process info _ArraySort($aProcesses, 1, 0, 0, $PROCESS_CPU_TIME) ;Sort by cpu time in descending order _ArrayDisplay($aProcesses, "List of processes", "", 0, Default, "PID|NAME|PATH|CPU TIME") EndFunc ;========================================================================== Func com_error_handler($oError) ;========================================================================== #forceref $oError Return ; Return so @error can be trapped by the calling function EndFunc Resulting array:

     
  13. Like
    mistersquirrle got a reaction from TheXman in Find out CPU (used) Time of processes.   
    Well I thought that it wasn't too hard, however it appears that on my system the normal function of _WinAPI_GetProcessTimes doesn't cut it. I needed to open the process myself (likely with debug enabled) to reliably get CPU time information. Check out this script:
     
    ;~ #RequireAdmin ;~ #AutoIt3Wrapper_UseX64=y #include <WinAPI.au3> #include <ProcessConstants.au3> Global $iNanoSecondsToMilliSeconds = 10000 Global $sProcessName = 'explorer.exe' Global $iProcessId = ProcessExists($sProcessName) If $iProcessId = 0 Or @error Then ConsoleWrite('Process does not exist, or error: ' & @error & @CRLF) Exit EndIf ;~ Global $aProcessTimes = _WinAPI_GetProcessTimes() Global $ghProcess = _WinAPI_OpenProcess($PROCESS_QUERY_LIMITED_INFORMATION, 0, $iProcessId, True) Global $aProcessTimes = __WinAPI_GetProcessTimes($ghProcess) If @error Then ConsoleWrite('Unable to get process times: ' & @error & ', ' & _WinAPI_GetLastError() & ', Msg: ' & _WinAPI_GetLastErrorMessage() & @CRLF) Exit EndIf ;~ For $i = 0 To UBound($aProcessTimes) - 1 ;~ ConsoleWrite('Index: ' & $i & ', type: ' & VarGetType($aProcessTimes[$i]) & ', string data: ' & String($aProcessTimes[$i]) & ', int data: ' & Int($aProcessTimes[$i]) & @CRLF) ;~ Next ConsoleWrite('Process ID: ' & $iProcessId & ', name: ' & $sProcessName & ' times: ' & @CRLF) ConsoleWrite(@TAB & 'Kernel mode: ' & __MillisecondToTimestamp(($aProcessTimes[1] / $iNanoSecondsToMilliSeconds)) & ' (' & $aProcessTimes[1] & ')' & @CRLF) ConsoleWrite(@TAB & ' User mode: ' & __MillisecondToTimestamp(($aProcessTimes[2] / $iNanoSecondsToMilliSeconds)) & ' (' & $aProcessTimes[2] & ')' & @CRLF) ConsoleWrite(@TAB & ' Total: ' & __MillisecondToTimestamp((($aProcessTimes[1] + $aProcessTimes[2]) / $iNanoSecondsToMilliSeconds)) & @CRLF) Exit Func __MillisecondToTimestamp($iMs, $bSeconds = False, $bColonSeparator = True) Local $sTimestamp If $bSeconds Then $iMs *= 1000 $iMs = Int($iMs, 0) ; Auto Int ; Convert the milliseconds to days, hours, minutes, and seconds $iDays = (($iMs >= 86400000) ? Int($iMs / 86400000) : 0) $iHours = Int(Mod($iMs, 86400000) / 3600000) $iMinutes = Int(Mod($iMs, 3600000) / 60000) $iSeconds = Int(Mod($iMs, 60000) / 1000) ; Format the timestamp as [DD ]hh:mm:ss.zzz ; Not using StringFormat here because it's considerably slower when you do it 10K+ times, so probably doesn't matter at all for this $sTimestamp = _ ($iDays > 0 ? String($iDays) & (($bColonSeparator) ? ' ' : 'd') : '') & _ StringRight('0' & String($iHours), 2) & (($bColonSeparator) ? ':' : 'h') & _ StringRight('0' & String($iMinutes), 2) & (($bColonSeparator) ? ':' : 'm') & _ StringRight('0' & String($iSeconds), 2) & _ ((Not $bSeconds) ? _ (($bColonSeparator) ? '.' : 's') & StringRight('00' & String($iMs), 3) & (($bColonSeparator) ? '' : 'ms') : _ (($bColonSeparator) ? '' : 's')) Return $sTimestamp EndFunc ;==>__MillisecondToTimestamp Func __WinAPI_GetProcessTimes($hProcess) ;~ If Not $iPID Then $iPID = @AutoItPID ;~ Local $hProcess = DllCall('kernel32.dll', 'handle', 'OpenProcess', 'dword', ((_WinAPI_GetVersion() < 6.0) ? 0x00000400 : 0x00001000), _ ;~ 'bool', 0, 'dword', $iPID) ;~ If @error Or Not $hProcess[0] Then Return SetError(@error + 20, @extended, 0) Local $tFILETIME = DllStructCreate($tagFILETIME) Local $aCall = DllCall('kernel32.dll', 'bool', 'GetProcessTimes', 'handle', $hProcess, 'struct*', $tFILETIME, 'uint64*', 0, _ 'uint64*', 0, 'uint64*', 0) If __CheckErrorCloseHandle($aCall, $hProcess) Then Return SetError(@error, @extended, 0) Local $aRet[3] $aRet[0] = $tFILETIME $aRet[1] = $aCall[4] $aRet[2] = $aCall[5] Return $aRet EndFunc ;==>__WinAPI_GetProcessTimes It did require a bit of tweaking, as since I mentioned using the default UDF function wasn't working on my system, with or without running as admin.
    Here's the output for explorer.exe:
    Process ID: 29536, name: explorer.exe times: Kernel mode: 01:10:35.937 (42359375000) User mode: 00:17:03.328 (10233281250) Total: 01:27:39.265  
    Sidenote, I am planning on releasing a UDF that makes getting some process information like CPU time very easy and fast. I'm not sure when I'm going to post it, but keep an eye out if interested.
  14. Like
    mistersquirrle got a reaction from ipc1234 in WinWaitActive behavior inconsistent on different servers?   
    Keep in mind that if these are headless servers, you may be running into limitations with Win* actions because the windows don't "really" exist, check out: https://www.autoitscript.com/wiki/FAQ#Why_doesn.27t_my_script_work_on_a_locked_workstation.3F
    For this use-case locked and headless (as in no remotely connected session with a monitor, or monitor connected to the system) are the same.
    Otherwise, there's an issue with your WinWaitActive, where you're using the wrong parameters:
    WinWaitActive("CHARON Launcher", 5) Is wrong, and it should be:
    WinWaitActive("CHARON Launcher", "", 5) Because you're saying that the window must have the "Text" of "5":
    WinWaitActive ( "title" [, "text" [, timeout = 0]] ) That's probably why your other WinWaitActive works better, you have the parameters in the correct order there.
  15. Like
    mistersquirrle got a reaction from Guy_ in Can an AutoIt.exe running as Admin start another program "normally"?   
    I believe that this works because by design explorer.exe cannot run with elevated permissions, so you're now launching the program through a non-elevated process. I'm sure that there is some official documentation on why, but I can't really find it. It's just something that I've seen mentioned. There's no credentials or anything, and you'd get the same thing if you started a different AutoIt program without administration and told it to launch another process.
    This was one of the suggestions in the linked thread as well, have a script that starts as admin, and one as non-admin, then use some type of IPC or control to tell one of the scripts to launch another program. explorer.exe is just a convenient way to start up something else, and you don't need a shortcut to do it. You can use the full path to the file as well.
  16. Like
    mistersquirrle got a reaction from Danp2 in Assign a window handle value to an application   
    That is true, the handle will be different. So you're saying that you need to use AutoIt to get the window handle for another program and feed that window handle back into itself? Why can't this program get its OWN window handle???
    Please, if you want more help, tell us more about what you're looking to do.
    What is the program that you're trying to pass the window handle to. Why does it need it. Why can't it manage or get its own window handle. What are you trying to do. Show us your current code. Screenshots. The XML. Something.
  17. Like
    mistersquirrle reacted to rsn in New to AutoIt   
    Task Schedule is fairly robust and running bat and cmd files from it is pretty straight forward.
    Coder or not (I'm not either but I stumble along well enough), AutoIt is easy to learn and the community here is welcoming and helpful. Try a few lines like what @mistersquirrle advised and see how you like it. Post it here and the community will help you improve it.
  18. Like
    mistersquirrle got a reaction from ioa747 in Know when the welcome screen disappears   
    Nice, @ioa747. There's another enhancement that could be done, but I didn't include it as when I tested it didn't give me any other results that I saw to be useful. It would be something like this:
    #include <WinAPIProc.au3> Global $hWnd, $PID, $hPrevWnd = -1 Global $aWindows Global $sMsg = '' Global $iPidTemp ; I'm not sure what the purpose of this is ;~ HotKeySet("{END}", "_Sleep") Sleep(1000) While 1 Sleep(250) $hWnd = WinGetHandle('[ACTIVE]') If $hPrevWnd = $hWnd Then ContinueLoop $hPrevWnd = $hWnd ConsoleWrite("--------------------------------------------------------------------------------" & @CRLF) ConsoleWrite("$hWnd:" & String($hWnd) & @CRLF) ConsoleWrite("WinTitle:" & WinGetTitle($hWnd) & @CRLF) $PID = WinGetProcess($hWnd) ConsoleWrite("PID:" & $PID & @CRLF) ConsoleWrite("PID FileName:" & _WinAPI_GetProcessFileName($PID) & @CRLF) $aWindows = WinList() $sMsg = '' For $iWindow = 1 To $aWindows[0][0] ; If $aWindows[$iWindow][0] = 'Default IME' Then ContinueLoop ; I think that these can be safely skipped $iPidTemp = WinGetProcess($aWindows[$iWindow][1]) If $iPidTemp = $PID And $aWindows[$iWindow][1] <> $hWnd Then $sMsg &= @TAB & "$hWnd:" & String($aWindows[$iWindow][1]) & @CRLF $sMsg &= @TAB & "WinTitle:" & String($aWindows[$iWindow][0]) & @CRLF EndIf Next If $sMsg <> '' Then ConsoleWrite('Additional windows: ' & @CRLF & $sMsg) EndIf WEnd ;~ Func _Sleep() ;~ Send("#1") ;~ EndFunc It didn't add anything for the blank handles or for "Windows Default Lock Screen", and for "UnlockingWindow" it's related to explorer.exe so it also listed all or most other open windows on the system.
  19. Like
    mistersquirrle got a reaction from Lepes in Mouseclick/MouseDown and MouseUp Speed question   
    @Lepes I don't think that this is a good method for measuring time with precision, at least over native AutoIt function. I did a quick test comparing that linked function vs just TimerInit and TimerDiff:
    Func _MicroSeconds() Local Static $nFreq = _WinAPI_QueryPerformanceFrequency() Local $a = _WinAPI_QueryPerformanceCounter() Local $b = _WinAPI_QueryPerformanceCounter() Return (($b - $a) / $nFreq) * 1000000 EndFunc ;==>_MicroSeconds Func _TimerDiff() Local $hTimer = TimerInit() Local $nOutput = TimerDiff($hTimer) * 1000 Return $nOutput EndFunc ;==>_TimerDiff And the speed output:
    2023-05-01 09.54.18.626: _MicroSeconds: 13.5 2023-05-01 09.54.18.627: _TimerDiff: 3.2 [================== Run progress, 100,000 times * 2 functions =================] +———————————————+—————————————————+———————————————+——————————————+—————————————+ | Function Name | Time Taken (ms) | Avg Time (ms) | Std Dev (ms) | Faster By % | +———————————————+—————————————————+———————————————+——————————————+—————————————+ | _MicroSeconds | 3288.67 | 0.0329 | 0.0170 | 0.00 | +| _TimerDiff | 396.91 | 0.0040 | 0.0082 | 87.93 | +———————————————+—————————————————+———————————————+——————————————+—————————————+ As you can see _MicroSeconds gave me 13.5us, _TimerDiff 3.2us, and comparing them TimerInit() and TimerDiff() are 87% faster. It can't measure as low as the native functions since they run so much faster.
    It's likely/possible that TimerInit uses QueryPerformanceCounter or GetTickCount internally anyway, and its internal method of calling these is just a lot faster than a DLL call.
    Also we're not looking at trying to measure sub-millisecond precision here, and even if _WinAPI_QueryPerformanceCounter was as fast/faster, I think it's still a bit simpler to use TimerInit/TimerDiff.
  20. Like
    mistersquirrle got a reaction from Dsmoeg999 in Count the number of times the highest number is repeated.   
    @Nine's is the solution that I would do as well, as it's the simplest and I would assume fastest. I was curious though how the suggestions here stacked up, so I did some tests.
    _Occurance_Max_Find = @RTFC _Occurance_Counter = @Nine _Occurance_Sort_Count = @Alecsis1 I did make a change to Alexsis1's solution to exit the for loop when $array[$i] <> $maxvalue, since it's sorted, exits a bit sooner
    When using a 10 row array:
    [====================== Run progress, 10,000 times * 3 functions ======================] +———————————————————————+—————————————————+———————————————+——————————————+—————————————+ | Function Name | Time Taken (ms) | Avg Time (ms) | Std Dev (ms) | Faster By % | +———————————————————————+—————————————————+———————————————+——————————————+—————————————+ | _Occurance_Max_Find | 4074.57 | 0.4075 | 0.0849 | 0.00 | +| _Occurance_Counter | 185.19 | 0.0185 | 0.0086 | 95.46 | | _Occurance_Sort_Count | 893.57 | 0.0894 | 0.0313 | 78.07 | +———————————————————————+—————————————————+———————————————+——————————————+—————————————+ When increasing the size to 100:
    [====================== Run progress, 10,000 times * 3 functions ======================] +———————————————————————+—————————————————+———————————————+——————————————+—————————————+ | Function Name | Time Taken (ms) | Avg Time (ms) | Std Dev (ms) | Faster By % | +———————————————————————+—————————————————+———————————————+——————————————+—————————————+ | _Occurance_Max_Find | 8702.17 | 0.8702 | 0.1885 | 30.33 | +| _Occurance_Counter | 1213.34 | 0.1213 | 0.0436 | 90.29 | | _Occurance_Sort_Count | 12490.12 | 1.2490 | 0.2485 | 0.00 | +———————————————————————+—————————————————+———————————————+——————————————+—————————————+ And then 10,000:
    [======================= Run progress, 100 times * 3 functions ========================] +———————————————————————+—————————————————+———————————————+——————————————+—————————————+ | Function Name | Time Taken (ms) | Avg Time (ms) | Std Dev (ms) | Faster By % | +———————————————————————+—————————————————+———————————————+——————————————+—————————————+ | _Occurance_Max_Find | 5833.96 | 58.3396 | 4.6752 | 72.94 | +| _Occurance_Counter | 1181.70 | 11.8170 | 1.2320 | 94.52 | | _Occurance_Sort_Count | 21559.50 | 215.5950 | 9.1349 | 0.00 | +———————————————————————+—————————————————+———————————————+——————————————+—————————————+ It's interesting that Sorting is a lot faster when the array size is smaller, but it quickly loses speed. It switches somewhere around ~50-60 indexes, though the data also likely affects it quite a bit.
     
     
  21. Like
    mistersquirrle got a reaction from argumentum in Sqlite remplace INI functions need optimization.   
    Keep in mind the overhead with SQLite calls from AutoIt. You're calling the DLL to do stuff in SQL, get data back and do something with it. It's a lot easier to read an ini file. Here's your posted version comparison:
    [================= Run progress, 10,000 times * 2 functions ===================] +———————————————+—————————————————+———————————————+——————————————+—————————————+ | Function Name | Time Taken (ms) | Avg Time (ms) | Std Dev (ms) | Faster By % | +———————————————+—————————————————+———————————————+——————————————+—————————————+ +| IniRead | 681.45 | 0.0681 | 0.0180 | 94.97 | | _DbRead_ | 13559.59 | 1.3560 | 0.2351 | 0.00 | +———————————————+—————————————————+———————————————+——————————————+—————————————+ And with @argumentum's suggestion of only doing [StartUp and Shutdown], [Open and Close] once:
    [================= Run progress, 10,000 times * 2 functions ===================] +———————————————+—————————————————+———————————————+——————————————+—————————————+ | Function Name | Time Taken (ms) | Avg Time (ms) | Std Dev (ms) | Faster By % | +———————————————+—————————————————+———————————————+——————————————+—————————————+ +| IniRead | 760.12 | 0.0760 | 0.0265 | 87.07 | | _DbRead_2 | 5878.42 | 0.5878 | 0.1161 | 0.00 | +———————————————+—————————————————+———————————————+——————————————+—————————————+ So, if all you're after is a couple of basic configuration options, I'd recommend sticking with a .ini file. If they're options that don't need to be constantly written/read, SQLite can work fine for getting options once at the start of the script, though you should probably create a function to get a whole 'section' of values at once, instead of one by one.
  22. Like
    mistersquirrle reacted to TheXman in Disable GUI in Taskbar and ALT+TAB dialog   
    By setting the form's parent to AutoIt's hidden window, it will not be shown in the taskbar.
    #include <GUIConstants.au3> Global $ghParentForm = WinGetHandle(AutoItWinGetTitle()) ;Get handle to AutoIt's hidden window Global $frmMain = GUICreate("Example Form (Pres ESC to Close)", 500, 300, -1, -1, -1, -1, $ghParentForm) GUISetState(@SW_SHOW, $frmMain) WinSetOnTop($frmMain, "", 1) Do Until GUIGetMsg() = $GUI_EVENT_CLOSE  
  23. Thanks
    mistersquirrle got a reaction from rsn in Verify Azure membership   
    You only need it in a while loop if the process is running and you want/need to get data while it's running. Or if you wanted to do something else in the loop while it's running. In @argumentums example and mine, ProcessWaitClose is used. So it waits until the output is done, then gets it all at once. If it was a process that ran for 10 minutes and you wanted status updates or get the output while it's running, then yes, use StdoutRead in a loop to get data as it's printed.
    These are the same:
    And:
    #AutoIt3Wrapper_UseX64=n ; running x86 #include <WinAPIFiles.au3> _WinAPI_Wow64EnableWow64FsRedirection(False) ; this does it =) ; ------ your code from the first post -------- #include <Constants.au3> Local $foo = Run(@WindowsDir & "\system32\dsregcmd.exe /status", @TempDir, @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) Local $sOutput While ProcessExists($foo) Sleep(10) $sOutput &= StdoutRead($foo) If @error Then ExitLoop EndIf WEnd $sOutput &= StdoutRead($foo) MsgBox(0,"",$sOutput) Obviously argumentum's is shorter and bit cleaner, however if it wasn't a process that ends in under a second, you'd probably want to go with the loop method so you can get status updates and whatnot.
  24. Like
    mistersquirrle got a reaction from Musashi in Verify Azure membership   
    I was testing this out and was just about to suggest what @rsn did. It seems like it's a x64 thing. This worked for me:
    #AutoIt3Wrapper_UseX64=y #include <Constants.au3> Global $sCommandLine = ' "C:\Windows\System32\dsregcmd.exe" /status ' ; >C:\GlobalDocs\intune.txt Global $sWorkingDir = 'C:\WINDOWS\system32' ; @SystemDir Global $iPid = Run(@ComSpec & " /c " & $sCommandLine, $sWorkingDir, @SW_HIDE, BitOR($RUN_CREATE_NEW_CONSOLE, $STDERR_MERGED)) ProcessWaitClose($iPid) ConsoleWrite(StdoutRead($iPid) & @CRLF) Or:
    #AutoIt3Wrapper_UseX64=y #include <Constants.au3> Global $sOutputFile = 'c:\temp\intune.txt' Global $sCommandLine = 'c:\windows\system32\dsregcmd.exe /status>' & $sOutputFile Global $iPid = Run(@ComSpec & " /c " & $sCommandLine, @SystemDir, @SW_HIDE, BitOR($RUN_CREATE_NEW_CONSOLE, $STDERR_MERGED)) ProcessWaitClose($iPid) ConsoleWrite('StdoutRead: ' & @CRLF & StdoutRead($iPid) & @CRLF) ConsoleWrite('FileRead: ' & @CRLF & FileRead($sOutputFile) & @CRLF)  
  25. Like
    mistersquirrle got a reaction from mucitbey in Export text file contents to Excel   
    Try this, again I can't test it because I don't have Excel, however there were a few issues with what you had when I looked at the functions vs the helpfile:
    #include <Array.au3> #include <Excel.au3> #include <File.au3> Global $OutFile = "Yeni.xlsx" Global $oExcel = _Excel_Open() ; Excel uygulaması başarısız olduysa, hata mesajı yazdır ve kodu sonlandır If @error Then ConsoleWrite('Excel uygulaması açılamadı. Unable to _Excel_Open, @error: ' & @error & ', @extended: ' & @extended & @CRLF) Exit EndIf ; Çıktı dosyasını aç ; Try to open an existing book, if not it'll try to create a new one Global $oWorkbook = _Excel_BookOpen($oExcel, @ScriptDir & "\" & $OutFile) ; Çıktı dosyası açılamazsa, hata mesajı yazdır ve kodu sonlandır If @error Then ConsoleWrite('Çıktı dosyası açılamadı. Unable to do _Excel_BookOpen, @error: ' & @error & ', @extended: ' & @extended & @CRLF) ConsoleWrite('Trying to create a new book and save it...' & @CRLF) $oWorkbook = _Excel_BookNew($oExcel, 1) If @error Then ConsoleWrite('Unable to do _Excel_BookNew, @error: ' & @error & ', @extended: ' & @extended & @CRLF) Exit EndIf _Excel_BookSaveAs($oWorkbook, @ScriptDir & "\" & $OutFile, $xlWorkbookDefault, True) If @error Then ConsoleWrite('Unable to do _Excel_BookSaveAs, @error: ' & @error & ', @extended: ' & @extended & @CRLF) Exit EndIf EndIf ; Okunacak dosyaların adlarını al Global $fileList = _FileListToArray(@ScriptDir, "*.txt") ; Okunacak dosya sayısı Global $fileCount = UBound($fileList) - 1 Global $inputFileName Global $dataArray Global $oSheet ; Her dosyayı oku ve excel dosyasına aktar For $i = 1 To $fileCount Step 1 ; Okunacak dosyanın adı $inputFileName = $fileList[$i] ; Dosya okunamazsa, hata mesajı yazdır ve diğer dosyaya geç If Not FileExists(@ScriptDir & "\" & $inputFileName) Then MsgBox(16, "Hata", $inputFileName & " dosyası okunamadı.") ContinueLoop EndIf ; Dosyayı oku ve verileri diziye aktar ;~ Local $fileContent = FileRead(@ScriptDir & "\" & $inputFileName) ;~ Local $dataArray = StringSplit(StringStripCR($fileContent), @LF, 1) _FileReadToArray(@ScriptDir & "\" & $inputFileName, $dataArray, $FRTA_NOCOUNT, '|') ; _ArrayDisplay($dataArray) ; Verileri excel dosyasına aktar ;~ $oSheet = _Excel_BookNew($oExcel, 1) $oSheet = _Excel_SheetAdd($oWorkbook, -1, False, 1, $inputFileName) If @error Then ConsoleWrite('Unable to do _Excel_BookNew, @error: ' & @error & ', @extended: ' & @extended & @CRLF) ContinueLoop EndIf _Excel_RangeWrite($oWorkbook, $oSheet, $dataArray, "A1") If @error Then ConsoleWrite('Unable to do _Excel_RangeWrite, @error: ' & @error & ', @extended: ' & @extended & @CRLF) ContinueLoop EndIf Next ; Excel uygulamasını kapat _Excel_BookSaveAs($oWorkbook, @ScriptDir & "\" & $OutFile, $xlWorkbookDefault) If @error Then ConsoleWrite('Unable to do _Excel_BookSaveAs, @error: ' & @error & ', @extended: ' & @extended & @CRLF) EndIf _Excel_BookClose($oWorkbook, False) If @error Then ConsoleWrite('Unable to do _Excel_BookClose, @error: ' & @error & ', @extended: ' & @extended & @CRLF) EndIf _Excel_Close($oExcel) If @error Then ConsoleWrite('Unable to do _Excel_Close, @error: ' & @error & ', @extended: ' & @extended & @CRLF) EndIf I added some more logging, so that you can see what/where a problem exists. If you can, try this and then copy/paste the output in the console here so that I can see what messages come up.
    As for the issues that you had, I don't think that _Excel_BookNew is what you wanted before you wrote data. When writing data, _Excel_RangeWrite using the wrong parameters, and needed $oWorkbook first. The third parameter of _Excel_BookSaveAs was also incorrect, it should be something from: https://learn.microsoft.com/en-us/office/vba/api/excel.xlfileformat
×
×
  • Create New...