Jump to content

Recommended Posts

Posted

Simpler:

; Returns the string on the left side of a search string consisting of digits only
ConsoleWrite(_StringGetDigitLeft("1234abcd5678") & @CRLF) ; Results in "1234"
ConsoleWrite(_StringGetDigitLeft("abcd5678") & @CRLF) ; Results in ""

; Returns the string on the right side of a search string consisting of digits only
ConsoleWrite(_StringGetDigitRight("1234abcd5678") & @CRLF) ; Results in "5678"
ConsoleWrite(_StringGetDigitRight("1234abcd") & @CRLF) ; Results in ""

Func _StringGetDigitLeft(Const ByRef $sString)
;   Return String(Number($sString)) ; requires at least one leading digit
    Return StringRegExpReplace($sString, "^(?|(\d+)|())(.*$)", "$1")
EndFunc

Func _StringGetDigitRight(Const ByRef $sString)
    Return StringRegExpReplace($sString, "(.*?)(?|(\d+)|())$", "$2")
EndFunc

 

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Posted

There's a certain grace that comes with admitting you were wrong (or that someone did something better). Trust me, I've been there... too much. It happens a lot, don't worry about it.

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Posted

I agree with @DonChunior, their version uses StringIsDigit while @jchd's version uses RegEx, it is a matter of opinion which is simpler, not all people know or like RegEx ;)

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Posted (edited)

Hi guys, I've spent a couple hours today to understand socks5 proxy and tried to implement connecting to an external proxy through autoit. My goal is to add this function to my IRC client. It's all about learning isn't it ?!?

I've got the authentication part working, and I am sending the snippet here thinking it might interest somebody :)

Have fun!

Next step, I will be testing some requests to IRC servers, I am also interested into adding SSL support !!!

-el tonio

 

 

 

; Socks5 proxy server authentication using the username/password method (0x02)

; Pure AutoIt 3, Authentication to Socks5 proxy server using the username/password method

Global Const $AuthNumberOfAuthMethodsSupported = 2
Global Const $AuthMethodNoAuthenticationRequired = 0x00
Global Const $AuthMethodUsernamePassword = 0x02

Local $ProxyHost = "your Socks5 server hostname";
Local $ProxyPort = "your Socks5 server port";
Local $Username = "User name"
Local $Password = "Password"

TCPStartup()
Opt("TCPTimeout", 5000)

; 1. Connect to Proxy
Local $socket

$socket = TCPConnect(TCPNameToIP($ProxyHost),$ProxyPort)
If $socket > 0 Then

    ConsoleWrite($socket & " Connected..." & @CRLF)

    ; 2. GREETING the server (Or telling it what Auth Method you support)
    Local $sReq = Chr("0x05") _                                 ; Socks version 5
                & Chr("2") _                                    ; 2 auth methods supported
                & Chr($AuthMethodNoAuthenticationRequired) _    ; No Auth Required method
                & Chr($AuthMethodUsernamePassword)              ; Username/Password method

    ConsoleWrite("$sReq : " & $sReq & @CRLF)

    TCPSend($socket, $sReq)

    Local $sBuff
    ; Waiting for the server to reply
    While 1
        $sBuff = TCPRecv($socket,6,1)
        If @error Then ExitLoop
        If StringLen($sBuff) > 0 Then ExitLoop

        Sleep(100)
    WEnd
    
    ConsoleWrite(@CRLF & "!   Reply: " & $sBuff & @CRLF)
    
    If StringRight($sBuff, 2) = "02" Then ; Server chose the username/password method which is GREAT!
    
        ; 3. Perform Authentification
        $sReq = "0x01" _
                & StringMid(Binary(StringLen($Username)), 3, 2) _
                & StringMid(StringToBinary($Username), 3) _
                & StringMid(Binary(StringLen($Password)), 3, 2) _
                & StringMid(StringToBinary($Password), 3)

        ConsoleWrite("$sReq : " & $sReq & @CRLF)

        TCPSend($socket, $sReq)

        ; Wait for the Reply
        ConsoleWrite("Waiting for the reply ... " & @CRLF)
        While 1

            $sBuff = TCPRecv($socket,10,1)
            If @error Then ExitLoop
            If StringLen($sBuff) > 0 Then ExitLoop

            Sleep(100)
        WEnd

        ConsoleWrite(@CRLF & "!   Reply: " & $sBuff & @CRLF)
        If StringRight($sBuff, 2) = "00" Then ; Authentication successful

            ConsoleWrite("Authenticated..." & @CRLF)
            
            While 1
                ; Now you can work on requests to whatever, from this point the request is similar to Socks4
                
                Sleep(10)
            WEnd

        Else ; Authentication failed

        EndIf
    Else
        ; In case the server do not discuss by the book!!
        
    EndIf
Else
    ; Connecting error
    ConsoleWrite("Connecting error " & " - " & @error & @CRLF)

EndIf

TCPCloseSocket($socket)
TCPShutdown()
Exit

