AutoHotkey Community

It is currently May 27th, 2012, 1:19 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 56 posts ]  Go to page Previous  1, 2, 3, 4
Author Message
 Post subject:
PostPosted: October 29th, 2010, 8:16 pm 
Offline

Joined: February 6th, 2007, 12:30 am
Posts: 142
Location: Michigan
Where can I download version 1.2 of the script?
I need stderr output as well.

Do you plan to include stderr capture back into the latest version?


Report this post
Top
 Profile  
Reply with quote  
PostPosted: October 30th, 2010, 12:57 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7503
Location: Australia
dsz wrote:
Looks like it's crashing at a malloc call.
It's not really crashing, just detecting a false error and throwing up an "error" message.
Here, I wrote:
The "Out of memory" checks in malloc() and calloc() are unnecessary, since the thread will automatically exit if the script runs out of memory. To demonstrate:
Code:
VarSetCapacity(var, 2**31)
They do however cause problems since VarSetCapacity is not guaranteed to set the capacity to exactly the amount requested. For instance,
Code:
malloc(a, 8)
malloc(a, 4)
;or
malloc(b, 2)
It's more apparent in Unicode builds of AutoHotkey_L, where the minimum allocation is 8 bytes.

FYI, malloc() is mostly unneeded:
Quote:
CONSOLEAPPS_PRIVATE_malloc(hStdoutRead, 4)
...
if (!DllCall("CreatePipe", "uint", &hStdoutRead, ...
hStdoutRead := NumGet(hStdoutRead, 0, "uint")
Instead you should use just this:
Code:
if (!DllCall("CreatePipe", "uint*", hStdoutRead, ...
There are numerous occurrences of CONSOLEAPPS_PRIVATE_malloc(var, 4) that can similarly be avoided. In AutoHotkey_L, the ones that deal with pointers/handles should be "ptr*" (required for 64-bit support). Similarly, any "uint" parameters which accept handles/pointers would need to be "ptr".

There are likely to still be encoding issues, since command-line tools usually output 8-bit strings (possibly ANSI or an OEM code page). The solution would be something like this (assuming cp gets its value via "uint*", cp not the current "uint", &cp):
Code:
; stdout := stdout . buf
stdout .= StrGet(&buf, cp, "CP0")
This should also work with AutoHotkey Basic and the script version of StrGet, but it would be superfluous.

Any variables with names containing [ or ] must be renamed.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 6th, 2010, 12:59 pm 
Does anyone know why the launched application initiates, gives an error and then terminates? Look at the code below:
Code:
Console initialized.
FileSystem initialized.
Network initialized.
Master module initialized.
Server module initialized.
World module initialized.
Demo client initialized.
Proxy module initialized.
--> ***** FATAL ERROR *****
--> CTextConsoleWin32::GetLine: !GetNumberOfConsoleInputEvents
--> *** STOPPING SYSTEM ***
Failed to load Steam ServiceBOpenService failedServiceStart: failed to startMaster module shutdown.
Status module shutdown.
Demo module shutdown.
World module shutdown.
Server module shutdown.
Network shut down.
Proxy module shutdown.
I've put "-->" in the error lines.
This is the message box that appear after all that command-line output:
Code:
---------------------------
NewAutoHotKeyScript.ahk
---------------------------
The program has completed successfully.
---------------------------
OK   
---------------------------
I could do what I wanted, by not using the command line, and just spitting things out, but in slower machines, timing would be a problem. Just one small note: the executable that I try to start is not mine and I don't have access to it's source-code. Thanks for any input about that error.


Report this post
Top
  
Reply with quote  
 Post subject: Re: updated demo
PostPosted: February 1st, 2011, 8:37 am 
Offline

Joined: December 17th, 2010, 5:44 am
Posts: 8
Location: Missouri, United States
As a warning for others who might be have the same problem I did in getting these scripts to work:

Make sure you are using the ANSI version of AutoHotkey. I wasted many hours until I finally figured out that neither CMDret, nor ConsoleApps will work with the UNICODE version.

Also, is it still possible for drifter to edit the first post in this thread to update the information? A lot of forum posts have to be read to learn (on page 3) that the function names have changed and that the demo script in the first post will not work...

drifter wrote:
Function names have changed as per the following:
RunConsoleAppWait() is now ConsoleApp_RunWait()
RunConsoleApp() is now ConsoleApp_Run()
GetConsoleAppStdOut() is now ConsoleApp_GetStdOut()
CloseConsoleAppHandle() is now ConsoleApp_CloseHandle()


Guest_AutoHotkey_L wrote:
I have updated the demo from the original post, hopefully to work with the latest (ConsoleApps.2.1.1.zip at the time of this writing)...


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 1st, 2011, 9:35 am 
Offline

Joined: October 13th, 2009, 10:09 pm
Posts: 1389
You are drawing the wrong conclusion. Instead of using the ANSI version, this library should be updated to support UNICODE and x64. This is the only way for AHK to advance and get away from this compatibility mess. I'm having similar issues, but reverting to older versions of AHK can only be a temporary solution.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 3rd, 2011, 3:14 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
Murp|e wrote:
Can someone clarify the similarities/differences between this and cmdret?
Additional difference: Development of the AHK version of CMDret has been discontinued (the dll version is still updated occasionally) :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 6th, 2011, 5:33 am 
Offline

Joined: December 18th, 2009, 6:08 pm
Posts: 63
Drifter - thanks for this. its working perfect for what i need.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 6th, 2011, 8:12 am 
Offline
User avatar

Joined: November 7th, 2010, 2:48 am
Posts: 72
Location: Egret Island
Thanks for your work!

I think using WshShell Object maybe a better way. For details, please see:
[AHK&AHK_l]Using COM to interact with command-line progs

_________________
Recommended: AutoHotkey_L My code is based on it or similar versions, e.g. AutoHotkey_H.
Image
Together with AutoHotkey, we grow and march forward. No matter how the future will be, this period of days is still epic.


Report this post
Top
 Profile  
Reply with quote  
 Post subject: Re: updated demo
PostPosted: June 27th, 2011, 8:45 pm 
Offline

Joined: February 16th, 2010, 4:01 am
Posts: 60
xpace wrote:
A lot of forum posts have to be read to learn (on page 3) that the function names have changed and that the demo script in the first post will not work...

drifter wrote:
Function names have changed as per the following:
RunConsoleAppWait() is now ConsoleApp_RunWait()
RunConsoleApp() is now ConsoleApp_Run()
GetConsoleAppStdOut() is now ConsoleApp_GetStdOut()
CloseConsoleAppHandle() is now ConsoleApp_CloseHandle()



Here is the fixed demo:

Code:
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#Include ConsoleApps.ahk

;Create GUI window with an edit control to print the output.
Gui, Add, Edit, x15 y15 w460 h300 -Wrap ReadOnly hscroll vtxtStdout,
Gui, Show, w490 h330, Standard Input/Output Redirection Example

; Create the process
ConsoleAppHandle := ConsoleApp_Run("ConsoleApps_TestFile.bat -p nothing", A_ScriptDir)
; In reality, this function will never return with a ConsoleAppHandle value of 0, but
; it is good to check for this possibility in case future versions do return a value of
; 0 for failure.
if (ConsoleAppHandle == 0)
{
    MsgBox, Error running cmd.exe
    ExitApp
}

/* Continuously retrieve the process's output and write it to the edit control
 * in a loop as it arrives.
 */
Loop
{
    ; Append the ConsoleApps standard output to StdOut.
    ConsoleAppStillRunning := ConsoleApp_GetStdOut(ConsoleAppHandle, StdOut, BytesAppended, ExitCode)
    ; If StdOut was appended with new text, write it to the GUI window.
    if (BytesAppended)
       GuiControl, , txtStdOut, %StdOut%  ; append the output to the edit control.
    ; If the ConsoleApp is no longer running, then stop checking for output.
    if (!ConsoleAppStillRunning)
       break
    ; Give up remainder of time-slice to give the child process a chance to generate more output
    ; before checking again.
    sleep 0
}
; This function must be called when the ConsoleAppHandle is no longer needed.
ConsoleApp_CloseHandle(ConsoleAppHandle)
if (!ExitCode)
    MsgBox, The program has completed successfully.
else
    MsgBox, The program has exitted with an error code of %ExitCode%.
return

; The following label is receives control when the user closes the GUI window.
GuiClose:
ExitApp


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 12th, 2012, 3:05 pm 
Offline

Joined: October 27th, 2006, 10:12 am
Posts: 649
Can we use this for real-time plotting with gnuplot? See http://www.autohotkey.com/forum/viewtopic.php?t=80893 and http://www.autohotkey.com/forum/viewtop ... 941#503941


Report this post
Top
 Profile  
Reply with quote  
PostPosted: May 17th, 2012, 11:01 am 
Offline

Joined: November 20th, 2008, 6:00 pm
Posts: 72
Location: Thionville, France
I modified the code so that it works with AHK_L x32.
I'm still having troubles with AHK_L x64: CreatePipe function fails with error "invalid memory access". Does the child process have to be x64 too?
This version is not compatible with old AHK.
I also followed Lexicos' advices, a few posts above.
I added a parameter to the functions ConsoleApp_RunWait() and ConsoleApp_GetStdOut() to be able to specify the encoding of stdout so that it gets converted correctly to unicode. See AHK_L help on StrGet() for accepted values.

There is an example featuring unicode stdout (comspec /U switch) and regular stdout (CP850 - i.e. code page 850 - reproduced stdout of ping.exe correctly for me). Uncomment the first commented block to run the example.

I was not able to find out how to write to stdin, which might be useful in some cases.
Code:
; ConsoleApps V3
;
; AutoHotkey_L Version: 1.x
; Language:       English
; Platform:       Win9x/NT
; Original program from Marcus Cortes <macortes84@yahoo.com>
; Modified and optimized for AutoHotkey_L by Louis Blesch
;
; Script Function:
;   Provides a set of functions to redirect and capture
;   the standard input and output of other programs.
;
/*
; Uncomment to run the example
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
Gui, Add, Edit, W400 R20 vLog
Gui, Show
GuiControl, , Log, % so:=ConsoleApp_RunWait("cmd /U /c Echo 你好^|Привет^|Hi^|Hallo^|Salut&Echo.", "", "UTF-16")
hP:=ConsoleApp_Run("cmd /c ping -n 2 -w 700 1.2.3.4")
Loop
{
   sleep 250
   bRunning:=ConsoleApp_GetStdOut(hP, so, "CP850")
   GuiControl, , Log, %so%
   if !bRunning
      break
}
ConsoleApp_CloseHandle(hP)
msgbox The End
exitapp
*/

/*
<summary>
    Runs an application and retrieves its standard output.
</summary>
<param="CmdLine">
    The executable file to run including any path information and arguments.
</param>
<param="WorkingDir">
    The startup directory for the program.
</param>
<param="CharSet">
    The character set of stdout. This parameter is optional.
    Acceptable values : 0/empty=ASCII,1=UTF8,2=Unicode
</param>
<param="ExitCode">
    When the function returns, this parameter is set to the exit code of the program.
</param>
<returns>
    Returns the StdOut of the program.
</returns>
<remarks>
    The output of programs that are explicity redirected or "piped" in their command-lines will
    not be captured by this function (e.g. "cmd.exe /C echo Hello World > test.txt").
</remarks>
<example>
</example>
*/
ConsoleApp_RunWait(CmdLine, WorkingDir="", encoding="CP0", byref ExitCode="")
{
   global
   local ConsoleAppHandle, ConsoleAppStillRunning, StdOut, BytesAppended, FirstWin32Error

   ConsoleApps_Initialize()
   ; Create the process
   ConsoleAppHandle := ConsoleApp_Run(CmdLine, WorkingDir)
   ; In reality, this function will never return with a ConsoleAppHandle value of 0, but
   ; it is good to check for this possibility in case future versions do return a value of
   ; 0 for failure.
   if (ConsoleAppHandle = 0)
      CONSOLEAPPS_PRIVATE_throw(ERROR_GENERIC_ERROR, "Unable to run console application.")
   /* Continuously retrieve the process's output and write it to the edit control
    * in a loop as it arrives.
    */
   Loop
   {
      sleep 100
      ; Append the ConsoleApps standard output to StdOut.
      ConsoleAppStillRunning := ConsoleApp_GetStdOut(ConsoleAppHandle, StdOut, encoding, BytesAppended, ExitCode)
      ; If the ConsoleApp is no longer running, then stop checking for output.
      if (!ConsoleAppStillRunning)
         break
      ; Give up remainder of time-slice to give the child process a chance to generate more output
      ; before checking again.
   }
   ; This function must be called when the ConsoleAppHandle is no longer needed.
   ConsoleApp_CloseHandle(ConsoleAppHandle)
   return StdOut
}

/*
<summary>
    Runs an application and redirects its standard input/output handles such that they can be accessed
    from the script using the ConsoleApp_GetStdOut() function.
</summary>
<param="CmdLine">
    The executable file to run including any path information and arguments.
</param>
<param="WorkingDir">
    The startup directory for the program.
</param>
<param="Reserved">
    This parameter is reserved for future use and should be a null string ("") or should be omitted.
</param>
<param="PID">
    Specifies a variable to receive the ProcessID of the program. This parameter is optional.
</param>
<returns>
    Returns a proprietary handle to the ConsoleApp for use in calls to ConsoleApp_GetStdOut() and
    ConsoleApp_CloseHandle(). This handle cannot be specified in any Win32 API functions to identify
    a process.
</returns>
<remarks>
    If this function completes successfully, the handle returned by this function must be closed
    when no longer needed using the ConsoleApp_CloseHandle() function.
    The output of programs that are explicity redirected or "piped" in their command-lines will
    not be captured in calls to ConsoleApp_GetStdOut (e.g. "cmd.exe /C echo Hello World > test.txt").
</remarks>
<example>
</example>
*/
ConsoleApp_Run(CmdLine, WorkingDir="", byref PID="")
{
   global
   local sa, pi, si, lpCurrentDirectory
   local hStdoutRead, hStdoutWrite
;   local hStdinRead, hStdinWrite
   local FirstWin32Error
   local hHeap, lpCAPI
   static RedProcNextHandle := 1

   ConsoleApps_Initialize()

   CONSOLEAPPS_PRIVATE_calloc(pi, 16, 0) ;PROCESS_INFORMATION
   CONSOLEAPPS_PRIVATE_calloc(si, 4*18, 0) ;STARTUP_INFO
   NumPut(4*18,  si, 0, "uint") ;STARTUP_INFO {HANDLE cbSize}
   NumPut(0x100 | 0x1, si, 4*11, "uint") ;STARTUP_INFO {dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW}
   ;NumPut(0x0, si, 4*12, "ushort") ;STARTUP_INFO {wShowWindow = SW_HIDE}
   
   ;ALLOC AND INIT SECURITY_ATTRIBUTES STRUC
   CONSOLEAPPS_PRIVATE_calloc(sa, 12, 0) ;security attributes
   NumPut(12,  sa, 0, "uint")
   NumPut(0, sa, 4, "uint")
   NumPut(1, sa, 8, "int")
   
   ;CREATE PIPE FOR STDOUT
   ;NOTE: For some reason, CreatePipe works fine with x32 and fails with "invalid memory access" with x64
   if !DllCall("CreatePipe", "uint*", hStdoutRead, "uint*", hStdoutWrite, "ptr", &sa, "uint", 0)
      CONSOLEAPPS_PRIVATE_throw(CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR, "Unable to create stdout pipe: ")
   if (!DllCall("SetHandleInformation", "uint", hStdoutRead, "uint", 1, "uint", 0, "int"))
   {
      FirstWin32Error := A_LastError
      DllCall("CloseHandle", "uint", hStdoutRead) ;HANDLE hThread
      DllCall("CloseHandle", "uint", hStdoutWrite) ;HANDLE hThread
      CONSOLEAPPS_PRIVATE_throw(CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR, "Unable to set handle information: ", "", FirstWin32Error)
   }

/*
   ;CREATE PIPE FOR STDIN
   if (!DllCall("CreatePipe", "uint*", hStdinRead, "uint*", hStdinWrite, "ptr", &sa, "uint", 0))
   {
      FirstWin32Error := A_LastError
      DllCall("CloseHandle", "uint", hStdoutRead) ;HANDLE hThread
      DllCall("CloseHandle", "uint", hStdoutWrite) ;HANDLE hThread
      CONSOLEAPPS_PRIVATE_throw(CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR, "Unable to create stdin pipe: ", "", FirstWin32Error)
   }
   if (!DllCall("SetHandleInformation", "uint", hStdinWrite, "uint", 1, "uint", 0, "int"))
   {
      FirstWin32Error := A_LastError
      DllCall("CloseHandle", "uint", hStdoutRead) ;HANDLE hThread
      DllCall("CloseHandle", "uint", hStdoutWrite) ;HANDLE hThread
      DllCall("CloseHandle", "uint", hStdinRead) ;HANDLE hThread
      DllCall("CloseHandle", "uint", hStdinWrite) ;HANDLE hThread
      CONSOLEAPPS_PRIVATE_throw(CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR, "Unable to set handle information: ", "", FirstWin32Error)
   }
*/

   ;USE PIPE HANDLES FOR STDIO
   NumPut(hStdinRead, si, 4*14, "uint") ;STARTUP_INFO {HANDLE hStdInput}
   NumPut(hStdoutWrite, si, 4*15, "uint") ;STARTUP_INFO {HANDLE hStdOutput}
   NumPut(hStdoutWrite, si, 4*16, "uint") ;STARTUP_INFO {HANDLE hStdError}
   
   if (StrLen(WorkingDir) = 0)
      lpCurrentDirectory := 0
   else
      lpCurrentDirectory := &WorkingDir
   if (!DllCall("CreateProcess", "uint", 0
                               , "ptr", &CmdLine
                               , "uint", 0
                               , "uint", 0
                               , "int", true
                               , "uint", 0
                               , "uint", 0
                               , "uint", lpCurrentDirectory
                               , "ptr", &si
                               , "ptr", &pi))
   {
      FirstWin32Error := A_LastError
      DllCall("CloseHandle", "uint", hStdoutRead) ;HANDLE hThread
      DllCall("CloseHandle", "uint", hStdoutWrite) ;HANDLE hThread
;      DllCall("CloseHandle", "uint", hStdinRead) ;HANDLE hThread
;      DllCall("CloseHandle", "uint", hStdinWrite) ;HANDLE hThread
      CONSOLEAPPS_PRIVATE_throw(CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR, "Unable to run process: ", "", FirstWin32Error)
   }
   hProcess := NumGet(pi, 0, "uint")
   hThread := NumGet(pi, 4, "uint")
   PID := NumGet(pi, 8, "uint") ;DWORD dwProcessId
   DllCall("CloseHandle", "uint", hThread) ;HANDLE hThread
   
   ;    struct ConsoleAppsProcessInfo
   ;    {
   ;        int hProcess;
   ;        int hStdoutRead;
   ;        int hStdoutWrite;
   ;        //int hStdinRead;
   ;        //int hStdinWrite;
   ;    }
   hHeap := DllCall("GetProcessHeap", "uint")

   lpCAPI := DllCall("HeapAlloc", "uint", hHeap, "uint", 0, "uint", 0xC, "uint")
   
   NumPut(hProcess, lpCAPI + 0x0)
   NumPut(hStdoutRead, lpCAPI + 0x4)
   NumPut(hStdoutWrite, lpCAPI + 0x8)
   NumPut(hStdinRead, lpCAPI + 0xC)
   NumPut(hStdinWrite, lpCAPI + 0x10)

   return lpCAPI
}

/*
<summary>
    Retrieves the standard output of a ConsoleApp that was run using ConsoleApp_Run().
</summary>
<param="ConsoleAppHandle">
    A handle to a ConsoleApp that was created in a call to ConsoleApp_Run.
</param>
<param="Stdout">
    A variable that is to be appended with the standard output of the ConsoleApp. The
    variable is appended with all of the standard output of the program since the last
    call to ConsoleApp_GetStdOut.
</param>
<param="encoding">
    A string indicating the encoding of stdout. See AutoHotKey_L help on StrGet() for more information.
</param>
<param="bytesAppended">
    A variable that is to receive the number of bytes that were appended to the Stdout
    parameter.
</param>
<returns>
    Returns true if the ConsoleApp is still running.
    Returns false if the ConsoleApp is no longer running.
</returns>
<remarks>
    The output of programs that are explicity redirected or "piped" in their command-lines will
    not be captured by this function (e.g. "cmd.exe /C echo Hello World > test.txt").
</remarks>
<example>
</example>
*/
ConsoleApp_GetStdOut(ConsoleAppHandle, byref Stdout, encoding="CP0", byref BytesAppended = 0, byref ExitCode="")
{
   global
   local hProcess, hStdoutRead, buf, ec, cb, FirstWin32Error
   
   ConsoleApps_Initialize()

   hProcess := NumGet(ConsoleAppHandle + 0x0)
   hStdoutRead := NumGet(ConsoleAppHandle + 0x4)
;   hStdoutWrite := NumGet(ConsoleAppHandle + 0x8)
;   hStdinRead := NumGet(ConsoleAppHandle + 0xC)
;   hStdinWrite := NumGet(ConsoleAppHandle + 0x10)
   BytesAppended := 0
   Loop
   {
      DllCall("PeekNamedPipe", "uint", hStdoutRead, "uint", 0, "uint", 0, "uint", 0, "uint*", cb, "uint", 0)
      if !cb
         break
      if (!CONSOLEAPPS_PRIVATE_ReadFile(hStdoutRead, encoding, buf, cb, 1024))
      {
         FirstWin32Error := A_LastError
         ConsoleApp_CloseHandle(ConsoleAppHandle)
         CONSOLEAPPS_PRIVATE_throw(CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR, "Error reading process stdout: ", "", FirstWin32Error)
      }
      stdout .= buf
      BytesAppended += NumGet(cb, 0, "uint")
   }
   
   if (!DllCall("GetExitCodeProcess", "uint", hProcess, "uint*", ec))
   {
      FirstWin32Error := A_LastError
      ConsoleApp_CloseHandle(ConsoleAppHandle)
      CONSOLEAPPS_PRIVATE_throw(CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR, "Error getting process exit code: ", "", FirstWin32Error)
   }
   ExitCode := ec
   
   ; If the exit code of the process is STILL_ACTIVE (0x103) then the process is still running
   if (ExitCode = 0x103)
      return true
   return false
}

/*
<summary>
    Closes a ConsoleApp handle returned by ConsoleApp_Run()
</summary>
<param="ConsoleAppHandle">
    Handle to close.
</param>
<returns>
    This function does not return a value.
</returns>
<remarks>
    Every handle returned by a successful call to ConsoleApp_Run() must be closed
    with this function.
</remarks>
*/
ConsoleApp_CloseHandle(ConsoleAppHandle)
{
   global
   local hProcess, hStdoutRead, hStdOutWrite

   ConsoleApps_Initialize()

   hProcess := NumGet(ConsoleAppHandle + 0x0)
   hStdoutRead := NumGet(ConsoleAppHandle + 0x4)
   hStdoutWrite := NumGet(ConsoleAppHandle + 0x8)
   hStdinRead := NumGet(ConsoleAppHandle + 0xC)
   hStdinWrite := NumGet(ConsoleAppHandle + 0x10)
   ; If any of the following functions fail, then the ConsoleAppProcessInfo structure must
   ; not be valid, or has already been closed. In this case we raise an error to alert the
   ; user of a possible mis-handling of the handle and prevent further corruption and memory
   ; leaks.
   if (!DllCall("CloseHandle", "uint", hProcess)) ;HANDLE hThread
      CONSOLEAPPS_PRIVATE_throw(ERROR_GENERIC_ERROR, "Error ConsoleAppHandle is corrupt or has already been closed.")
   if (!DllCall("CloseHandle", "uint", hStdoutRead)) ;HANDLE hThread
      CONSOLEAPPS_PRIVATE_throw(ERROR_GENERIC_ERROR, "Error ConsoleAppHandle is corrupt or has already been closed.")
   if (!DllCall("CloseHandle", "uint", hStdoutWrite)) ;HANDLE hThread
      CONSOLEAPPS_PRIVATE_throw(ERROR_GENERIC_ERROR, "Error ConsoleAppHandle is corrupt or has already been closed.")
   /*
   if (!DllCall("CloseHandle", "uint", hStdinRead)) ;HANDLE hThread
      CONSOLEAPPS_PRIVATE_throw(ERROR_GENERIC_ERROR, "Error ConsoleAppHandle is corrupt or has already been closed.")
   if (!DllCall("CloseHandle", "uint", hStdinWrite)) ;HANDLE hThread
      CONSOLEAPPS_PRIVATE_throw(ERROR_GENERIC_ERROR, "Error ConsoleAppHandle is corrupt or has already been closed.")
   */
   hHeap := DllCall("GetProcessHeap", "uint")
   if (!DllCall("HeapFree", "uint", hHeap, "uint", 0, "uint", ConsoleAppHandle))
      CONSOLEAPPS_PRIVATE_throw(CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR, "Error deallocating heap. This is a serious error which can cause heap corruption. This program will now close. Specifically: ")
}


; +----------------------+
; | PRIVATE DECLARATIONS |
; +----------------------+

ConsoleApps_Initialize()
{
   global
   
   if (ConsoleApps_Initialized)
      Return
   ConsoleApps_Initialized := True
   
   CONSOLEAPPS_PRIVATE_EXIT_FAILURE := 1
   CONSOLEAPPS_PRIVATE_MAXIMUM_INTEGER := 0x7FFFFFFF  ; 2147483647
   CONSOLEAPPS_PRIVATE_MAXIMUM_UNSIGNED_INTEGER := 0xFFFFFFFF  ; 4294967295

   CONSOLEAPPS_PRIVATE_ERROR_NOT_ENOUGH_MEMORY := 0x8
   CONSOLEAPPS_PRIVATE_ERROR_INVALID_PARAMETER   := 0x57
   CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR := CONSOLEAPPS_PRIVATE_MAXIMUM_UNSIGNED_INTEGER + 1

   CONSOLEAPPS_PRIVATE_STD_ERROR_CODES_%CONSOLEAPPS_PRIVATE_ERROR_NOT_ENOUGH_MEMORY% := "Not enough storage is available to process this command."
   CONSOLEAPPS_PRIVATE_STD_ERROR_CODES_%CONSOLEAPPS_PRIVATE_ERROR_INVALID_PARAMETER% := "Invalid parameter value."
   CONSOLEAPPS_PRIVATE_STD_ERROR_CODES_%CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR% := "Unspecified exception."
}

;bufferSize includes a terminating 16-bit null character.
CONSOLEAPPS_PRIVATE_ReadFile(hFile, encoding="CP0", byref buf="", byref bytesRead=0, bufferSize=4096)
{
   if (bufferSize <= 2)
      return false
   if (VarSetCapacity(buf, bufferSize) < bufferSize)
      CONSOLEAPPS_PRIVATE_throw(CONSOLEAPPS_PRIVATE_ERROR_NOT_ENOUGH_MEMORY)
   if (!DllCall("ReadFile", "uint", hFile, "ptr", &buf, "uint", bufferSize-2, "uint*", bytesRead, "uint", 0))
      return false
   NumPut(0, buf, bytesRead, "ushort")  ;UTF-16 null terminator
   VarSetCapacity(buf, -1)
   buf := StrGet(&buf, encoding)
   return true
}

CONSOLEAPPS_PRIVATE_abort()
{
   global
   Critical, %CONSOLEAPPS_PRIVATE_MAXIMUM_INTEGER%
   CONSOLEAPPS_PRIVATE_STD_Exiting := True
   OnExit
   BlockInput, MouseMoveOff
   BlockInput, Off
   ExitApp, %CONSOLEAPPS_PRIVATE_EXIT_FAILURE%
}

CONSOLEAPPS_PRIVATE_calloc(byref Var, size, fillbyte=0)
{
   global
   local cb
   if (cb := VarSetCapacity(Var, size, fillbyte) < size)
      CONSOLEAPPS_PRIVATE_throw(CONSOLEAPPS_PRIVATE_ERROR_NOT_ENOUGH_MEMORY)
   return cb
}

; ParamName is only valid if ErrorCode is CONSOLEAPPS_PRIVATE_ERROR_INVALID_PARAMETER
; LastWin32Error is only necessary if ErrorCode is CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR
; and the A_LastError built-in variable is no longer valid.
CONSOLEAPPS_PRIVATE_throw(ErrorCode, ErrorMessage="", ParamName="", LastWin32Error="")
{
   global
   local lpMsg
   Critical, %CONSOLEAPPS_PRIVATE_MAXIMUM_INTEGER%
   if (ErrorCode = CONSOLEAPPS_PRIVATE_ERROR_INVALID_PARAMETER)
   {
      if (StrLen(ErrorMessage) = 0)
         ErrorMessage := CONSOLEAPPS_PRIVATE_STD_ERROR_CODES_%ErrorCode%
      if (StrLen(ParamName) != 0)
         ErrorMessage .= "\nParameter: " . ParamName
   }
   else if (ErrorCode = CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR)
   {
      if (StrLen(ErrorMessage) = 0)
         ErrorMessage := CONSOLEAPPS_PRIVATE_STD_ERROR_CODES_%ErrorCode%
      if (StrLen(LastWin32Error) = 0)
         LastWin32Error := A_LastError
 ;varsetcapacity(lpMsg,4)
      if !(DllCall("FormatMessage"
     , "uint", 0x1300
     , "uint", 0
     , "uint", LastWin32Error
     , "uint", ((1 << 10) | 0)
     , "uint*", lpMsg
     , "uint", 0
     , "uint", 0, "uint"))
         ErrorMessage .= CONSOLEAPPS_PRIVATE_STD_ERROR_CODES_%CONSOLEAPPS_PRIVATE_ERROR_WIN32_ERROR%
      else
      {
         ErrorMessage .= DllCall("MSVCRT\memcpy", "uint", lpMsg, "uint", 0, "uint", 0, "str")
         DllCall("LocalFree", "uint", lpMsg)
         VarSetCapacity(lpMsg, 0)
      }
   }
   else
   {
      if (StrLen(ErrorMessage) = 0)
         ErrorMessage := CONSOLEAPPS_PRIVATE_STD_ERROR_CODES_%ErrorCode%
   }
   MsgBox, 0x1010, %A_ScriptName%, %ErrorMessage%
   CONSOLEAPPS_PRIVATE_abort()
}


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 56 posts ]  Go to page Previous  1, 2, 3, 4

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bon and 15 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group