Request an additional flag for the OpenConsole() function

Just starting out? Need help? Post your questions and find answers here.
ZX80
Enthusiast
Enthusiast
Posts: 375
Joined: Mon Dec 12, 2016 1:37 pm

Request an additional flag for the OpenConsole() function

Post by ZX80 »

Hello, all.

I wanted to ask: is it possible to add additional flags for OpenConsole() in the future? Such as #PB_Console_Invisible and #PB_Console_Minimize (similar to OpenWindow()).
How can I do the same now, while these flags do not exist?

Now I will show you what I really need:

Code: Select all

Import "kernel32.lib"
  GetConsoleWindow.i()
EndImport

If OpenConsole()
  hwnd=GetConsoleWindow()
  ShowWindow_(hwnd, #SW_HIDE) ;#SW_MINIMIZE
  Sleep_(5000)
EndIf
Yes, it works, but I don't like how it works. Because the console window is still displayed for a moment (flickers) when you open it. I suspect that I need to start the console with RunProgram() with #PB_Program_Hide flag and then attach to it.

Code: Select all

Import "kernel32.lib"
  AttachConsole(processID.l)
EndImport
Isn't it? Maybe there is a more beautiful solution?

Why is this needed?
For the case when I do not want to show the console window, but simply perform some operations in it.

Code: Select all

ImportC "msvcrt.lib"
  system(str.p-ascii)
EndImport
But If I need debugging, I can always show the window again: #SW_SHOW.

Now I did something like this:

Code: Select all

Structure RunProgramExtendedStructure
  ProgramID.i
  WindowHandle.i
EndStructure

Procedure EnumWindows(hwnd.i, lParam.i)
  Protected Result.i = #True, PID.l, *RunProgramExtended.RunProgramExtendedStructure = lParam
  Protected classText.s = Space(255)
  
  If hwnd
    If IsIconic_(hwnd) ;IsWindowVisible_(hwnd) = 0
      GetClassName_(hwnd, @classText, 255)
      If classText = "ConsoleWindowClass"
        If GetWindowThreadProcessId_(hwnd, @PID)
          If PID = *RunProgramExtended\ProgramID
            *RunProgramExtended\WindowHandle = hwnd
            Result = #False
          EndIf
        EndIf
      EndIf
    EndIf
  Else
    Result = #False
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure RunProgramEx(file$, param$, dir$, showflag, lParam.i)
  Protected Result.i = #False, *RunProgramExtended.RunProgramExtendedStructure = lParam
  
  If Left(param$,1)<>" " : param$=" "+param$ : EndIf
  Info.STARTUPINFO : Info\cb=SizeOf(STARTUPINFO) : Info\dwFlags=1
  Info\wShowWindow=showflag : ProcessInfo.PROCESS_INFORMATION
  If CreateProcess_(@file$,@param$,0,0,0,#NORMAL_PRIORITY_CLASS,0,@dir$,@Info,@ProcessInfo)
    *RunProgramExtended\ProgramID = ProcessInfo\dwProcessId
    Result.i = #True
  EndIf
  ProcedureReturn Result
EndProcedure


Define RunProgramExtended.RunProgramExtendedStructure
Define hwnd.i, *ExtendedStructure = @RunProgramExtended
Define app$ = GetEnvironmentVariable("comspec") ; Full path needed!

If RunProgramEx(app$, "", GetPathPart(app$), #SW_MINIMIZE, *ExtendedStructure) ;#SW_HIDE
  Repeat
    Sleep_(500)
    EnumWindows_(@EnumWindows(), *ExtendedStructure)
    hwnd = RunProgramExtended\WindowHandle
  Until hwnd
  
  Debug hwnd
  Sleep_(3000)
  ShowWindow_(hwnd, #SW_SHOW)
EndIf
But I would like native support for this. Also now it shows a command line prompt, which is not the same as openconsole(). And I want to be able to use print(n).
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5499
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Request an additional flag for the OpenConsole() function

Post by Kwai chang caine »

Hello ZX80 :)

Thanks for your code, it working here 8)
Except that for me ....a "real" invisible window/console not appear in the taskbar too :wink:
So i try to adding the nice code of TSSOFT, and unfortunately the console have when even the time to appear some second :|
Apparently it's not simple to fully hide the windows console :cry:

Code: Select all

Structure RunProgramExtendedStructure
  ProgramID.i
  WindowHandle.i
EndStructure

Procedure HideFromTaskBar(hWnd.l, Flag.l) ; TsSoft
  Protected TBL.ITaskbarList 

  CoInitialize_(0) 
  If CoCreateInstance_(?CLSID_TaskBarList, 0, 1, ?IID_ITaskBarList, @TBL) = #S_OK 
    TBL\HrInit() 
    If Flag 
      TBL\DeleteTab(hWnd) 
    Else 
      TBL\AddTab(hWnd) 
    EndIf 
    TBL\Release() 
  EndIf 
  CoUninitialize_() 
  
  DataSection 
    CLSID_TaskBarList: 
    Data.l $56FDF344 
    Data.w $FD6D, $11D0 
    Data.b $95, $8A, $00, $60, $97, $C9, $A0, $90 
    IID_ITaskBarList: 
    Data.l $56FDF342 
    Data.w $FD6D, $11D0 
    Data.b $95, $8A, $00, $60, $97, $C9, $A0, $90 
  EndDataSection 
EndProcedure 

Procedure EnumWindows(hwnd.i, lParam.i)
  Protected Result.i = #True, PID.l, *RunProgramExtended.RunProgramExtendedStructure = lParam
  Protected classText.s = Space(255)
  
  If hwnd
    If IsIconic_(hwnd) ;IsWindowVisible_(hwnd) = 0
      GetClassName_(hwnd, @classText, 255)
      If classText = "ConsoleWindowClass"
        If GetWindowThreadProcessId_(hwnd, @PID)

          If PID = *RunProgramExtended\ProgramID
            *RunProgramExtended\WindowHandle = hwnd
            HideFromTaskBar(Hwnd, #True)
            Result = #False
          EndIf
        EndIf
      EndIf
    EndIf
  Else
    Result = #False
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure RunProgramEx(file$, param$, dir$, showflag, lParam.i)
  Protected Result.i = #False, *RunProgramExtended.RunProgramExtendedStructure = lParam
  
  If Left(param$,1)<>" " : param$=" "+param$ : EndIf
  Info.STARTUPINFO : Info\cb=SizeOf(STARTUPINFO) : Info\dwFlags=1
  Info\wShowWindow=showflag : ProcessInfo.PROCESS_INFORMATION
  If CreateProcess_(@file$,@param$,0,0,0,#NORMAL_PRIORITY_CLASS,0,@dir$,@Info,@ProcessInfo)
    *RunProgramExtended\ProgramID = ProcessInfo\dwProcessId
    Result.i = #True
  EndIf
  ProcedureReturn Result
EndProcedure


Define RunProgramExtended.RunProgramExtendedStructure
Define hwnd.i, *ExtendedStructure = @RunProgramExtended
Define app$ = GetEnvironmentVariable("comspec") ; Full path needed!

If RunProgramEx(app$, "", GetPathPart(app$), #SW_MINIMIZE, *ExtendedStructure) ;#SW_HIDE
  Repeat
    Sleep_(500)
    EnumWindows_(@EnumWindows(), *ExtendedStructure)
    hwnd = RunProgramExtended\WindowHandle
  Until hwnd
  
  Debug hwnd
  Sleep_(3000)
  ShowWindow_(hwnd, #SW_SHOW)
  HideFromTaskBar(Hwnd, #False)
EndIf

ImageThe happiness is a road...
Not a destination
ZX80
Enthusiast
Enthusiast
Posts: 375
Joined: Mon Dec 12, 2016 1:37 pm

Re: Request an additional flag for the OpenConsole() function

Post by ZX80 »

Kwai chang caine,

You are welcome.
I did not understand you. Try changing line 11 to this:

Code: Select all

If IsWindowVisible_(hwnd) = 0
and also line 46 to this:

Code: Select all

If RunProgramEx(app$, "", GetPathPart(app$), #SW_HIDE, *ExtendedStructure)
Did you need it? I left comments in the code for this case.

P.S. Unfortunately I have to go.
Marc56us
Addict
Addict
Posts: 1600
Joined: Sat Feb 08, 2014 3:26 pm

Re: Request an additional flag for the OpenConsole() function

Post by Marc56us »

This doesn't answer the original request, but just a tip (Just in case other coders want to do something similar): Avoid tinkering with the system and you may lose control of the program. It's like end users are left with a bunch of ghost processes. :?

A console program is meant to be run from a console, or it will open one except if starting from background.

If you want a console program without any display, several simples solutions:
  • Windows: launch the main window as a Splashscreen and make it invisible as soon as the initialization is complete. This is the cleanest and safest way. (Put a Traycon to take control of it).
  • Windows: Run it via the task manager (schtasks / ?) if there is no need for interactivity, or make it a service.
  • *nix: Run it via the task manager (e.g. cron) or run it interactively in the background (<program> &) or with nohup (nohup <program> if it needs to survive the logout).
:wink:
Post Reply