Was helpful to me:

https://en.wikipedia.org/wiki/SOCKS#SOCKS5

https://blog.zhaytam.com/2019/11/15/socks5-a-net-core-implementation-from-scratch/

 

 

 

 

Edited by T0ny
Posted (edited)

I found myself needing to search different parts of a large array and did not need all the results from _ArrayFindAll, so I wrote a similar function, which I call _ArrayFindRanges. Instead of $iStart and $iEnd, you use ranges separated by semi-colons (ex: "2-5;8-12;18-30;42-50"). I tested various aspects and I am not finding any flaws yet. If anyone has suggestions to make it better or more efficient, I would love to hear from you. Hope you guys like it!

🤠

Update! (10-6-2020)

I took seadoggie01's suggestion to only ReDim once (Thx, seadoggie01!). Also, while integrating this function into a script, I discovered I was forcing the $iForward parameter to be forward searching only in the _ArraySearch call. I fixed that as well. I changed where Default is passed to $iRanges will search the entire array (this makes it act like _ArrayFindAll). Lastly, I discovered if you entered nothing or incorrect data for $iRanges, it will crash your program. I included a check that will return an error code instead of going through the loops, letting you know you have no matches because you passed improper data for $iRanges. I just realized I need to put in more checks to make sure only numbers are passed and possible error codes - I will work on this.

The syntax should be the same except for not receiving errors for having the correct number of parameters. _ArraySearch uses 9 parameters and my function uses 8 parameters (the $iStart and $iEnd are replaced with $iRanges).

It's working efficiently and perfectly in my script. I will work on more error checking and update when I have completed it.

Updated code:

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
#include <array.au3>

; Examples

Local $aValues[20] = ["", "", "you", "you", "you", "me", "me", "", "", "you", "me", "", "", "me", "you", "me", "", "", ""] ; 1D array
Local $aValues2[2][4] = [["peter", "paul", "mary", "paul"], ["peter", "mary", "mary", "peter"]] ; 2D array
Local $test, $testErrorNotArray = "wow"

$test = _ArrayFindRanges($aValues, "Me", "2-7;12-18", 0, 0, 0, False) ; test 1D array
If @error Then MsgBox(0, "", @error)
_ArrayDisplay($test)

$test = _ArrayFindRanges($aValues2, "mary", "1-4", 0, 0, 1, True) ; test 2D array choosing to search columns instead of rows
If @error Then MsgBox(0, "", @error)
_ArrayDisplay($test)

$test = _ArrayFindRanges($aValues2, "joe", "1-4", 0, 0, 1, True) ; test 2D array, testing @error result
If @error Then MsgBox(0, "", @error)
_ArrayDisplay($test)

$test = _ArrayFindRanges($testErrorNotArray, "joe", "1-4", 0, 0, 1, True) ; test 2D array, testing a different @error result
If @error Then MsgBox(0, "", @error)
_ArrayDisplay($test)

#cs

Syntax:
_ArrayFindRanges ( Const ByRef $aArray, $iRanges ("num1-num2;num3-num4;num5-num6"), [, $iCase = 0 [, $iCompare = 0 [, $iSubItem = 0 [, $bRow = False]]]]]] )
Note: $iRanges must enclose all the number ranges in quotes and separate the various ranges by semi-colons.

Success:
An array of all index numbers in array containing $vValue.

Failure:
Sets the @error flag to non-zero (see _ArraySearch() description for @error).

Remarks
The values of $iCompare can not be combined together.

#ce

; #FUNCTION# ====================================================================================================================
; Title .........: ArrayFindRanges
; AutoIt Version : 3.3.14.2
; Description ...: Search ranges of an array (similar to _ArrayFindAll)
; Author ........: abberration
; Thanks ........: seadoggie01 for improvement suggestions
; ===============================================================================================================================

Func _ArrayFindRanges(Const ByRef $aArray, $vValue, $iRanges, $iCase = 0, $iCompare = 0, $iForward = 1, $iSubItem = 0, $bRow = False)
    Local $iIndex = 1, $avResult[UBound($aArray)], $aRangeSplit, $aValuesSplit, $iResult
    If $iRanges = Default Then $iRanges = "1-" & UBound($aArray)
    If $iCompare = Default Then $iCompare = 0
    If $iSubItem = Default Then $iSubItem = 0
    If $bRow = Default Then $bRow = False

    $aRangeSplit = StringSplit($iRanges, ";")
    If $aRangeSplit[1] = "" Then
        Return SetError(@error, 0, -1)
    Else
        For $i = 1 To $aRangeSplit[0]
            $aValuesSplit = StringSplit($aRangeSplit[$i], "-", 2)
            For $j = $aValuesSplit[0] To $aValuesSplit[1]
                $iResult = _ArraySearch($aArray, $vValue, $j, $aValuesSplit[1], $iCase, $iCompare, $iForward, $iSubItem, $bRow)
                $j = $iResult
                If $iResult = -1 Then ExitLoop
                $avResult[$iIndex - 1] = $iResult
                $iIndex += 1
            Next
        Next
    EndIf
    If $iIndex = 1 Then Return SetError(@error, 0, -1)
    ReDim $avResult[$iIndex - 1]
    Return $avResult
