Is there any way to embed a CMD / Console in a GUI?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Is there any way to embed a CMD / Console in a GUI?

Post by kyuuuri » 05 Mar 2020, 01:10

Introduction
Hello, I'm trying to embed a CMD in a GUI window (probably using setParent or something) but had no luck. I tried some codes I found on the old forum but they do not work.

Why?
I want to run UPX.exe and be able to show the output on a GUI.

Example
Image

What I tried
WScript.Shell
Spoiler
Doesn't show that "progress" line that you can see on the gif.


Lexikos' code from https://autohotkey.com/board/topic/42308-embedding-a-console-window-in-a-gui/:
Spoiler
The Console window simply dissappears.


garry
Posts: 3740
Joined: 22 Dec 2013, 12:50

Re: Is there any way to embed a CMD / Console in a GUI?

Post by garry » 10 Mar 2020, 16:43

ask again , how to add a DOS window to a GUI
here an example with WGET , see process in GUI edit (copies DOS Window and send to Edit )

Code: Select all

;MODIFIED = 20200310
;CREATED  = 20200310
;FILE     = see wget download in GUI / downloads a MP3-file to > a_desktop . "\Downloads"

Gui,2:default
Gui,2: -DPIScale
Gui,2:color,black,black
Gui,2:Font,s12 cYellow,Lucida Console
DetectHiddenWindows On
wa:=A_screenwidth
ha:=A_screenHeight
xx:=100

;-------------------- test for WGET.exe --------------------------------
;f1:="http://74.136.132.35/MUSIC/RHAPSODY/J/Johnny%20Horton/American%20Originals/02%20-%20North%20To%20Alaska.mp3"
f1:="http://peterchen.nicerweb.net/songs/Chinese/Chinese3/Mei%20Gui%20Mei%20Gui%20Wo%20Ai%20Ni.mp3"
SplitPath,f1, name, dir, ext, name_no_ext, drive
name:= URLdecode(name)
wget1  =%a_scriptdir%\wget.exe
 loop,%wget1%                                 ;- create shortpath
   SP1= %A_loopFileShortPath%
folderx2:= a_desktop . "\Downloads"
ifnotexist,%folderx2%
 filecreatedir,%folderx2%
f2  := folderx2 . "\" . name           ;- where file
VAR     =%sp1%  --output-document="%f2%" %f1%
;Runwait,%comspec% /k %var%
;exitapp
;----------------------------------------------------------------------

x:=(wa*1)/xx,y:=(ha*1)/xx,h:=(ha*3)/xx,w:=(wa*70)/xx
Gui,2:Add, Edit  , x%x%  y%y%   h%h%   w%w% vVAR ,%VAR%
x:=(wa*72)/xx,y:=(ha*1)/xx,h:=(ha*2.5)/xx,w:=(wa*5)/xx
Gui,2:Add, Button, x%x%  y%y%  w%w%  h%h%  gSTART1,Start

x:=(wa*1)/xx,y:=(ha*10)/xx,h:=(ha*50)/xx,w:=(wa*70)/xx
Gui,2:Add,Edit, x%x%   y%y%  h%h%  w%w% vED1 cYellow,
Gui,2:add,Text,x0 y0 w0 h0 vTT
x:=(wa*.1)/xx,y:=(ha*.1)/xx,h:=(ha*70)/xx,w:=(wa*80)/xx
Gui,2:Show, x%x% y%y% w%w% h%h% ,SendToDOS & Copy
GuiControl,2:Focus,TT
return
;----------------------------------------------

2Guiescape:
2Guiclose:
xx=wget.exe
process,exist,%xx%
pps:=errorlevel
if pps<>0
 Process, Close, %pid2%
exitapp
;----------------------------------------------
start1:
gui,2:submit,nohide
GuiControl,2:,ED1,
settimer,aa,1100
;Runwait,%sp1% --output-document="%f2%" %f1% -o logfile.txt ,,hide,pid2
Runwait,%var%,,hide,pid2
settimer,aa,off
GuiControl,2:,ED1,ENDED`nNow Start file = %name%
try
run,%f2%
return
;----------------------------------------------
aa:
gui,2:submit,nohide
WinActivate ahk_pid %PID2%
ClipBoard =
send,^a{Enter}                      ;- <<< copy hidden DOS Windows-10
ClipWait
GuiControl,2:,ED1,%Clipboard%
return
;----------------- URL-DECODE ------------------
URLdecode(str) {
   Loop
      If RegExMatch(str, "i)(?<=%)[\da-f]{1,2}", hex)
         StringReplace, str, str, `%%hex%, % Chr("0x" . hex), All
      Else Break
   Return, str
}
return
;================= END SCRIPT WGET =============================
Last edited by garry on 12 Mar 2020, 15:16, edited 1 time in total.

kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Is there any way to embed a CMD / Console in a GUI?

Post by kyuuuri » 10 Mar 2020, 17:30

Hello, I don't understand your code. I read it like 10 times and still don't see about the DOS window being embedded into the GUI

guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: Is there any way to embed a CMD / Console in a GUI?

Post by guest3456 » 10 Mar 2020, 18:51

lexikos' code works for me


garry
Posts: 3740
Joined: 22 Dec 2013, 12:50

Re: Is there any way to embed a CMD / Console in a GUI?

