Hi. Thanks for this great script SKAN. I'm using it successfully in a project which makes use of the Spotify Web API and curl to make server calls to retrieve track information (artist, album, duration, progress etc) and display these in a permanent GUI on a second monitor. These details come back in the form of a JSON response which I then store to my variable 'Output' and parse.
c="https api.spotify.com /v1/me/player" Broken Link for safety
d="Accept: application/json"
e="Content-Type: application/json"
f:="Authorization: Bearer " . token2 ""
g="%f%"
mX:="curl -s -X GET " . c " -H " . d " -H " . e " -H " . g ""
SetTimer, UpdateTime, 200 ; this frequency is necessary to implement track timer functionality
UpdateTime:
Output:=RunCMD(mX)
--- bunch of parsing code ---
return
The only problem with this implementation is that it causes a continual spike in the 'Antimalware Service Executable'. On my modestly specced machine it averages around 5%. I appreciate that figure is not ridiculously high but i thought it worth asking if anyone had any suggestions for improving efficiency or perhaps could suggest a completely different approach. I have tried adding the relevant programs as exclusions in Windows Security to no avail. I also have a version of my project which hands off this portion of code to Python which doesn't upset the antivrus at all but does seem like an ugly workaround.
PS. The only modification i've made to RunCMD v0.94 is changing the Sleep integer to "1"
What about using an implementation of MSXML2 directly? HEres my [gross] implementation of it, which i use for all sorts of API calls with AHK, rather using curl through a cmd prompt.
sendstring(type, url, body="", Headers="", URLParams="") {
pwhr := comobjcreate("MSXML2.ServerXMLHTTP")
for k,v in URLParams
Params .= k "=" v "&"
url := (isobject(URLParams)) ? url "?" substr(params,1,-1) : url
pwhr.open(type, url, false)
for k,v in Headers
pwhr.setrequestheader(k,v)
if isobject(body)
{
for k,v in body
{
for k1,v1 in v
body .= k1 "=" v1 "&"
}
body:=substr(body,1,-1)
}
pwhr.Send(body)
Response := pwhr.Responsetext
return, Response
}
Thanks for expanding on your earlier example. Not had a chance to test it yet but no doubt it will save me a lot of time. I am using the 'non-blocking' version of RunCMD but until I properly implement your suggestion I can't say for sure if this is a working solution. I shall report back! Your help is greatly appreciated.
RunCMD() is a rewrite and renamed version of my old StdOutToVar() which was adapted from Sean's StdoutToVar
RunCMD( CmdLine, WorkingDir, Codepage, Fn ) RunCMD() runs a console utility in windowless mode and captures its output one line at a time, concatenates them and returns the complete text.
The lines that are read maybe redirected to a helper function for pre-process. Within the helper functions individual lines they maybe omitted or reformatted.
Unlike previous versions, the current RunCMD() v0.93 reads from a non-blocking pipe enabled via PIPE_NOWAIT flag passed to SetNamedPipeHandleState()
During the lifetime of the created process, a global array element A_Args.RunCMD.PID will contain the PID and assigning a 0 (false) to this element will cancel RunCMD().
The created process will inherit the Priority of the script. Therefore Process, Priority,, High maybe used in scripts to see some marginal improvement.
Parameters:
CmdLine : The command line to be executed.
WorkingDir : Use this parameter to specify Working Directory. If omitted the launched process will default to A_WorkingDir.
Codepage : Default is Cp0. Use UTF-8 or UTF-16 when dealing with unicode.
Fn : Helper function name. When a helper function is available, RunCMD() will call it with two parameters Line, LineNum.
You may control the output within the helper function.
MsgBox % StrSplit(RunCmd("WMIC OS get version"), "`n", "`r ").2 ; OS version
MsgBox % RunCmd(A_ComSpec . " /c ftype AutoHotkeyScript") ; executable for .ahk files
MsgBox % RunCmd("Where user32.dll") ; fullpath to user32.dll
MsgBox % RunCmd( A_Comspec . " /c Dir *.* /s", A_AhkPath . "\..\") ; AutoHotkey files
Example using a helper function:
The following function code fetches the IP address of autohotkey.com. It ignores the first line, pre-process' the second line and immediately cancels RunCMD().
An advanced example:
A wrapper function that uses RunCMD() for retrieving External IP address. This function skips 5 lines and pre-process' only the last/6th line.
One potential problem you face is trying to RunWait on adb.exe. ADB actually never terminates. So if the process does not exist, and is then run with RunWait, your last line will never actually execute until ADB terminates.
SKAN gave you the best solution. Of course, if ADB is run for the first time, there is an unavoidable delay while the ADB server starts up the first time. But after that the return will be basically instant.