EndFunc   ;==>_ArrayFindRanges

 

Edited by abberration
Last update for today. Included thanks to seadoggie01 in function header and a couple grammar fixes.
Posted

My two three cents: (whatever they're worth :D )

1. Arrays resizing (ReDim) is a costly process. To speed things up, don't do it every time you find a match. Instead, either calculate the largest number of possible results up front and then size your array, or start with an array of say 100 and add as needed. At the very least, right now you're resizing your array after every match and at the end. Instead, just resize it when you get a match (start with $iIndex = 0 and resize before adding the value to the array).

2. I'm not sure (because I haven't tested), but I would think that calling _ArrayFindAll once instead of _ArraySearch many times would be more efficient.

3. I think that an invalid string passed in $iRanges (shouldn't that be $sRanges?) will break your function... you aren't checking the @error value of StringSplit. And yeah, GIGO, but I try to handle all the garbage I can find

That said, as long as it works for you, who cares?! :) I probably would've started with the results from _ArrayFindAll and chucked out all the results I didn't need, but that's probably wasteful. It's a good function if you have a need for it!

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

Posted

Hi, seadoggie01,

You make a great point about ReDim. I will look at the code soon and try to rework it to only ReDim once.

_ArrayFindAll is what I used to model my function. It uses _ArraySearch for it's results, so using _ArrayFindAll should not be any faster.

You are correct, I should have done more error checking. Before I put in the one @error, when I passed bad info, it only returned an empty array. When I put in the one @error, it seemed to return the correct error handle. But I do need to do more testing in this area.

I got it working and was very tired, so I just posted it. I will continue working on it. I think it could be a very useful addition when it's perfected. I have already determined that declaring the default value of $iRanges is useless as it is. I need to work on that.

Thank you for your suggestions. I will use them to improve the script.

 

  • 2 weeks later...
Posted (edited)
On 9/17/2020 at 1:55 PM, jchd said:

Simpler:

; Returns the string on the left side of a search string consisting of digits only
ConsoleWrite(_StringGetDigitLeft("1234abcd5678") & @CRLF) ; Results in "1234"
ConsoleWrite(_StringGetDigitLeft("abcd5678") & @CRLF) ; Results in ""

; Returns the string on the right side of a search string consisting of digits only
ConsoleWrite(_StringGetDigitRight("1234abcd5678") & @CRLF) ; Results in "5678"
ConsoleWrite(_StringGetDigitRight("1234abcd") & @CRLF) ; Results in ""

Func _StringGetDigitLeft(Const ByRef $sString)
;   Return String(Number($sString)) ; requires at least one leading digit
    Return StringRegExpReplace($sString, "^(?|(\d+)|())(.*$)", "$1")
EndFunc

Func _StringGetDigitRight(Const ByRef $sString)
    Return StringRegExpReplace($sString, "(.*?)(?|(\d+)|())$", "$2")
EndFunc

 

Hello @jchd,

I did a small benchmark to compare the performance of our _StringGetDigitLeft and _StringGetDigitRight functions.
For this purpose I have used the following password list: https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt
The code of my benchmark was as follows:

Local $asPasswordList = 0
Local $hTimer = 0
Local $fDiff = 0.0

$asPasswordList = FileReadToArray("10-million-password-list-top-1000000.txt")
$hTimer = TimerInit()
For $sPassword In $asPasswordList
    _StringGetDigitLeft($sPassword)
;~  _StringGetDigitRight($sPassword)
Next
$fDiff = TimerDiff($hTimer)
ConsoleWrite($fDiff & " ms" & @CRLF)

It turned out that your functions based on regular expressions were each over 50% faster!
So I have to give you credit for the fact that your variants would be technically preferable in any case. 🏆👏

Edited by DonChunior
Posted

Well, it's not always the case that regexps are the fastest way to perform a given task. However once one takes the pain to reasonably master their "strange" syntax and specific features, they can prove elegant and unvaluable in a large number of use cases. Of course their power tends to make overuse tempting.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Posted
18 hours ago, DonChunior said:

It turned out that your functions based on regular expressions were each over 50% faster!

And I'd like to mention that it is probably because AutoIt has a lot of overhead in string processing and the interpreter itself is a bit slow. Compare that to an optimized RegEx engine written in C(++) and it is clear why it is faster, despite being logically a more complex operation :)

Speed isn't everything, and AutoIt isn't that fast really, so unless you are processing many strings in bulk, it is okay to use whatever you prefer, it won't make a significant difference in operation.

EasyCodeIt - A cross-platform AutoIt implementation - Fund the development! (GitHub will double your donations for a limited time)

DcodingTheWeb Forum - Follow for updates and Join for discussion