Post by garry » 11 Mar 2020, 03:25

@guest3456 thank you , get error at start , must check it
@kyuuuri, it's not a DOS window, only a GUI with edit, script copies the running DOS window every second and show copied window in edit ( windows-10 / german )
check this line > send,^a{Enter} ;- <<< copy hidden DOS Windows-10 / german
or can add a GUI and attach DOS window
I'll try lexikos script ...

screenshot from script above :
Image

garry
Posts: 3740
Joined: 22 Dec 2013, 12:50

Re: Is there any way to embed a CMD / Console in a GUI?

Post by garry » 11 Mar 2020, 05:59

have no success with lexikos's script
here a GUI with attached DOS , wget.exe test ( check first the path from wget.exe )

Code: Select all

;modified = 20200311
;created  = 20200311
;ahk-file = movetogether/attach from user wolf-II / GUI with attached DOS Window / wget.exe test , download a mp3-file to Downloadfolder
;Windows  = windows-10
;------------------------------------------

#NoEnv
setworkingdir,%a_scriptdir%
wa:=a_screenwidth
ha:=a_screenheight
xx:=100
Handles := []
;------------ ahk script  --------------------
   ;- create ahk GUI
   Gui,2: New, hwndhwin1, Window 1
   Gui,2: -DPIScale
   SS_REALSIZECONTROL := 0x40
   Gui,2:default
   Gui,2:Color,Black,Black
   Gui,2:Font,s12 cYellow ,Lucida Console
   ;------------------------------------------------------
   x:=(wa*1)/xx,y:=(ha*1)/xx,w:=(wa*9)/xx,h:=(ha*2.7)/xx
   Gui,2:add,Button,x%x% y%y% w%w% h%h% gWgetrun,WGET TEST
   ;------------------------------------------------------
   x:=(wa*11)/xx
   Gui,2:add,Button,x%x% y%y% w%w% h%h% gTEST01,VERSION
   ;------------------------------------------------------
   x:=(wa*21)/xx
   Gui,2:add,Button,x%x% y%y% w%w% h%h% gOpenFolder,DownloadFolder
   ;------------------------------------------------------
   x:=(wa*.1)/xx,y:=(ha*.1)/xx,w:=(wa*95)/xx,h:=(ha*10)/xx
   Gui,2:Show,       x%x% y%y% w%w% h%h%,Drag & Close here
   Handles.Push(hwin1)
;----------- next-attached window > DOS ----------
title2=AutoHotkey DOS
;Run, %COMSPEC% /S /U /Q /E:ON /F:ON /T:0A /k "title %title2% & mode con lines=32400 cols=120&CD %a_desktop%&@echo off&ver&vol&chcp&@echo ======== Hello %a_username% ==================&CD",,,pid2   ; define title / lines / colons / color
Run, %COMSPEC% /S /U /Q /E:ON /F:ON /T:0A /k "title %title2% & @echo off&ver&vol&chcp&@echo ======== Hello %a_username% ==================&CD\&date /t&time /t",,,pid2   ; define title / color
;-------------------------------------------------
WinWaitActive, ahk_pid %pid2%
x:=(wa*.1)/xx,y:=(ha*11.5)/xx,w:=(wa*95)/xx,h:=(ha*82)/xx
WinMove, ahk_pid %pid2%, , x,y,w,h                            ;- move DOS to the right position
IfWinNotActive ,ahk_pid %pid2%,,WinActivate,ahk_pid %pid2%    ;- Activate DOS
  WinWaitActive,ahk_pid %pid2%
;controlsend,,time /t`n,ahk_pid %pid2%
Handles.Push(WinExist("A"))                                   ;- DOS is lastactive
MoveTogether(Handles)
settimer,closethisscript,500                                  ;- close this script also if DOS was closed
Return
;-------------------------------------------------------------------------------------------------------------
closethisscript:
process, exist, %PID2%
 status1 = %ErrorLevel%
if (status1 = 0)          ;- close this ahk-script if PID2 ( DOS ) not exist
  exitapp
return
;-----------------------------------
2Guiclose:                                                     ;- when close GUI close also attached DOS
WinClose, ahk_pid %pid2%             
WinWaitClose,ahk_pid %pid2%
exitapp
;------------------------------------
checkwget:
xx=wget.exe
process,exist,%xx%
pps:=errorlevel
if pps=0
  {
  settimer,checkwget,off
  msgbox, 262208,WGET-Check ,WGET.exe ended,2
  Run,C:\users\%a_username%\downloads
  }
return
;------------------------------------

test01:
WinActivate, ahk_pid %PID2%
send,ver`n
return
;------------------------------------
OpenFolder:
Run,C:\users\%a_username%\downloads
return
;------------------------------------
wgetrun:
;f1:="http://74.136.132.35/MUSIC/RHAPSODY/J/Johnny%20Horton/American%20Originals/02%20-%20North%20To%20Alaska.mp3"
f1:="http://peterchen.nicerweb.net/songs/Chinese/Chinese3/Mei%20Gui%20Mei%20Gui%20Wo%20Ai%20Ni.mp3"
SplitPath,f1, name, dir, ext, name_no_ext, drive
name:= URLdecode(name)
wget1=D:\M_GARRY\PROGRAMME_SA\WGET\wget.exe   ;- <<<<<  check path from wget.exe
 loop,%wget1%                                 ;-        create shortpath
   SP1= %A_loopFileShortPath%
