Fastest way to read and work with a binary file - autoit

Im working on a script that work with a Binary file Inside of loop and read its bytes Consecutive , (also be able to Go back and forth inside the file (savepos) (setpos))
But I dont know I need to use what method so its not bad for performance
My first attempt was to use FileRead with FileHandle, But sadly This made the speed of the program slower as the program progressed and read further from file (Program finish after like 30 min for a 10MB file)
$File = FileOpen($Path, 16)
$tTimer = TimerInit()
$ndx = 4
for $i=0 to 100000
$test = FileRead($File, $ndx)
$ndx += 4
ConsoleWrite($test & #CRLF)
Next
ConsoleWrite(TimerDiff($ttimer) &" Sekunden"& #CRLF)
So I tried to first read whole File into a variable and then read the binary from it with BinaryMid
But this method was even more slower...
$File = FileOpen($Path, 16)
$Readfilee = FileRead($File)
$tTimer = TimerInit()
$ndx = 4
for $i=0 to 100000
$test = _BinaryRead(4)
ConsoleWrite($test & #CRLF)
Next
ConsoleWrite(round(TimerDiff($ttimer) /1000,2) &" Sekunden"& #CRLF)
Func _BinaryRead($iCount)
$ndx += $iCount
Return BinaryMid($Readfilee, $GNOW - $iCount, $iCount)
EndFunc
so I want to know what can I do for reading Bin file as fast as possible?
sorry if its not a good question, Im new in autoit

You don't need to read the file byte-by-byte, the function FileRead() do everything for you in only one step, you can use something like this:
$hFile = FileOpen($Path, $FO_BINARY)
$tTimer = TimerInit()
$bFileContent = FileRead($hFile)
FileClose($hFile)
; Now you can use $bFileContent as you want.
ConsoleWrite(TimerDiff($ttimer) &" Sekunden"& #CRLF)

Related

Conditional include of file

I'd like to include certain script only if it's present. Unfortunately #include is processed before the execution, so I can't make it conditional like this:
If FileExists(#ScriptDir & "\common.au3") Then
#include "common.au3"
EndIf
I tried to use Execute to evaluate the read file in place via Execute(ReadFile(...)). But that seems to only process single statements - I couldn't declare multiple functions for example.
Is there a different way to conditionally include another file?
Probably not a good design choice but if you really need to do somethin like this, try #OnAutoItStartRegister:
#OnAutoItStartRegister "_OnAutoItStart_CreateIncludes"
#include "include_collection.au3"
If IsDeclared("iExample_Common") Then
MsgBox(64, "", "Common.au3 exists")
Else
MsgBox(16, "", "Common.au3 wasnt included")
EndIf
MsgBox(0, "", "Your Script here")
Func _OnAutoItStart_CreateIncludes()
If StringInStr($CmdLineRaw, '-_OnAutoItStart_CreateIncludes', 1) Then Return
If FileExists(#ScriptDir & "\common.au3") And Not StringInStr(FileRead("include_collection.au3"), '#include "common.au3"') Then
FileWrite("include_collection.au3", '#include "common.au3"')
EndIf
$iPID = Run('"' & #AutoItExe & '" ' & $CmdLineRaw & ' -_OnAutoItStart_CreateIncludes', #WorkingDir, Default, 2)
While ProcessExists($iPID)
ConsoleWrite(StdoutRead($iPID))
Sleep(10)
WEnd
Exit
EndFunc ;==>_OnAutoItStart_CreateIncludes
Create an additional empty file "include_collection.au3" as well.
In this example, I created "commons.au3" containing a statement "$iExample_commons = 1234'.
Note: Once the file is included this way, it should not be deleted otherwise your script will fail again. This could probably be overcome too but at some point it will become very messy.
Maybe it's a better Idea to wrap a launcher around your application which will add/remove include lines before startup as needed.

How to get telegram bot getUpdates json from vbscript and read it

i wanted to create my bot in VBScript (i know its like troll and bad idea probably, i can do it in lua, python, C#, PHP, ...., but i decided to try and make it from vbscript)
the hard part is that i'm trying to Retrieve information from Telegram getUpdates
i've made this code for example and it kind of works, i'll explain what works and what doesn't
Dim fso, outFile, TeleTest
Set fso = CreateObject("Scripting.FileSystemObject")
Set outFile = fso.CreateTextFile("output.txt", True)
set TeleTest = fso.CreateTextFile("TeleTest.txt", True)
Dim url, req, json
Set req = CreateObject("MSXML2.XMLHTTP")
url = "https://api.telegram.org/bot"[TOKEN]"/getUpdates"
req.open "GET", url, False
req.send
If req.Status = 200 Then
TeleTest.Write req.responseText
End If
' Load the JSON array into a JsonArray:
set jsonArray = CreateObject("Chilkat_9_5_0.JsonArray")
success = jsonArray.Load("TeleTest.txt")
If (success <> 1) Then
outFile.WriteLine(jsonArray.LastErrorText)
WScript.Quit
End If
' Get some information from each record in the array.
numRecords = jsonArray.Size
i = 0
Do While i < numRecords
outFile.WriteLine("------ Record " & i & " -------")
' jsonRecord is a Chilkat_9_5_0.JsonObject
Set jsonRecord = jsonArray.ObjectAt(i)
outFile.WriteLine(" ok: " & jsonRecord.StringOf("ok"))
outFile.WriteLine(" result: " & jsonRecord.SizeOfArray("result"))
' Examine information for this record
u = 0
Do While u < nummessage
nummessage = jsonRecord.SizeOfArray("result[u].message")
Loop
outFile.WriteLine("Number of message: " & nummessage)
j = 0
Do While j < nummessage
jsonRecord.J = j
outFile.WriteLine(" message text: " & jsonRecord.StringOf("result[j].message[j].text"))
j = j + 1
Loop
i = i + 1
Loop
outFile.Close
so the first part that should get updates and save it ino TeleTest.txt works fine, it gets updates, it saves the json in to the .txt file (or anything, i can also save it into string in the vbs, or .json file)
the problem is that the second part where i'm using Chilkat gives error
Blockquote
ChilkatLog: Load:
ChilkatVersion: 9.5.0.78
Unable to get array at index 0. --Load
--ChilkatLog
any help or any idea would be appereciated, also if Chilkat is not good for doing this, maybe tell me why and give me something else?! (Chilkat was the only dll i found to work with vbscript and does json reading, stuff)
i got it to working, i found out that from this example
Chilkat needs the Json file to like this
[ { json } ]
but the Telegram json is like this
{ json }
so, the fix would be easy to just change line 15 from TeleTest.Write req.responseText to this code below
TeleTest.Write "[" + req.responseText + "]"
my code now works fine , if anyone else found something wrong or any answer to my question it would be appreciated
i hope someone else who needs this find this

Can LLDB data formatters call methods?

I'm debugging a Qt application using LLDB. At a breakpoint I can write
(lldb) p myQString.toUtf8().data()
and see the string contained within myQString, as data() returns char*. I would like to be able to write
(lldb) p myQString
and get the same output. This didn't work for me:
(lldb) type summary add --summary-string "${var.toUtf8().data()}" QString
Is it possible to write a simple formatter like this, or do I need to know the internals of QString and write a python script?
Alternatively, is there another way I should be using LLDB to view QStrings this way?
The following does work.
First, register your summary command:
debugger.HandleCommand('type summary add -F set_sblldbbp.qstring_summary "QString"')
Here is an implementation
def make_string_from_pointer_with_offset(F,OFFS,L):
strval = 'u"'
try:
data_array = F.GetPointeeData(0, L).uint16
for X in range(OFFS, L):
V = data_array[X]
if V == 0:
break
strval += unichr(V)
except:
pass
strval = strval + '"'
return strval.encode('utf-8')
#qt5
def qstring_summary(value, unused):
try:
d = value.GetChildMemberWithName('d')
#have to divide by 2 (size of unsigned short = 2)
offset = d.GetChildMemberWithName('offset').GetValueAsUnsigned() / 2
size = get_max_size(value)
return make_string_from_pointer_with_offset(d, offset, size)
except:
print '?????????????????????????'
return value
def get_max_size(value):
_max_size_ = None
try:
debugger = value.GetTarget().GetDebugger()
_max_size_ = int(lldb.SBDebugger.GetInternalVariableValue('target.max-string-summary-length', debugger.GetInstanceName()).GetStringAtIndex(0))
except:
_max_size_ = 512
return _max_size_
It is expected that what you tried to do won't work. The summary strings feature does not allow calling expressions.
Calling expressions in a debugger is always interesting, in a data formatter more so (if you're in an IDE - say Xcode - formatters run automatically). Every time you stop somewhere, even if you just stepped over one line, all these little expressions would all automatically run over and over again, at a large performance cost - and this is not even taking into account the fact that your data might be in a funny state already and running expressions has the potential to alter it even more, making your debugging sessions trickier than needed.
If the above wall of text still hasn't discouraged you ( :-) ), you want to write a Python formatter, and use the SB API to run your expression. Your value is an SBValue object, which has access to an SBFrame and an SBTarget. The combination of these two allows you to run EvaluateExpression("blah") and get back another SBValue, probably a char* to which you can then ask GetSummary() to get your c-string back.
If, on the other hand, you are now persuaded that running expressions in formatters is suboptimal, the good news is that QString most certainly has to store its data pointer somewhere.. if you find out where that is, you can just write a formatter as ${var.member1.member2.member3.theDataPointer} and obtain the same result!
this is my trial-and-error adaptation of a UTF16 string interpretation lldb script I found online (I apologise that I don't remember the source - and that I can't credit the author)
Note that this is for Qt 4.3.2 and versions close to it - as the handling of the 'data' pointer has since changed between then and Qt 5.x
def QString_SummaryProvider(valobj, internal_dict):
data = valobj.GetChildMemberWithName('d')#.GetPointeeData()
strSize = data.GetChildMemberWithName('size').GetValueAsUnsigned()
newchar = -1
i = 0
s = u'"'
while newchar != 0:
# read next wchar character out of memory
data_val = data.GetChildMemberWithName('data').GetPointeeData(i, 1)
size = data_val.GetByteSize()
e = lldb.SBError()
if size == 1:
newchar = data_val.GetUnsignedInt8(e, 0) # utf-8
elif size == 2:
newchar = data_val.GetUnsignedInt16(e, 0) # utf-16
elif size == 4:
newchar = data_val.GetUnsignedInt32(e, 0) # utf-32
else:
s = s + '<unexpected char size - error parsing QString>'
break
if e.fail:
s = s + '<parse error:' + e.why() + '>'
break
i = i + 1
if i > strSize:
break
# add the character to our string 's'
# print "char2 = %s" % newchar
if newchar != 0:
s = s + unichr(newchar)
s = s + u'"'
return s.encode('utf-8')

Simplifying device creation in sip.conf

I often have to define many similar devices in sip.conf like this:
[device](!)
; setting some parameters
[device01](device)
callerid=dev01 <01>
[device02](device)
callerid=dev02 <02>
; ...
[deviceXX](device)
callerid=devXX <XX>
The question is perhaps I could avoid setting device-name specific parameters by using some variable like following?
[device](!)
callerid=dev${DEVICE_NAME:-2} <${DEVICE_NAME:-2}>
; setting some parameters
[device01](device)
[device02](device)
; ...
[deviceXX](device)
P.S.
It would be perfect, if there was some device constructor, so I could reduce the script to following, but, I think, that is not possible in Asterisk.
[device](!)
callerid=dev${DEVICE_NAME:-2} <${DEVICE_NAME:-2}>
; setting some parameters
;[device${MAGIC_LOOP(1,XX,leading_zeroes)}](device)
I've had good results writing a small program that takes care of it. It checks for a line saying something like
------- Automatically generated -------
and whatever is after that line, it's going to be regenerated as soon as it detects that there are new values for it (it could be from a database or from a text file). Then, I run it with supervisor and it checks every XX seconds if there are changes.
If there are changes, it issues a sip reload command after updating the sip.conf file
I wrote it in python, but whatever language you feel comfortable with should work just fine.
That's how I managed that and has been working fine so far (after a couple of months). I'd be extremely interested in learning about other approaches though. It's basically this (called from another script with supervisor):
users = get_users_logic()
#get the data that will me used on the sip.conf file
data_to_be_hashed = reduce(lambda x, y: x + y, map(lambda x: x['username'] + x['password'] + x['company_prefix'], users))
m = hashlib.md5()
m.update(str(data_to_be_hashed).encode("ascii"))
new_md5 = m.hexdigest()
last_md5 = None
try:
file = open(os.path.dirname(os.path.realpath(__file__)) + '/lastMd5.txt', 'r')
last_md5 = file.read().rstrip()
file.close()
except:
pass
# if it changed...
if new_md5 != last_md5:
#needs update
with open(settings['asterisk']['path_to_sip_conf'], 'r') as file:
sip_content = file.read().rstrip()
parts = sip_content.split(";-------------- BEYOND THIS POINT IT IS AUTO GENERATED --------------;")
sip_content = parts[0].rstrip()
sip_content += "\n\n;-------------- BEYOND THIS POINT IT IS AUTO GENERATED --------------;\n\n"
for user in users:
m = hashlib.md5()
m.update(("%s:sip.ellauri.it:%s" % (user['username'], user['password'])).encode("ascii"))
md5secret = m.hexdigest()
sip_content += "[%s]\ntype = friend\ncontext = %sLocal\nmd5secret = %s\nhost = dynamic\n\n" % (
user['username'], user['company_prefix'], md5secret)
#write the sip.conf file
f = open(settings['asterisk']['path_to_sip_conf'], 'w')
print(sip_content, file=f)
f.close()
subprocess.call('asterisk -x "sip reload"', shell=True)
#write the new md5
f = open(os.path.dirname(os.path.realpath(__file__)) + '/lastMd5.txt', 'w')
print(new_md5, file=f)
f.close()

how to automate uninstall of a program via autoit?

I am trying to uninstall a program from add or remove programs via an AutoIt script.
*I dont want to uninstall via removing the registry keys.
* I dont want to uninstall via running an uninstaller.
I can open "add remove programs" by a appwiz.cpl command
However I am failing to recognize the correct program name from the list and invoke an uninstall.
All I want to do is recognize my program from the list, for example "Helloworld" and invoke an uninstall.
You can just loop through all your corresponding Registry Values of which your uninstall list in your "Add or remove programs" is made of... And then directly extract the command that you want to execute. I display it in a Message Box in this example, but you could directly compare the DisplayName to "Helloworld" and then execute the UninstallString with Run(...). This is the exact same as your "Add or remove programs" would invoke. It doesn't mean simply removing registry keys. And it doesn't mean just running "any" uninstaller but the proper one, needed to exactly uninstall this very program like clicking the "Uninstall" button in appwiz.cpl will invoke. So to perform what you asked for as a result, this solution works just fine. It does not acutally handle the appwiz.cpl and cycle through the list of programs...
$uninstall_path1 = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall"
searchUninstallStrings($uninstall_path1)
$uninstall_path2 = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
searchUninstallStrings($uninstall_path2)
Func searchUninstallStrings($uninstall_path)
$i = 0
While True
$i += 1
Local $entry = RegEnumKey($uninstall_path, $i)
If #error <> 0 Then ExitLoop
$regPath = $uninstall_path & "\" & $entry
$DisplayName = RegRead($regPath, "DisplayName")
If $DisplayName <> "" Then
$message = $DisplayName & #CR
$UninstallString = RegRead($regPath, "UninstallString")
If $UninstallString <> "" Then
$message &= "Uninstall: '" & $UninstallString & "'"
MsgBox(4096, "SubKey #" & $i & ": " & $entry, $message)
EndIf
EndIf
WEnd
EndFunc
Good Luck!
I was able to successfully automate program uninstalls with the following command to open up the Programs and Features control panel menu followed by a series of keystrokes:
Run("C:\Windows\System32\control.exe appwiz.cpl")
WinWait("Programs and Features")
WinActivate("Programs and Features")
Send("ProgramNameHere")
Send("{Enter}")

Resources