Posted
4 hours ago, TheDcoder said:

And I'd like to mention that it is probably because AutoIt has a lot of overhead in string processing and the interpreter itself is a bit slow. Compare that to an optimized RegEx engine written in C(++) and it is clear why it is faster, despite being logically a more complex operation :)

Speed isn't everything, and AutoIt isn't that fast really, so unless you are processing many strings in bulk, it is okay to use whatever you prefer, it won't make a significant difference in operation.

That my version would be easier to understand (for me) was admittedly a subjective opinion.
I just wanted to look at the topic more objectively, hence my benchmark.

  • 1 month later...
Posted

Code to a String:

This is a tool to modify code from the clipboard to be pasted as code that can let one program write a file and run the code from that file.

I had written an #include file that needed to run a separate program to make a window, but I didn't want to hard code the location of the include file or the window. So I decided to carry the window program within the main program.

To do this I wrote the separate program to make the window, then copied it to the clipboard and ran the program below that takes the clipboard and reformats it into code that when run puts that code into a string.  

I copy that code into the main program then when I need to run the window program the main program calls the function that  takes the string 
writes it to a file and runs the file.

 

;Make a $sString of code to include in prgm
;Put the code on the clipboard run the prg and paste the string building code in your prg
#include <array.au3>
Global $q = Chr(39)
$aStr = StringSplit(clipget(),@CRLF,3) ;ArrayFromClip
for $i = 0 to UBound($aStr) - 1
    if $i = 0 then
        $aStr[$i] = "$sString = " & $q & $aStr[$i] & $q & "& @CRLF"
    Else
        $aStr[$i] = "$sString &= " & $q & $aStr[$i] & $q & "& @CRLF"
    EndIf
Next
_ArrayToClip($aStr,@CRLF)

So copying the program above to the clipboard and running it would produce...

$sString = ';Make a $sString of code to include in prgm'& @CRLF
$sString &= ';Put the code on the clipboard run the prg and paste the string building code in your prg'& @CRLF
$sString &= '#include <array.au3>'& @CRLF
$sString &= 'Global $q = Chr(39)'& @CRLF
$sString &= '$aStr = StringSplit(clipget(),@CRLF,3) ;ArrayFromClip'& @CRLF
$sString &= 'for $i = 0 to UBound($aStr) - 1'& @CRLF
$sString &= '   if $i = 0 then'& @CRLF
$sString &= '       $aStr[$i] = "$sString = " & $q & $aStr[$i] & $q & "& @CRLF"'& @CRLF
$sString &= '   Else'& @CRLF
$sString &= '       $aStr[$i] = "$sString &= " & $q & $aStr[$i] & $q & "& @CRLF"'& @CRLF
$sString &= '   EndIf'& @CRLF
$sString &= 'Next'& @CRLF
$sString &= '_ArrayToClip($aStr,@CRLF)'& @CRLF
$sString &= ''& @CRLF

Adding:

FileWrite(@workingdir & "filename.au3",$sString)
ShellExecute(@workingdir & "filename.au3")

would write it and run it.

You could add code to erase the file as part of $GUI_EVENT_CLOSE or just before the codes exits with OnAutoItExitRegister.  That way you don't end up with multiple copies if you run in different folders.

I hope this is understandable :)  but I happy to answer a question if it isn't.

Posted (edited)

While I hate this kind of file, I recently had to re-write an Excel VBA script that wrote the worksheet to a fixed width format file. It isn't perfect, but this is what I have so far:

; #FUNCTION# ====================================================================================================================
; Name ..........: _Export_FixedWidth
; Description ...: Exports an array to a file using a fixed width format
; Syntax ........: _Export_FixedWidth($avData, $aiWidth, $aiPrecision, $sFile[, $sNewLine = Default])
; Parameters ....: $avData              - a 2D array of variants.
;                  $aiWidth             - a 1D array of integers.
;                  $aiPrecision         - a 1D array of integers. Default copies $aiWidth.
;                  $sFile               - full file path to save as or a file handle.
;                  $sNewLine            - [optional] newline. Default is @CRLF.
; Return values .: Success - True
;                  Failure - False and sets @error:
;                  |1 - $avData isn't a 2D array
;                  |2 - $avData has more columns than (@extended) 1 - $aiWidth or 2 - $aiPrecision
;                  |3 - Unable to write data to $sFile
; Author ........: Seadoggie01
; Modified ......: December 17, 2020
; Remarks .......: $aiWidth's and $aiPrecision's sizes must match $avData's column count.
;                  If $sFile is a handle, it will not be closed
;                  Data is right aligned; set $aiWidth's value to negative to right align data. 
;                  +$aiPrecision uses the absolute value (helpful if $aiPrecision = $aiWidth)
; Related .......: 
; Link ..........: 
; Example .......: No
; ===============================================================================================================================
Func _Export_FixedWidth($avData, $aiWidth, $aiPrecision, $sFile, $sNewLine = Default)

    If IsKeyword($aiPrecision) Then $aiPrecision = $aiWidth
    If IsKeyword($sNewLine) Then $sNewLine = @CRLF
    
    ; Ensure 2D array
    If UBound($avData, 0) <> 2 Then Return SetError(1, 0, False)
    ; Check sizes of the arrays
    If UBound($aiWidth) <> UBound($avData, 2) Then Return SetError(2, 1, False)
    If UBound($aiPrecision) <> UBound($avData, 2) Then Return SetError(2, 2, False)
    
    Local $sExportText
    ; For each row
    For $iRow = 0 To UBound($avData) - 1
        ; For each column
        For $iColumn = 0 To UBound($avData, 2) - 1
            ; Format the data as a string using the width and precision assigned by the user
            $sExportText &= StringFormat("%" & (-1 * $aiWidth[$iColumn]) & "." & Abs($aiPrecision[$iColumn]) & "s", $avData[$iRow][$iColumn])
        Next

        $sExportText &= $sNewLine
    Next

    If Not FileWrite($sFile, $sExportText) Then Return SetError(3, 0, False)
    Return True
    