folderx2=C:\users\%a_username%\downloads
f2=%folderx2%\%name%
;Runwait,%sp1% --output-document="%f2%" %f1% -o logfile.txt ,,hide,pid2
;Run,%sp1%  --output-document="%f2%" %f1%,,hide,pid2
WinActivate, ahk_pid %PID2%
clipboard=cls&%sp1% --output-document="%f2%" %f1%
send,^v`n
clipboard=
settimer,checkwget,500
return
;------------------------------------

;----------------- URL-DECODE ------------------
URLdecode(str) {
   Loop
      If RegExMatch(str, "i)(?<=%)[\da-f]{1,2}", hex)
         StringReplace, str, str, `%%hex%, % Chr("0x" . hex), All
      Else Break
   Return, str
}
return
;----------------------------------------------

;----------- ATTACH from user 'wolf_II' ----------------------------------------
MoveTogether(wParam, lParam = "", _ = "", hWnd = "") { ; using DeferWindowPos
;-------------------------------------------------------------------------------
    ; call MoveTogether(Handles) with an array of handles
    ; to set up a bundle of AHK Gui's that move together
    ;---------------------------------------------------------------------------
    ; https://autohotkey.com/boards/viewtopic.php?p=199402#p199402
    ; version 2018.02.08

    static init := OnMessage(0xA1, "MoveTogether") ; WM_NCLBUTTONDOWN
    static Handles

	If IsObject(wParam)             ; detect a set up call
		Return, Handles := wParam   ; store the array of handles

    If (wParam != 2) ; HTCAPTION
        Return

    ; changing AHK settings here will have no side effects
    CoordMode, Mouse, Screen    ; for MouseGetPos
    SetBatchLines, -1           ; for onMessage
    SetWinDelay, -1             ; for WinActivate, WinMove

    M_old_X := lParam & 0xFFFF, M_old_Y := lParam >> 16 & 0xFFFF
    WinActivate, ahk_id %hWnd%

    Win := {}
    For each, Handle in Handles {
        WinGetPos, X, Y, W, H, ahk_id %Handle%
        Win[Handle] := {X: X, Y: Y, W: W, H: H}
    }

    While GetKeyState("LButton", "P") {
        MouseGetPos, M_new_X, M_new_Y
        dX := M_new_X - M_old_X, M_old_X := M_new_X
      , dY := M_new_Y - M_old_Y, M_old_Y := M_new_Y

        If GetKeyState("Shift", "P")
            WinMove, ahk_id %hWnd%,, Win[hWnd].X += dX, Win[hWnd].Y += dY

        Else { ; DeferWindowPos cycle
            hDWP := DllCall("BeginDeferWindowPos", "Int", Handles.Length(), "Ptr")
            For each, Handle in Handles
                hDWP := DllCall("DeferWindowPos", "Ptr", hDWP
                    , "Ptr", Handle, "Ptr", 0
                    , "Int", Win[Handle].X += dX
                    , "Int", Win[Handle].Y += dY
                    , "Int", Win[Handle].W
                    , "Int", Win[Handle].H
                    , "UInt", 0x214, "Ptr")
            DllCall("EndDeferWindowPos", "Ptr", hDWP)
        }
    }
}
;=================================== END script ====================================
Last edited by garry on 12 Mar 2020, 15:17, edited 1 time in total.

kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Is there any way to embed a CMD / Console in a GUI?

Post by kyuuuri » 11 Mar 2020, 08:01

Hi, your example gave me an idea. But now I found another problem haha.
Image
When I use setParent the child window (cmd) will go behind the parent and I can't bring it back with winActivate nor with winSet, Top

@edit: Using WinMove to resize the window will bring it back to front!!. It works, thank you all for your help!

