Announcement

Collapse
No announcement yet.

SHELL from DOS App

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • SHELL from DOS App

    I have a DOS app from which I shell to a PB/DLL app. The PB/DLL app acts as
    a tsr to do various disk and registry operations (eg, read long file names,
    read the registry to launch other apps to open various types of files). In Win95/
    98 it works quite well but with some configurations of Win2000/NT the PB app
    grabs the focus and doesn't let go. Is there some way to give up the focus
    so that it will return to the calling DOS app?


    ------------------
    Walt Decker

  • #2
    Is there some way to give up the focus ...

    When you find that way, please mail a copy of the solution to:

    William J.Clinton
    New York City, NY


    Thank you,
    MCM


    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      The strange thing is that, even if I end the PB/DLL app after it has done its thing,
      the focus still doesn't return to the DOS app unless I manually go in and terminate
      the PB/DLL process. Once I do that, then it works fine by continually SEHLLing
      out to the PB/DLL.

      I don't have to do that in 95/98. Haven't checked it in ME.

      Using the SHELL function in PB one can specify whether the called app has the focus or
      not. Should't PB be able to determine whether it has the focus. Incidentally,
      the PB app creates no windows of any kind.
      ------------------


      [This message has been edited by Walt Decker (edited May 11, 2001).]
      Walt Decker

      Comment


      • #4
        I think I have some PBDOs code that will regain the focus for you.
        I also have some that will maximize the dos session etc...Inter-Sceptre had it all, worked great under 95/98.


        As to WHY? Remember you are operating on a true (caugh caugh) 32 bit operating system on NT, whereas 95/98 is a lot of 16 bit stuff, definitely different video and kernel etc...

        The only other method would be to grab the window handle of the dos prompt and send it a set focus before terminating the PB/DLl app...

        How do you communiate bakc to the dos box, via text file?


        Scott

        ------------------
        Scott
        Scott Turchin
        MCSE, MCP+I
        http://www.tngbbs.com
        ----------------------
        True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

        Comment


        • #5
          Yes, through a text file. Once the PB app starts, all info is passed through 2 text files.
          One tells the PB app what to do, the PB app then delets it, and writes the result to
          another text file. By having 2 files, all I have to look for are the file names. If they are
          present, then the appropriate app takes action.

          Unfortunately, the DOS app is in MSPDS. However, if the PBDOS code uses interrupts in
          ASM fasion, I can readily translet to something compatible with PDS.



          ------------------
          Walt Decker

          Comment


          • #6
            Walt --

            Probably, I lost something, but I don't see any problem here.

            1) To compile PB/DLL module as console app (for example, using a wrapper, which I posted a week ago).
            2) In PB/DLL:
            a) to retrieve hwnd of console window (for example, SetConsoleTitle ... FindWindow).
            b) to execute GUI part
            c) to return focus to console window.
            It's not a problem, even if app has no focus (search SetForegroundWindow / AttachThreadInput / SwitchToThisWindow and so on).
            But typically GUI app will be finished by pressing any button.
            In this moment GUI is foreground and before closing a dialog it's possible to use simple
            ShowWindow hWndConsole, %SW_SHOWNA: SetForegroundWindow hWndConsole

            ------------------
            E-MAIL: [email protected]

            Comment


            • #7
              Semen, I think you did miss something. The PB app does nothing except read directories and the WINNT registry.
              It then passes that information back to the PDS app through a file. Once that is done it goes into an infinite loop
              until, via a file, it receives a request for more information. When the PDS app is finished, it sends a message to the PB
              app to shut itself down and clean up it's own files. There are no windows or GUI's involved in the PB app.

              I don't see how compiling the PB app in a wrapper can make it give up the focus so that the PDS app can continue doing
              it's thing, but I'll take a look at your posted code. Perhaps in WINNT it will work, NT seems a bit strange anyway.

              Walt



              ------------------
              Walt Decker

              Comment


              • #8
                The problem is that when a DOS app launches a GUI (or GUI subsystem) app, Windows launches it as a separate Process, and focus may or may not be restored to the DOS app when the GUI app finishes. If the DOS app was running full screen, then it is almost certain the DOS window will not be restored.

                However, if you launch a console app from a DOS app, the console app uses the current DOS window, so focus is not lost. Also, it is possibly to synchronously SHELL to a GUI app from a console app (but not from a DOS app), so this may be a simpler solution for you.

                I wrote a small app called WINLINK.EXE that is designed to help with this exact issue - restoring the DOS app to the foreground after Synchronously SHELLing to a GUI app. If you'd like a free copy, please just send me a private email mailto:[email protected]@xtra.co.nz[email protected]@xtra.co.nz</A>

                PS: I made this offer a few weeks ago, and several folks asked for a copy of WINLINK< but there was one guy whose email bounced several times. If you have asked me for a copy of WINLINK and did not receive it (you know who you are!), please email me again!

                Thanks!


                ------------------
                Lance
                PowerBASIC Support
                mailto:[email protected][email protected]</A>
                Lance
                mailto:[email protected]

                Comment


                • #9
                  Walt --
                  if Pb/DLL is compiled as console app, it will share dos window.

                  But I see that your task is much easy.
                  I wrote simple Turbo Basic app (dos.exe).
                  Guess, PB DOS will understand it also.

                  Code:
                     On Error Goto PrErr1
                     Goto Start
                  
                   PrErr1:
                     Er = 1: Resume Next
                  
                   Start:
                     Line Input "Type a request to PB/DLL ? ", Buf$
                     Do
                        Er = 0: Open "Request" For Output As #1
                        If Er = 0 Then Exit Loop Else Delay 0.1
                     Loop
                     Print #1, Buf$: Close #1
                     If Buf$ = "Stop" Then End
                  
                     Do
                        Er = 0: Open "Answer" For Input As #1
                        If Er = 0 Then Exit Loop Else Delay 0.1
                     Loop
                  
                     Line Input #1, Buf$: Close #1: Kill "Answer": Print Buf$: Goto Start
                  Following PB/DLL exe is a leader
                  Code:
                     #Compile Exe
                     #Register None
                     #Dim All
                     #Include "WIN32API.INC"
                  
                     Function WndProc(ByVal hWnd    As Dword, ByVal wMsg    As Dword,_
                        ByVal wParam  As Dword, ByVal lParam  As Dword) As Long
                  
                        Dim i As Long, Buf As String
                             
                        Select Case wMsg
                           Case %WM_CREATE
                              i = Shell ("Dos.Exe")
                              SetTimer hWnd, 1, 100, ByVal 0&
                             
                           Case %WM_TIMER
                              Open "Request" For Input As #1
                              If IsFalse(Err) Then
                                 Line Input #1, Buf
                                 Close #1
                                 Kill "Request"
                                 If Buf = "Stop" Then
                                    PostMessage hWnd, %WM_SYSCOMMAND, %SC_CLOSE, 0
                                 Else
                                    Open "Answer" For Output As #1
                                    Print #1, "Reply from PB/DLL : --- " Buf " ---"
                                    Close #1
                                    SetTimer hWnd, 1, 100, ByVal 0&
                                 End If
                              End If
                             
                           Case %WM_DESTROY
                              PostQuitMessage 0
                        End Select
                        
                        Function = DefWindowProc(hWnd, wMsg, wParam, lParam)
                  
                     End Function
                  
                  
                     Function PbMain
                        Dim Msg As tagMsg, wc As WndClassEx, hWnd As Dword, szClassName As Asciiz * 5
                        szClassName = "Test"
                        wc.cbSize        = SizeOf(wc)
                        wc.lpfnWndProc   = CodePtr(WndProc)
                        wc.hInstance     = GetModuleHandle(ByVal 0&)
                        wc.hIcon         = LoadIcon  (%NULL, ByVal %IDI_APPLICATION)
                        wc.lpszClassName = VarPtr(szClassName)
                  
                        RegisterClassEx wc
                        hWnd = CreateWindow (szClassName, "Test", 0, 0, 0, 0, 0, 0, 0, wc.hInstance, 0)
                        While GetMessage(Msg, ByVal 0&, 0, 0)
                           TranslateMessage Msg
                           DispatchMessage  Msg
                        Wend
                     End Function
                  It's starts DOS part. A program will be finished, when you type Stop instead of "real request".




                  ------------------
                  E-MAIL: [email protected]

                  Comment


                  • #10
                    I realized my initial suggestion.
                    TB module
                    Code:
                       Print "Press Enter to start GUI ..."
                       While Inkey$ <> CHR$(13): Wend
                       Shell "GUI.Exe"
                       Print "Returned. Press Esc ..."
                       While Inkey$ <> CHR$(27): wend
                    shells GUI.Exe (compiled as "console" in wrapper - '%&)
                    Code:
                         #Compile Exe
                         #Dim All
                         #Register None
                         #Include "WIN32API.INC"
                    
                         '%&
                    
                         Declare Function SwitchToThisWindow (ByVal Long, ByVal Long) As Long
                    
                         Sub pSetForegroundWindow(ByVal hwnd As Long)
                    
                            Dim hSwitchToThisWindow As Dword, lForeThreadID As Long, lThisThreadID As Long, lReturn As Long
                    
                            hSwitchToThisWindow = GetProcAddress(GetModuleHandle("user32.dll"), "SwitchToThisWindow")
                            Do
                               If hwnd = GetForegroundWindow Then Exit Loop
                               lForeThreadID = GetWindowThreadProcessId(GetForegroundWindow, ByVal 0&)
                               lThisThreadID = GetWindowThreadProcessId(hwnd, ByVal 0&)
                               If lForeThreadID <> lThisThreadID Then
                                  AttachThreadInput lForeThreadID, lThisThreadID, 1
                                  SetForegroundWindow hwnd
                                  AttachThreadInput(lForeThreadID, lThisThreadID, 0
                              Else
                                 lReturn = SetForegroundWindow(hwnd)
                              End If
                              If hwnd = GetForegroundWindow Then Exit Loop
                              Call Dword hSwitchToThisWindow Using SwitchToThisWindow(hwnd, 1) To lReturn
                              If hwnd = GetForegroundWindow Then Exit Loop
                              ShowWindow hWnd, %SW_MINIMIZE: ShowWindow hWnd, %SW_RESTORE
                           Loop
                           If IsIconic(hwnd) Then ShowWindow hwnd, %SW_RESTORE Else ShowWindow hwnd, %SW_SHOW
                         End Sub
                    
                         Function GetConsoleWindow As Long
                            Dim lpConsName1 As Asciiz * 256, lpConsName2 As Asciiz * 256, hWndConsole1 As Long, hWndConsole2 As Long
                    
                            GetConsoleTitle lpConsName1, SizeOf(lpConsName1)
                            Do
                               If Len(lpConsName2) >= SizeOf(lpConsName2) Then Exit Function
                               lpConsName2 = lpConsName2 + " "
                               SetConsoleTitle lpConsName2
                               Do
                                  hWndConsole1 = FindWindow(ByVal %NULL, lpConsName2)
                                  If hWndConsole1 Then Exit Do Else ApiSleep 40
                               Loop
                               If hWndConsole1 = hWndConsole2 Then Exit Do
                               hWndConsole2 = hWndConsole1
                            Loop
                            Function = hWndConsole1
                            SetConsoleTitle lpConsName1
                         End Function
                    
                         Function PbMain
                            Dim hWndConsole As Long
                            hWndConsole = GetConsoleWindow
                    
                            Shell "notepad.exe" ' <---- to lose a focus
                            pSetForegroundWindow hWndConsole
                    
                       End Function
                    GUI starts Notepad. To continue it's necessary to close notepad's window.
                    Tested under Win2000 and ME (in window and full screen modes).


                    ------------------
                    E-MAIL: [email protected]

                    Comment


                    • #11
                      Thank you, Lance, that clears up the confusion.

                      Semen, I'll give your wrapper a whirl. Perhaps it will make it possible
                      for me to regain the focus when the PB app is done.

                      Thanks for pointing me in the right direction.

                      ------------------
                      Walt Decker

                      Comment

                      Working...
                      X