EndFunc

As the VBA was looping through each cell, reading it (and the precision), and writing it to file, it was taking upwards of 10 minutes as the worksheet was 72 columns x 15367 rows (~1.1 M cells). I'm very impatient and this was just too much. Now it takes less than a second to write the data I lied, I needed more error checking. 🤦‍♂️ However, 24 seconds is still much better :D

Edited by seadoggie01

All my code provided is Public Domain... but it may not work. ;) Use it, change it, break it, whatever you want.

Spoiler

My Humble Contributions:
Personal Function Documentation - A personal HelpFile for your functions
Acro.au3 UDF - Automating Acrobat Pro
ToDo Finder - Find #ToDo: lines in your scripts
UI-SimpleWrappers UDF - Use UI Automation more Simply-er
KeePass UDF - Automate KeePass, a password manager
InputBoxes - Simple Input boxes for various variable types

  • 4 weeks later...
Posted (edited)

Text in, AutoIt string concatenation out (clipboard in and out). Can choose double or single quote character for output by editing script.

Args (can be combined):

W - Chars 128+ are encoded with AscW()

V - Strings in the form "$$string" are concatenated as AutoIt variables. Useful for generating code for a child script that uses values established in the parent script. For example:

Input string 1:

Const $sChildString = $sParentString

Output with (or without) Arg "V":

"Const $sChildString = $sParentString" & @CRLF

Input string 2 (note double "$$"):

Const $sChildString = "$$sParentString"

Output with Arg "V":