@edit2: Do you know any way to prevent input on that window? (I'm trying to avoid intercepting the input, I want to know if there is something like "disable window", some style or some parameter on CMD that disables input)
The idea is that it will show the output of what the script is doing but I don't want the user to be able to type in there.

garry
Posts: 3740
Joined: 22 Dec 2013, 12:50

Re: Is there any way to embed a CMD / Console in a GUI?

Post by garry » 12 Mar 2020, 06:08

example DOS commands display in GUI edit

Code: Select all

;-------- saved at Donnerstag, 12. März 2020 19:58:22 --------------
;- Is there any way to embed a CMD  Console in a GUI 
;- https://www.autohotkey.com/boards/viewtopic.php?f=76&t=73221

#warn
setworkingdir,%a_scriptdir%
Gui,2:default
Gui,2: -DPIScale
Gui,2:color,black,black
Gui,2:Font,s12 cYellow,Lucida Console
DetectHiddenWindows On
autotrim,off
transform,s,chr,32
wa:=A_screenwidth
ha:=A_screenHeight
xx:=100

DllCall("AllocConsole")
;DllCall("AttachConsole")
;DllCall("AttachConsole", "UInt", pid)
WinHide % "ahk_id " DllCall("GetConsoleWindow", "ptr")
;WinMinimize % "ahk_id " DllCall("GetConsoleWindow", "uint")


objShell := ComObjCreate("WScript.Shell")
;---------------
gosub,readLB
;---------------
x:=(wa*1)/xx ,y:=(ha*1)/xx,h:=(ha*50)/xx,w:=(wa*10)/xx
Gui,2:Add,Listbox,x%x%   y%y% w%w% h%h%  vLB1 gLB1,%e1x%
x:=(wa*12)/xx,y:=(ha*1)/xx,h:=(ha*50)/xx,w:=(wa*68)/xx
Gui,2:Add,Edit, x%x%   y%y%  h%h%  w%w% vED1 cYellow,
x:=(wa*.1)/xx,y:=(ha*.1)/xx,h:=(ha*53)/xx,w:=(wa*80)/xx
Gui,2:Show, x%x% y%y% w%w% h%h% ,DOS-HELP
return
;----------------------------------------------
2Guiescape:
2Guiclose:
DllCall("FreeConsole")
sleep,200
exitapp
;----------------------------------------------
;----------------------------------------------
lb1:
gui,2:submit,nohide
GuiControl,2:,ED1,
objExec := objShell.Exec(ComSpec " /c  " . lb1 . "`n")
cl:=""
while, !objExec.StdOut.AtEndOfStream
    cl:= objExec.StdOut.ReadAll()
GuiControl,2:,ED1,%Cl%
cl:=""
return
;----------------------------------------------
;----------------------------------------------
readLB:
;--------------------- DOS commands -----
fcdm=%a_scriptdir%\doscommands_new2.txt
ifnotexist,%fcdm%
   runwait,%comspec% /c help >"%fcdm%",,hide,
;-----------------------------------------
i=0
e1x:=""
fileread,a,%fcdm%
   loop,parse,a,`n,`r           ;- parse each line
   {
   i++
   if (i<3)                     ;- remove at least the first two lines from help
     continue
   y1=%a_loopfield%
   stringmid,y2,y1,1,3
   if (y1="" or y2="   ")
     {
     y1=
     y2=
     continue
     }
   c1=
   stringsplit,c,y1,%s%
   if (c1="dir" or c1="ver" or c1="path" or c1="chcp")
     e1x .= c1 . "|"
   e1x .= c1 . " /?|"
   }
a=
return
;================= END SCRIPT ================================================
esc::exitapp
here the same with more commands

Code: Select all

#warn
setworkingdir,%a_scriptdir%
Gui,2:default
Gui,2: -DPIScale
Gui,2:color,black,black
Gui,2:Font,s12 cYellow,Lucida Console
DetectHiddenWindows On
autotrim,off
transform,s,chr,32
transform,q,chr,34

wa:=A_screenwidth
ha:=A_screenHeight
xx:=100

DllCall("AllocConsole")
;DllCall("AttachConsole")
;DllCall("AttachConsole", "UInt", pid)
WinHide % "ahk_id " DllCall("GetConsoleWindow", "ptr")
;WinMinimize % "ahk_id " DllCall("GetConsoleWindow", "uint")


objShell := ComObjCreate("WScript.Shell")



;---------------
gosub,readLB
;---------------
/*
x:=(wa*1)/xx,y:=(ha*1)/xx,w:=(wa*6)/xx,h:=(ha*2.4)/xx
Gui,2:Add,Button,x%x%   y%y% w%w% h%h% gWgetRun,WGET-RUN
x:=(wa*7.5)/xx,y:=(ha*1)/xx,w:=(wa*8)/xx,h:=(ha*2.4)/xx
Gui,2:Add,Edit  ,x%x%   y%y% w%w% h%h% vWGETinfo cYellow,
*/
;--------------
x:=(wa*1)/xx,y:=(ha*1)/xx,w:=(wa*6)/xx,h:=(ha*2.4)/xx
Gui,2:Add,Button,x%x%   y%y% w%w% h%h% gTEST01,TEST-01


x:=(wa*1)/xx,y:=(ha*5)/xx,h:=(ha*50)/xx,w:=(wa*10)/xx
Gui,2:Add,Listbox,x%x%   y%y% w%w% h%h%  vLB1 gLB1,%e1x%
x:=(wa*12)/xx,y:=(ha*5)/xx,h:=(ha*50)/xx,w:=(wa*77)/xx
Gui,2:Add,Edit, x%x%   y%y%  h%h%  w%w% vED1 cYellow,
x:=(wa*.1)/xx,y:=(ha*.1)/xx,h:=(ha*70)/xx,w:=(wa*89)/xx
Gui,2:Show, x%x% y%y% w%w% h%h% ,SendToDOS & Copy
return
;----------------------------------------------
2Guiescape:
2Guiclose:
DllCall("FreeConsole")
sleep,200
exitapp
;----------------------------------------------
test01:
gosub,ping
return

;----------------------------------------------
ping:
Gui,2:submit,nohide
objExec := objShell.Exec("cmd /c ping -n 3 -w 1000 autohotkey.com")
output:=""
while,!objExec.StdOut.AtEndOfStream
  {
  GuiControlGet,ED1
  ;-----------------------------------------
  output.=objExec.StdOut.readline() . "`n"
  ;-----------------------------------------
  GuiControl,2:,ED1,%output%
  }
;GuiControl,2:,ED1,%output%
output=
return
;--------------------------------
;==================== DOS HELP ================
lb1:
gui,2:submit,nohide
GuiControl,2:,ED1,
lb1=%lb1%
stringmid,pingx,lb1,1,4

if (lb1="ping /?")
 {
 gosub,exec
 return
 }

if (pingx="ping")
 {
 gosub,ping
 return
 }

;- run#xxx
stringmid,lb1a,lb1,1,1
if (lb1a="#")
  {
  stringtrimleft,lb1,lb1,1
  try {
  run,%lb1%
  } catch {
    erl:= errorlevel
    msgbox, 262208,ERROR,Not found =%lb1%`nERROR=%erl%
  }
 return
 }

;------ change directories and open folder ----
if lb1 contains % "cd "
{
k1:=""
k2:=""
stringsplit,k,lb1,`;,
stringmid,str1,k2,1,2
if (str1="::")
  {
  run, "%k2%"
  return
  }
if k2<>
 {
 run,%k2%
 return
 }
;gosub,exec
return
}
gosub,exec
return


exec:
objExec := objShell.Exec(ComSpec " /c  " . lb1 . "`n")
cl:=""
while, !objExec.StdOut.AtEndOfStream
    cl:= objExec.StdOut.ReadAll()
GuiControl,2:,ED1,%Cl%
cl:=""
return
;-----------------------------------------------

;----------------------------------------------
readLB:
;--------------------- DOS commands -----
fcdm=%a_scriptdir%\doscommands_new2.txt
ifnotexist,%fcdm%
   runwait,%comspec% /c help >"%fcdm%",,hide,
;-----------------------------------------
i=0
e1x:=""
e1x =
(Ltrim Join|
#charmap
#notepad
#calc
#winver
#moviemk
cd MyDocuments                 ;%a_mydocuments%
cd Desktop                     ;%A_desktop%
cd MyComputer                  ;::{20d04fe0-3aea-1069-a2d8-08002b30309d}
cd MyNetworkPlaces             ;::{208d2c60-3aea-1069-a2d7-08002b30309d}
cd NetworkConnections          ;::{7007acc7-3202-11d1-aad2-00805fc1270e}
cd Printers                    ;::{2227a280-3aea-1069-a2de-08002b30309d}
cd RecycleBin                  ;::{645ff040-5081-101b-9f08-00aa002f954e}
cd Appdata                     ;%a_appdata%
cd Appdatacommon               ;%a_appdatacommon%
cd Programfiles                ;%a_programfiles%
cd Programs                    ;%a_programs%
cd ProgramsCommon              ;%a_programsCommon%
cd StartMenu                   ;%a_StartMenu%
cd StartMenuCommon             ;%a_StartMenuCommon%
cd Startup                     ;%a_Startup%
cd StartupCommon               ;%a_StartupCommon%
cd Windows                     ;%a_windir%
cd Temp                        ;%a_temp%
cd WorkingDir                  ;%a_workingdir%
cd Script                      ;notepad "%a_scriptfullpath%"
cd ScriptDir                   ;%a_scriptdir%
ping /?
ping -n 4 -w 1000 www.google.com
netstat -an
netstat -e -s
netstat
ipconfig /?
ipconfig
ipconfig /all
dir
dir /P /Q /L /4 /TAWC
dir /?
help
cmd /?
ver
vol
date /t
time /t
path
)

fileread,a,%fcdm%                 ;- textfile is in variable A
   loop,parse,a,`n,`r           ;- parse each line
   {
   i++
   if (i<3)                     ;- remove at least the first two lines from help
     continue
   y1=%a_loopfield%
   stringmid,y2,y1,1,3
   if (y1="" or y2="   ")
     {
     y1=
     y2=
     continue
     }

   c1=
   stringsplit,c,y1,%s%
   if (c1="dir" or c1="ver" or c1="path" or c1="chcp")
     e1x .= c1 . "|"
   e1x .= c1 . " /?|"
   }
a=
return
;================= END SCRIPT ================================================

tuzi
Posts: 223
Joined: 27 Apr 2016, 23:40

Re: Is there any way to embed a CMD / Console in a GUI?

Post by tuzi » 27 Jul 2020, 12:10

i think you need "StdOutToVar" or runcmd()?

it work on autohotkeyu32.exe

Code: Select all

;此函数可实时响应CMD的输出,以下是tmplinshi给出的演示例子
MsgBox % StdOutStream( "ipconfig /All" )
MsgBox % StdOutStream( "ping www.autohotkey.com", "StdOutStream_Callback" ) 

StdOutStream_Callback( data, n ) {
  Static D
  ToolTip % D .= data

  if ! ( n ) {
    Tooltip % D := ""
    Return "Callback says: Hi!"
  }
}

StdOutStream( sCmd, Callback = "" ) { ; Modified  :  SKAN 31-Aug-2013 http://goo.gl/j8XJXY
    Static StrGet := "StrGet"           ; Thanks to :  HotkeyIt         http://goo.gl/IsH1zs
    ; Original  :  Sean 20-Feb-2007 http://goo.gl/mxCdn

    DllCall( "CreatePipe", UIntP,hPipeRead, UIntP,hPipeWrite, UInt,0, UInt,0 )
    DllCall( "SetHandleInformation", UInt,hPipeWrite, UInt,1, UInt,1 )

    VarSetCapacity( STARTUPINFO, 68, 0  )      ; STARTUPINFO          ;  http://goo.gl/fZf24
    NumPut( 68,         STARTUPINFO,  0 )      ; cbSize
    NumPut( 0x100,      STARTUPINFO, 44 )      ; dwFlags    =>  STARTF_USESTDHANDLES = 0x100
    NumPut( hPipeWrite, STARTUPINFO, 60 )      ; hStdOutput
    NumPut( hPipeWrite, STARTUPINFO, 64 )      ; hStdError

    VarSetCapacity( Process_INFORMATION, 16 )  ; Process_INFORMATION  ;  http://goo.gl/b9BaI

    If ! DllCall( "CreateProcess", UInt,0, UInt,&sCmd, UInt,0, UInt,0 ;  http://goo.gl/USC5a
              , UInt,1, UInt,0x08000000, UInt,0, UInt,0
              , UInt,&STARTUPINFO, UInt,&PROCESS_INFORMATION )
        return ""
            , DllCall( "CloseHandle", UInt,hPipeWrite )
            , DllCall( "CloseHandle", UInt,hPipeRead )
            , DllCall( "SetLastError", Int,-1 )

    hProcess := NumGet( Process_INFORMATION, 0 )
    hThRead  := NumGet( Process_INFORMATION, 4 )

    DllCall( "CloseHandle", UInt,hPipeWrite )

    AIC := ( SubStr( A_AhkVersion, 1, 3 ) = "1.0" )                   ; A_IsClassic
    VarSetCapacity( Buffer, 4096, 0 ), nSz := 0

    while DllCall( "ReadFile", UInt,hPipeRead, UInt,&Buffer, UInt,4094, UIntP,nSz, Int,0 ) {

    tOutput := ( AIC && NumPut( 0, Buffer, nSz, "Char" ) && VarSetCapacity( Buffer,-1 ) )
    ? Buffer : %StrGet%( &Buffer, nSz, "CP0" )                      ; 原版是“CP850”,将导致乱码

    IsFunc( Callback ) ? %Callback%( tOutput, A_Index ) : sOutput .= tOutput

  }

DllCall( "GetExitCodeProcess", UInt,hProcess, UIntP,ExitCode )
DllCall( "CloseHandle",  UInt,hProcess  )
DllCall( "CloseHandle",  UInt,hThread   )
DllCall( "CloseHandle",  UInt,hPipeRead )
DllCall( "SetLastError", UInt,ExitCode  )

return IsFunc( Callback ) ? %Callback%( "", 0 ) : sOutput
}

Ninel
Posts: 4
Joined: 22 Jun 2019, 15:17

Re: Is there any way to embed a CMD / Console in a GUI?

Post by Ninel » 08 Jul 2021, 17:56

Not sure if you solved or not, but I had the same problem.
You have to use ReadLine inside the Loop

Code: Select all

#WinActivateForce
#SingleInstance Off

DetectHiddenWindows On

Gui, Add, Edit, x10 y5 h700 w700 vEdit_Box, Here will append the console output!
Gui, Show, x150 y150 h710 w710, CMD Realtime Ping...

; This will not hide the console window from the begining!
; DllCall("AllocConsole")
; WinHide % "ahk_id " DllCall("GetConsoleWindow", "ptr")

Run "%ComSpec%" /K,, Hide, cmd_pid
While !(hConsole := WinExist("ahk_pid" cmd_pid))
	{
	 Sleep 10
	}
DllCall("AttachConsole", "UInt", cmd_pid)

objShell := ComObjCreate("WScript.Shell")

; This will start a nested CMD inside the first one
;objExec  := objShell.Exec(ComSpec " /C ping -n 10 8.8.8.8")

objExec  := objShell.Exec("ping.exe -n 10 8.8.8.8")

While, !objExec.StdOut.AtEndOfStream
	{
	 new_line:= objExec.StdOut.ReadLine()
	 GuiControlGet, previous_text,, Edit_Box ; Read current text...
	 GuiControl,, Edit_Box, %previous_text%`n%new_line% ; ...And append a new line
	}

all_error_lines:= objExec.StdErr.ReadAll()
GuiControlGet, previous_text,, Edit_Box ; Read current text...
GuiControl,, Edit_Box, %previous_text%`n%all_error_lines% ; ...And append the StdErr if any

DllCall("FreeConsole")
Process Exist, %cmd_pid%
If (ErrorLevel == cmd_pid)
	{
	 Process Close, %cmd_pid%
	}
Return

; varl:= objExec.StdOut.ReadAll() - will wait and return the text alter the process has completed!
; var2:= objExec.StdErr.ReadAll() - will wait and return the text alter the process has completed!
; var3:= objExec.StdOut.ReadLine() - will return after every new line. Can be used in a loop to simulate realtime process experience!

Ninel
Posts: 4
Joined: 22 Jun 2019, 15:17

Re: Is there any way to embed a CMD / Console in a GUI?

Post by Ninel » 08 Jul 2021, 20:07

Or you can use it in a function and also redirect StdErr to StdOut and have a natural line order.

Code: Select all

#WinActivateForce
#SingleInstance Off

DetectHiddenWindows On

Gui, Add, Edit, x10 y5 h700 w700 vEdit_Box, Here will append the console output!
Gui, Show, x150 y150 h710 w710, CMD Realtime Ping...

Device_Address = 8.8.8.8
PING_CMD = ping.exe -n 10 -w 1500 %Device_Address% 2>&1

Run_In_Console("ECHO Pinging the device '" Device_Address "' ... & ECHO. & " PING_CMD " && (ECHO. & ECHO The command finished successfully) || (ECHO. & ECHO There was a error with this command!)")
Return

Run_In_Console(Command)
{
Global

Run "%ComSpec%" /K,, Hide, cmd_pid
While !(hConsole := WinExist("ahk_pid" cmd_pid))
	{
	 Sleep 10
	}
DllCall("AttachConsole", "UInt", cmd_pid)

objShell := ComObjCreate("WScript.Shell")
objShell.CurrentDirectory := "C:\"
objExec  := objShell.Exec(ComSpec " /C " Command)

While, !objExec.StdOut.AtEndOfStream
	{
	 new_line:= objExec.StdOut.ReadLine()
	 GuiControlGet, previous_text,, Edit_Box  ; Read current text...
	 GuiControl,, Edit_Box , %previous_text%`n%new_line% ; ...And append a new line
	}

;Errors has been redirected to StdOut using "2>&1"! No need for this.
;all_error_lines:= objExec.StdErr.ReadAll()
;GuiControlGet, previous_text,, Edit_Box  ; Read current text...
;GuiControl,, Edit_Box , %previous_text%`n%all_error_lines% ; ...And append the StdErr if any

DllCall("FreeConsole")
Process Exist, %cmd_pid%
If (ErrorLevel == cmd_pid)
	{
	 Process Close, %cmd_pid%
	}
}
Return

; varl:= objExec.StdOut.ReadAll() - will wait and return the text alter the process has completed!
; var2:= objExec.StdErr.ReadAll() - will wait and return the text alter the process has completed!
; var3:= objExec.StdOut.ReadLine() - will return after every new line. Can be used in a loop to simulate realtime process experience!

garry
Posts: 3740
Joined: 22 Dec 2013, 12:50

Re: Is there any way to embed a CMD / Console in a GUI?

Post by garry » 09 Jul 2021, 04:33

or also an example cmdret from user @teadrinker

Code: Select all

;- Hide command console when using RunWaitOne() example / from user teadrinker
;- https://www.autohotkey.com/boards/viewtopic.php?f=76&t=84266&sid=eff012cadb7a851b2c18f5f03b68408f
;----------------------------------------------
;- CREATED   = 20201211  cmdret  from user 'teadrinker'
;----------------------------------------------
cmdx:="ping autohotkey.com -n 4&&ver"
;cmdx:="dir"
;============== GUI ===========
#warn
#noenv
Fileencoding,UTF-8
name1:="DOS_TEST"
global name1
e:=""
CPX:="cp" . DllCall("GetOEMCP", "UInt")        ;- get CODEPAGE e.g. cp850
;CPX:="cp65001"
setworkingdir,%a_scriptdir%
Gui,1:default
Gui,1: -DPIScale 
Gui,1:Color,Black,Black                        ; GUI black   / EDIT is BLACK
wa:=A_screenwidth,ha:=A_screenHeight,xx:=100
;- maybe change fontsize
;============ GUISIZEx DPIx 4Kx 3840*2160 is 100% ============
if (wa=3840)
 Gui,1:Font,s12 cYellow,Lucida Console
;============ GUISIZEx DPIx FHD 1920*1080 is 100% ============
else if (wa=1920)
 Gui,1:Font,s10 cYellow,Lucida Console
else
 Gui,1:Font,s8 cYellow,Lucida Console
;=============================================================
x:=(wa*1)/xx,y:=(ha*1)/xx,w:=(wa*70)/xx,h:=(ha*60)/xx
Gui, Add, Edit, x%x%   y%y%  w%w% h%h% vED1                  ;- here the output
x:=(wa*1)/xx,y:=(ha*63)/xx,w:=(wa*65)/xx,h:=(ha*6)/xx
Gui, Add, Edit, x%x%   y%y% w%w%  h%h% vED2,%cmdx%           ;- add CMDx command above / or input command
x:=(wa*67)/xx,y:=(ha*63)/xx,w:=(wa*5)/xx,h:=(ha*2.2)/xx
Gui, add, Edit, x%x%  y%y% w%w%  h%h% vED3,                  ;- ENDED
x:=(wa*67)/xx,y:=(ha*66)/xx,w:=(wa*5)/xx,h:=(ha*2.2)/xx
Gui,add,button, x%x%  y%y% w%w%  h%h% gPrintx, PRINT
x:=(wa*2)/xx,y:=(ha*2)/xx,w:=(wa*75)/xx,h:=(ha*75)/xx
Gui, Show,x%x% y%y% w%w% h%h%,%name1%
gosub,a0
GuiControl,1: Focus,ED2
return
;-------------------------
Guiclose:
esc::
ProcessNames := "ping.exe|cmd.exe"
Loop, Parse, ProcessNames, |
{
   Process, Exist, %A_LoopField%
   if (ErrorLevel <> 0)
      Process, Close, %ErrorLevel%
}
exitapp
;-------------------------
~$enter::
gosub,a0
return
;=========================================================
AddOutputInGui(output) {
   Control, EditPaste, %output%`r`n, Edit1,%name1%    ;- display output in 1st EDIT
}
;=========================================================

A0:
Gui,1:submit,nohide
Guicontrol,1:,ED3,...running
ed2a:="cmd /c " . ed2
xxc:=cmdret(ED2a, Func("AddOutputInGui"),CPX)
e .="`r`n===============================`r`n" . ed2 . " =`r`n-------------------------------`r`n" . xxc . "`r`n===============================`r`n"
e := RegExReplace(e, "((^)|\R)\h*(?=\R|$)(?(2)\R)")              ;- remove empty lines
gosub,clear
;gosub,printx
return
;-------------------------
CLEAR:
Gui,1:submit,nohide
Guicontrol,1:,ED2,
Guicontrol,1:,ED3,ENDED
GuiControl,1: Focus,ED2
return
;-------------------------
printx:
f1=%a_desktop%\%a_now%_DOS_SCREEN_OUTPUT.txt
Gui,1:submit,nohide
if e<>
 {
 fileappend,%e%,%f1%,utf-8
 run,%f1%
 e:=""
 }
return

;=========================================================
CmdRet(sCmd, callBackFuncObj := "", encoding := "CP0")
{
   static HANDLE_FLAG_INHERIT := 0x00000001, flags := HANDLE_FLAG_INHERIT
        , STARTF_USESTDHANDLES := 0x100, CREATE_NO_WINDOW := 0x08000000
   hPipeRead:=""
   hPipeWrite:=""
   sOutput:=""
   DllCall("CreatePipe", "PtrP", hPipeRead, "PtrP", hPipeWrite, "Ptr", 0, "UInt", 0)
   DllCall("SetHandleInformation", "Ptr", hPipeWrite, "UInt", flags, "UInt", HANDLE_FLAG_INHERIT)
   
   VarSetCapacity(STARTUPINFO , siSize :=    A_PtrSize*4 + 4*8 + A_PtrSize*5, 0)
   NumPut(siSize              , STARTUPINFO)
   NumPut(STARTF_USESTDHANDLES, STARTUPINFO, A_PtrSize*4 + 4*7)
   NumPut(hPipeWrite          , STARTUPINFO, A_PtrSize*4 + 4*8 + A_PtrSize*3)
   NumPut(hPipeWrite          , STARTUPINFO, A_PtrSize*4 + 4*8 + A_PtrSize*4)
   
   VarSetCapacity(PROCESS_INFORMATION, A_PtrSize*2 + 4*2, 0)
   if !DllCall("CreateProcess", "Ptr", 0, "Str", sCmd, "Ptr", 0, "Ptr", 0, "UInt", true, "UInt", CREATE_NO_WINDOW
                              , "Ptr", 0, "Ptr", 0, "Ptr", &STARTUPINFO, "Ptr", &PROCESS_INFORMATION)
   {
      DllCall("CloseHandle", "Ptr", hPipeRead)
      DllCall("CloseHandle", "Ptr", hPipeWrite)
      throw Exception("CreateProcess is failed")
   }
   DllCall("CloseHandle", "Ptr", hPipeWrite)
   VarSetCapacity(sTemp, 4096), nSize := 0
   while DllCall("ReadFile", "Ptr", hPipeRead, "Ptr", &sTemp, "UInt", 4096, "UIntP", nSize, "UInt", 0) {
      sOutput .= stdOut := StrGet(&sTemp, nSize, encoding)
      ;sOutput .= stdOut := StrGet(&sTemp, nSize)
      ;sOutput .= stdOut := StrGet(&sTemp, nSize, CPX)
      ( callBackFuncObj && callBackFuncObj.Call(stdOut) )
   }
   DllCall("CloseHandle", "Ptr", NumGet(PROCESS_INFORMATION))
   DllCall("CloseHandle", "Ptr", NumGet(PROCESS_INFORMATION, A_PtrSize))
   DllCall("CloseHandle", "Ptr", hPipeRead)
   Return sOutput
}
;================= END SCRIPT ========================================================================
Last edited by garry on 18 Aug 2022, 15:31, edited 2 times in total.

Panaku
Posts: 14
Joined: 02 Apr 2022, 17:24

Re: Is there any way to embed a CMD / Console in a GUI?

Post by Panaku » 17 Aug 2022, 04:09

Do you know if there's a way to cancel a running command using this code that @teadrinker put together? If I try to send a second command it locks up the entire program, I can kind of close the cmd window from the task manager but that seems a little hit and miss to it's effectiveness.

garry
Posts: 3740
Joined: 22 Dec 2013, 12:50

Re: Is there any way to embed a CMD / Console in a GUI?

Post by garry » 18 Aug 2022, 15:06

in example above , here is also ping.exe running .... try to close process ping.exe and cmd.exe ...

Code: Select all

;-------------------------
;cmdx:="ping autohotkey.com -n 50&&ver"
;...
Guiclose:
esc::
ProcessNames := "ping.exe|cmd.exe"
Loop, Parse, ProcessNames, |
{
   Process, Exist, %A_LoopField%
   if (ErrorLevel <> 0)
      Process, Close, %ErrorLevel%
}
exitapp
;-------------------------------------------------------

Post Reply

Return to “Ask for Help (v1)”