"Const $sChildString = """ & $sParentString & """ & @CRLF

Updated script:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#Au3Stripper_Parameters=/so
#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d
#AutoIt3Wrapper_AU3Check_Stop_OnWarning=y
#AutoIt3Wrapper_Change2CUI=n
#AutoIt3Wrapper_Outfile_type=a3x
#AutoIt3Wrapper_Run_Au3Stripper=y
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_UseX64=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
;
; Text2Au3.au3
; Text to AutoIt string concatenation
; Clipboard in + out
; CLD rev. 1/18/2021
;
; Quote char for output code
Global $sQChar = '"'     ; double quote (")
; Global $sQChar = "'" ; single quote (')
;
Global $sIn = ClipGet()
If Not $sIn Then Exit
Global $sArg = ""
If $CmdLine[0] > 0 Then
; Arg "V" converts $$variable to $variable
; Arg "W" encodes Ascii 128+
    For $a = 1 To $CmdLine[0]
        $sArg &= $CmdLine[$a]
    Next
EndIf
Global $aIn = StringSplit($sIn, "")
Global $sCloseQuo = $sQChar & " & "
Global $bTx = 0, $sOut = ""
Global $sVarChars = "_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

For $i = 1 To $aIn[0]
    Select
        Case $aIn[$i] = $sQChar
            $sOut &= $sQChar & $sQChar
        Case $aIn[$i] = Chr(13)
            PutCloseQuo()
            $sOut &= "@CR"
            If $i < $aIn[0] And $aIn[$i + 1] = @LF Then
                $sOut &= "LF"
                $i += 1
            EndIf
            $sOut &= " & "
        Case $aIn[$i] = Chr(10)
            PutCloseQuo()
            $sOut &= "@LF & "
        Case Asc($aIn[$i]) < 32
            PutCloseQuo()
            $sOut &= "Chr(" & Asc($aIn[$i]) & ") & "
        Case AscW($aIn[$i]) > 127
            If StringInStr($sArg, "W") Then
                PutCloseQuo()
                $sOut &= "ChrW(" & AscW($aIn[$i]) & ") & "
            Else
                ContinueCase
            EndIf
        Case ( StringInStr($sArg, "V") And $aIn[$i] = "$" And _
                    $i < $aIn[0] - 1 )
            If $aIn[$i + 1] = "$" And StringInStr($sVarChars, $aIn[$i + 2]) Then
                PutCloseQuo()
                $i += 1
                Do
                    $sOut &= $aIn[$i]
                    $i += 1
                    If $i > $aIn[0] Then ExitLoop 2
                Until StringInStr($sVarChars, $aIn[$i]) = 0
                $i -= 1
                $sOut &= " & "
                $bTx = 1
            Else
                ContinueCase
            EndIf
        Case Else
            If $bTx = 0 And StringLen($sOut) > 0 Then $sOut &= $sQChar
            $bTx = 1
            If Not $sOut Then $sOut = $sQChar
            $sOut &= $aIn[$i]
    EndSelect
Next
If StringInStr(StringRight($sOut, 3), "&") Then $sOut = StringTrimRight($sOut, 3)
If $bTx = 1 Then $sOut &= $sQChar
ClipPut($sOut & @CRLF)
Exit MsgBox(0, @ScriptName, "Ctrl-V pastes output")

Func PutCloseQuo()
    If $bTx = 1 And StringLen($sOut) > 0 Then $sOut &= $sCloseQuo
    $bTx = 0
    Return
EndFunc  ;==>PutCloseQuo

 

Edited by CarlD
Update
  • 4 weeks later...
Posted (edited)

Function that returns the singular or plural, depending on the number.

; Example 1
$sMessage = _
    @HOUR & " " & _OneMany("hour", @HOUR) & ", " & _
    @MIN & " " & _OneMany("MINUTE", @MIN) & ", " & _
    @SEC & " " & _OneMany("second", @SEC)
MsgBox(0, @ScriptName, $sMessage)

;Example 2
MsgBox(0, @ScriptName, "He has five " & _OneMany("child", 5, "children") & ".")

Func _OneMany($sSingular, $iCount, $sPlural = "")
; Returns singular or plural depending on count
; Plural appends S to singular unless $sPlural is supplied
    Local $sEss = "s"
    If StringUpper($sSingular) == $sSingular Then $sEss = "S"
    If Not $sPlural Then $sPlural = $sSingular & $sEss
    If Abs($iCount) = 1 Then
        Return $sSingular
    Else
        Return $sPlural
    EndIf
EndFunc  ;==>_OneMany
 

 

 

Edited by CarlD
  • 1 month later...
Posted (edited)
#include-once
;~ #include <AutoItConstants.au3> ; needed For $STDERR_CHILD & $STDOUT_CHILD
Global $__g_RunWaitEx_sWorkingDir = @TempDir
Global $__g_RunWaitEx_iShowFlag = @SW_HIDE
Global $__g_RunWaitEx_iOptFlag = 6 ;  ; "BitOR($STDERR_CHILD, $STDOUT_CHILD) = 6"
Global $__g_RunWaitEx_msTimeout = 0

; these helper functions return the set values, or sets the values if provided with one.
Func _RunWaitEx_WorkingDir($val = Default)
    If $val <> Default Then $__g_RunWaitEx_sWorkingDir = String($val)
    Return $__g_RunWaitEx_sWorkingDir
EndFunc   ;==>_RunWaitEx_WorkingDir
Func _RunWaitEx_ShowFlag($val = Default)
    If $val <> Default Then $__g_RunWaitEx_iShowFlag = Int($val)
    Return $__g_RunWaitEx_iShowFlag
EndFunc   ;==>_RunWaitEx_ShowFlag
Func _RunWaitEx_OptFlag($val = Default)
    If $val <> Default Then $__g_RunWaitEx_iOptFlag = Int($val)
    Return $__g_RunWaitEx_iOptFlag
EndFunc   ;==>_RunWaitEx_ShowFlag
Func _RunWaitEx_Timeout($val = Default)
    If $val <> Default Then $__g_RunWaitEx_msTimeout = Int($val)
    Return $__g_RunWaitEx_msTimeout
EndFunc   ;==>_RunWaitEx_Timeout

; ..say you'd like to change a default due to circumstance
;~ If Not @Compiled Then _RunWaitEx_ShowFlag(@SW_SHOW)

; this example is to showcase the errorlevel/exitcode as the @extended value.
Exit ConsoleWrite('--- Text     >' & _RunWaitEx("dir /.ThisWillFail") & _
                  '--- @error   >' & @error & @CRLF & _ ; timeout ?
                  '--- exitcode >' & @extended & @CRLF)

;RunWait: Runs an external program and pauses the script execution until the program finishes, returning the exit code of the program that was run.
;_RunWaitEx: Same as RunWait() but also returns the output text and has an optional timeout.
Func _RunWaitEx($sCommand, $sWorkingDir = Default, $iShowFlag = Default, $iOptFlag = Default, $msTimeout = Default)
    ;   https://www.autoitscript.com/forum/index.php?showtopic=139260&view=findpost&p=1478119
    ; ------------------- GetExitCodeProcess portion
    Switch $sWorkingDir
        Case "/OpenProcess"
            Local $hPID_HANDLE = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', 0x400, 'int', 0, 'int', $sCommand)
            If Not @error Then Return $hPID_HANDLE
            Return SetError(1, 0, 0)
        Case "/GetExitCodeProcess"
            Local $v_Placeholder, $aRet = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $sCommand[0], 'int*', $v_Placeholder)
            If Not @error And UBound($aRet) > 2 Then Return $aRet[2]
            Return SetError(1, 0, 0)
        Case "/CloseHandle"
            DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $sCommand)
            If Not @error Then Return 1
            Return 0
    EndSwitch

    ; ------------------- set defaults
    If $sWorkingDir = Default Then $sWorkingDir = _RunWaitEx_WorkingDir() ; @TempDir
    If $iShowFlag = Default Then $iShowFlag = _RunWaitEx_ShowFlag() ; @SW_HIDE
    If $iOptFlag = Default Then $iOptFlag = _RunWaitEx_OptFlag() ; "BitOR($STDERR_CHILD, $STDOUT_CHILD) = 6"
    If $msTimeout = Default Then $msTimeout = _RunWaitEx_Timeout() ; ( 0 ms. = OFF ) in case the process takes longer than expected

    ; ------------------- Run()
    Local $iPID = Run(@ComSpec & " /c " & $sCommand, $sWorkingDir, $iShowFlag, $iOptFlag)
    If @error Or $iPID = 0 Then Return SetError(@error + 100, 0, "")
    Local $iExitCode = 0, $hPID_HANDLE = _RunWaitEx($iPID, "/OpenProcess")
    Local $hTimer = TimerInit(), $sOutput = ""
    While 1
        $sOutput &= StdoutRead($iPID)
        If @error Then ExitLoop
        If $msTimeout And TimerDiff($hTimer) > $msTimeout Then ExitLoop
        Sleep(1)
    WEnd
    While 1
        $sOutput &= StderrRead($iPID)
        If @error Then ExitLoop
        If $msTimeout And TimerDiff($hTimer) > $msTimeout Then ExitLoop
        Sleep(1)
    WEnd
    If $hPID_HANDLE <> 0 Then
        $iExitCode = _RunWaitEx($hPID_HANDLE, "/GetExitCodeProcess")
        If $iExitCode = 259 Then
            $iExitCode = 100000 + $iPID ; ...process not done, should not close handle.
        Else ;                            ...the PID will be the @extended - 100000
            _RunWaitEx($hPID_HANDLE, "/CloseHandle")
        EndIf
    EndIf
    Return SetError($msTimeout And TimerDiff($hTimer) > $msTimeout ? 200 : 0, $iExitCode, $sOutput)
EndFunc   ;==>_RunWaitEx

I bet there are examples of this but I liked this "All In One".

2021.04.03: Added helper functions to Set or Get default values.
2021.06.25: Added OptFlag() to set/change default ( does script break from prior version )

Edited by argumentum
better code

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

  • 3 weeks later...
Posted

Center GUI on Monitor based on mouse position

#include <AutoItConstants.au3>
#include <GUIConstants.au3>
#include <WinAPIGdi.au3>

Func GuiCenterOnMonitorFromMousePosition($hForm, $sText = "")
    Local $aData, $hMonitor, $tPos = _WinAPI_GetMousePos()
    If Not @error Then $hMonitor = _WinAPI_MonitorFromPoint($tPos)
    If Not @error Then $aData = _WinAPI_GetMonitorInfo($hMonitor)
    If @error Then Return SetError(1, -1, 1)
    Local $iWinState = WinGetState($hForm, $sText)
    If @error Then Return SetError(2, $aData[2], 2)
    If BitAND($iWinState, $WIN_STATE_MINIMIZED) Or _
            BitAND($iWinState, $WIN_STATE_MAXIMIZED) Then WinSetState($hForm, $sText, @SW_RESTORE)
    Local $aWinPos = WinGetPos($hForm, $sText)
    If @error Then Return SetError(3, $aData[2], 3)
    WinMove($hForm, _
            $sText, _
            Int((($aData[0].Right - $aData[0].Left - $aWinPos[2]) / 2) + $aData[0].Left), _
            Int((($aData[0].Bottom - $aData[0].Top - $aWinPos[3]) / 2) + $aData[0].Top))
    If @error Then Return SetError(4, $aData[2], 4)
    Return SetError(0, $aData[2], 0)
EndFunc   ;==>GuiCenterOnMonitorFromMousePosition

Example()
Func Example()
    Local $hGUI = GUICreate("GuiCenterOnMonitorFromMousePosition example", 600, 200)
    GuiCenterOnMonitorFromMousePosition($hGUI)
    GUICtrlCreateLabel("Primary display monitor = " & @extended, 20, 20, 160, 21)
    GUISetState()
    While GUIGetMsg() <> $GUI_EVENT_CLOSE
    WEnd
    GUIDelete()
EndFunc   ;==>Example

 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

  • 4 months later...
Posted

I needed _DateDiff() to include milliseconds.

ConsoleWrite('>>> ' & _DateDiffMs('2021/08/16 13:25:08.727', '2021/08/16 13:25:08.729') & @CRLF)
Func _DateDiffMs($sDate1st, $sDate2nd)
    Local $iDate1st, $aDate1st = StringSplit($sDate1st, ".")
    ReDim $aDate1st[3]
    Local $iDate2nd, $aDate2nd = StringSplit($sDate2nd, ".")
    ReDim $aDate2nd[3]
    Local $iDate1st = _DateDiff('s', '1970/01/01 00:00:00', $aDate1st[1])
    Local $iDate2nd = _DateDiff('s', '1970/01/01 00:00:00', $aDate2nd[1])
    $iDate1st &= "000"
    $iDate2nd &= "000"
    $iDate1st += Int($aDate1st[2])
    $iDate2nd += Int($aDate2nd[2])
    Return  ( $iDate2nd - $iDate1st ) / 1000
EndFunc

 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

  • 1 month later...
Posted (edited)

Func _DateDiffWords uses _DateDiff and _DateAdd to report difference between two dates in words (also uses my Func _OneMany)

#include <Date.au3>
#include <MsgBoxConstants.au3>
#AutoIt3Wrapper_AU3Check_Parameters=-w 3 -w 4 -w 5 -w 6 -d
; CarlD rev. 2021-09-25

Global $sDate1 = "2199/12/31 23:59:59"; later date
Global $sDate2 = "1900/01/01 00:00:01"; earlier date (default = now)

MsgBox( $MB_SYSTEMMODAL, @ScriptName, "Difference is:" & @LF & _DateDiffWords($sDate1) ); $sDate2

Func _DateDiffWords($date1, $date2 = @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC)
; Reports difference between two dates in words
; #include <Date.au3>
; $date1 = YYYY/MM/DD[ hh:mm[:ss]]
    Local $sDiffOut = ""
    Local $sYear = "year", $sMon = "month", $sWeek = "week", $sDay = "day"
    Local $sHour = "hour", $sMin = "minute", $sSec = "second"
    Local $sAnd = "and"
    Local $Y, $M, $W, $D, $H, $N, $S; _DateDiff types
    $Y = _DateDiff("Y", $date2, $date1)
    If $Y Then
        $sDiffOut = $Y & " " & _OneMany($sYear, $Y)
        $date1 = _DateAdd("Y", -1 * $Y, $date1)
    EndIf
    $M = _DateDiff("M", $date2, $date1)
    If $M Then
        If $sDiffOut Then $sDiffOut &= ", "
        $sDiffOut &= $M & " " & _OneMany($sMon, $M)
        $date1 = _DateAdd("M", -1 * $M, $date1)
    EndIf
    $W = _DateDiff("W", $date2, $date1)
    If $W Then
        If $sDiffOut Then $sDiffOut &= ", "
        $sDiffOut &= $W & " " & _OneMany($sWeek, $W)
        $date1 = _DateAdd("W", -1 * $W, $date1)
    EndIf
    $D = _DateDiff("D", $date2, $date1)
    If $D Then
        If $sDiffOut Then $sDiffOut &= ", "
        $sDiffOut &= $D & " " & _OneMany($sDay, $D)
        $date1 = _DateAdd("D", -1 * $D, $date1)
    EndIf
    $H = _DateDiff("H", $date2, $date1)
    If $H Then
        If $sDiffOut Then $sDiffOut &= ", "
        $sDiffOut &= $H & " " & _OneMany($sHour, $H)
        $date1 = _DateAdd("H", -1 * $H, $date1)
    EndIf
    $N = _DateDiff("N", $date2, $date1)
    If $N Then
        If $sDiffOut Then $sDiffOut &= ", "
        $sDiffOut &= $N & " " & _OneMany($sMin, $N)
        $date1 = _DateAdd("N", -1 * $N, $date1)
    EndIf
    $S = _DateDiff("S", $date2, $date1)
    If $S Then
        If $sDiffOut Then $sDiffOut &= " " & $sAnd & " "
        $sDiffOut &= $S & " " & _OneMany($sSec, $S)
    EndIf
    Return $sDiffOut
EndFunc  ;==>_DateDiffWords

Func _OneMany($sSingular, $iCount, $sPlural = "")
; Returns singular or plural depending on count
; Plural appends S to singular (ES if it ends in S)
;  unless $sPlural is supplied
    Local $sEss = "s"
    If StringRight($sSingular, 1) = "s" Then $sEss = "es"
    If StringUpper($sSingular) == $sSingular Then $sEss = StringUpper($sEss)
    If Not $sPlural Then $sPlural = $sSingular & $sEss
    If Abs($iCount) = 1 Then
        Return $sSingular
    Else
        Return $sPlural
    EndIf
EndFunc  ;==>_OneMany

 

Edited by CarlD
Update

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
  • Recently Browsing   0 members

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