Announcement

Collapse
No announcement yet.

Shell only receving 218 characters

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

    Shell only receving 218 characters

    SHELL is only receiving the first 218 characters when shelling between two
    PbWin programs. I will need to pass more than this to a 3rd party program.
    Is there a way to increase the environment space using XP PRO XP3.
    I've tried chopping several things out and rebooted with no success.

    I've requested only passing a file name with the parameters within it, but that may come later.

    With these test programs the max is 243 characters on this machine.
    Code:
    #COMPILE EXE "\test1"
      FUNCTION PBMAIN AS LONG
         s$ = STRING$(310,"A") + $CRLF
         SHELL "c:\test2.exe " + s$
       END FUNCTION

    Code:
    #COMPILE EXE "test2"
      FUNCTION PBMAIN AS LONG
        ? STR$(LEN(COMMAND$))
      END FUNCTION

    'tried this suggestion on google without luck.
    SHELL "c:\windows\system32\cmd.exe /e:2048 /c " + "c:\test2.exe " + s$ '204 characters

    'Found a work-around to at least pass enough characters
    CHDIR "\program files\yadda\yadda"
    SHELL programname$ + " " + parameters$
    Where it was SHELL "c:\program files\yadda\yadda\programname " + parameters$
    Last edited by Mike Doty; 19 Jul 2008, 04:36 PM. Reason: Show work-around

    #2
    CreateProcess to the rescue

    Hi Mike,

    Try something like this:

    Code:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "Win32API.INC"
    
    FUNCTION PBMAIN () AS LONG
       LOCAL rcStart AS STARTUPINFO
       LOCAL rcProcess AS PROCESS_INFORMATION
       LOCAL sProg AS STRING
       LOCAL sCom AS STRING
       
       sProg = "\Test2.exe"
       sCom = REPEAT$(100, "1234567890")
       CreateProcess BYVAL 0, BYCOPY sProg & " " & sCom, BYVAL 0, BYVAL 0, 1&, _
                                        %NORMAL_PRIORITY_CLASS, BYVAL 0, BYCOPY CURDIR$, rcStart, rcProcess
    END FUNCTION
    My testing here shows command line receiving 1000 characters, and more is probably possible, so should be plenty for your needs.

    Regards,

    Pete.
    Last edited by Peter Jinks; 19 Jul 2008, 07:02 PM. Reason: Typo

    Comment


      #3
      That works great and allows passing thousands of characters!
      Problem now is as follows:

      [Program1 asyncronous shell to] ----> [MyProgram CreateProcess to] ------> [Program3 creates return-file]

      Program1 is a DOS program that does an asyncronous shell to MyProgram
      MyProgram now uses CreateProcess to Program3
      Program3 creates a return-file

      Program1 now gets return-file before it is complete

      1) Can MyProgram wait for Program3 to end?
      2) Does MyProgram need to execute ExitProcess?
      Last edited by Mike Doty; 19 Jul 2008, 10:52 PM.

      Comment


        #4
        This works:
        Is WaitForInputIdle necessary?



        Code:
        FUNCTION WaitShell(BYVAL CmdLine AS STRING) AS LONG
         
          LOCAL Si        AS STARTUPINFO
          LOCAL Pi        AS PROCESS_INFORMATION
          'Local TimeLimit As Long
          LOCAL Pid       AS DWORD
          'TimeLimit = 30
          Si.cb = SIZEOF(Si)
          Si.dwFlags = %STARTF_USESHOWWINDOW
          Si.wShowWindow = %SW_SHOWNORMAL
          Pid = CreateProcess("", _
                         BYVAL STRPTR(CmdLine), _
                         BYVAL %NULL, _
                         BYVAL %NULL, _
                         0, _
                         %NORMAL_PRIORITY_CLASS, _
                         BYVAL %NULL, _
                         BYVAL %NULL, _
                         Si, _
                         Pi)
          IF Pid THEN
           'Call WaitForInputIdle(pi.hProcess, %IGNORE)
           'If TimeLimit Then
               FUNCTION =  WaitForSingleObject(pi.hProcess, %INFINITE)
             CALL CloseHandle(pi.hProcess)
             CALL CloseHandle(pi.hThread)
           'End If
        END IF
        END FUNCTION

        Comment


          #5
          Hi Mike,

          To question (1), the answer is yes. Here's one way (there are probably others):
          Code:
          #COMPILE EXE
          #DIM ALL
          #INCLUDE "Win32API.INC"
          
          FUNCTION PBMAIN () AS LONG
             LOCAL rcStart AS STARTUPINFO
             LOCAL rcProcess AS PROCESS_INFORMATION
             LOCAL sProg AS STRING
             LOCAL sCom AS STRING
             LOCAL hChild AS DWORD, lReason AS DWORD
             
             sProg = "\Test2.exe"
             sCom = REPEAT$(100, "1234567890")
             hChild = CreateProcess( BYVAL 0, BYCOPY sProg & " " & sCom, BYVAL 0, BYVAL 0, 1&, _
                                              %NORMAL_PRIORITY_CLASS, BYVAL 0, BYCOPY CURDIR$, rcStart, rcProcess)
             IF hChild <> 0 THEN
                ' Wait 10 seconds for child to complete before timing out - could also specify %INFINITE
                lReason = WaitForSingleObject(rcProcess.hProcess, 10000)
                MSGBOX "Wait ended : " & SWITCH$(lReason = %WAIT_TIMEOUT, "Timeout", lReason = %WAIT_OBJECT_0, "Complete", lReason = %WAIT_ABANDONED, "Abandoned"), %MB_TASKMODAL
             ELSE
                MSGBOX "CreateProcess failed", %MB_TASKMODAL
             END IF
                                              
          END FUNCTION
          For question (2), I'm sorry but I don't know!

          Regards,

          Pete.

          EDIT: Wow, posted at exactly the same time! Looks like you got it anyway.
          Last edited by Peter Jinks; 19 Jul 2008, 11:38 PM. Reason: Cross post

          Comment


            #6
            Not sure if CloseHandle is required after WaitForSingleObject? If so, then I've seen quite a few programs with memory leaks.

            Wow, indeed! You really got me going in the right direction.
            This will make an excellent function in some other programs, too.



            Code:
            'test1.bas
            #COMPILE EXE
            #DIM ALL
            #INCLUDE "Win32API.INC"
            FUNCTION PBMAIN () AS LONG
              LOCAL rcStart AS STARTUPINFO  
              LOCAL rcProcess AS PROCESS_INFORMATION
              LOCAL sProg AS STRING
              LOCAL sCom AS STRING
              LOCAL hChild AS DWORD, lReason AS DWORD
              sProg = "\Test2.exe"
              sCom = REPEAT$(100, "1234567890")
              hChild = CreateProcess( BYVAL 0, BYCOPY sProg & " " & sCom, BYVAL 0, BYVAL 0, 1&, _
              %NORMAL_PRIORITY_CLASS, BYVAL 0, BYCOPY CURDIR$, rcStart, rcProcess)
              IF hChild <> 0 THEN
              ' Wait 10 seconds for child to complete before timing out - could also specify %INFINITE
              lReason = WaitForSingleObject(rcProcess.hProcess, %INFINITE)
              [B]CALL CloseHandle(rcProcess.hProcess)[/B]
            [B]  CALL CloseHandle(rcProcess.hThread)[/B]
              MSGBOX "Wait ended : " & SWITCH$(lReason = %WAIT_TIMEOUT, "Timeout", lReason = %WAIT_OBJECT_0, "Complete", lReason = %WAIT_ABANDONED,       "Abandoned"), %MB_TASKMODAL
              ELSE
              MSGBOX "CreateProcess failed", %MB_TASKMODAL
              END IF
            END FUNCTION
            Last edited by Mike Doty; 19 Jul 2008, 11:55 PM.

            Comment


              #7
              Hi Mike,

              According to MSDN, CloseHandle is not required after WaitForSingleObject. However, it is required after CreateProcess, so your code is correct. Sorry for that omission.

              Regards,

              Pete.

              Comment


                #8
                Good catch! Thanks for reporting it. Code came from Scott Turchin. I posted a link above and here.
                http://www.powerbasic.com/support/pb...=createprocess Post #3 2/7/2006 Fuill disclosure
                Last edited by Mike Doty; 20 Jul 2008, 09:12 AM.

                Comment


                  #9
                  >CloseHandle is not required after WaitForSingleObject

                  Of course it isn't, because you may not be done with the handle.

                  To put your statement into "PB parallel;" " CLOSE is not required after LINE INPUT".

                  Of course it isn't, because you may want to read more records from the file.

                  And in your case, too...
                  Code:
                   
                      WFSO   hProcess 
                      GetExitCodeProcess  hProcess ....
                  This won't work real well if you 'CloseHandle' immediately after WFSO.

                  That said, you should always "CloseHandle" when you are done with that handle. , just like you should always close a file handle when you are done with that file.


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

                  Comment


                    #10
                    "What thalt shall Open"
                    "What thalt shall Close"

                    Programming Bible 101
                    Engineer's Motto: If it aint broke take it apart and fix it

                    "If at 1st you don't succeed... call it version 1.0"

                    "Half of Programming is coding"....."The other 90% is DEBUGGING"

                    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                    Comment


                      #11
                      GetShortPathName() function might be handy.
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                        #12
                        Can programs another program?

                        Shortcut to z:\DOSProgram.exe from client machine
                        DOSProgram.exe shells to program2.exe okay.
                        program2.exe won't shell or createprocess to "c:\program3.exe"
                        Is this possible down a network?


                        The code works on the local machine
                        PID returns 0 when run down the network
                        GetLastError returns 0
                        CALL WaitShell($FullPathProgram + " " + ShellString, TimeOutInMilliseconds)
                        Code:
                        REM client starts "z:\DosProgram.exe"
                        REM  DosProgram.exe shells to this program"\program2.exe"
                        REM Can't shell or create process to "c:\program.exe"
                         
                        FUNCTION WaitShell(BYVAL CmdLine AS STRING, TimeOutInMilliseconds AS LONG) AS LONG   
                          LOCAL Si AS STARTUPINFO
                          LOCAL Pi AS PROCESS_INFORMATION
                          LOCAL Pid AS DWORD
                          Si.cb = SIZEOF(Si)
                          Si.dwFlags = %STARTF_USESHOWWINDOW
                          Si.wShowWindow = %SW_SHOWNORMAL
                          Pid = CreateProcess("", _
                          BYVAL STRPTR(CmdLine), _
                          BYVAL %NULL, _
                          BYVAL %NULL, _
                          0, _
                          %NORMAL_PRIORITY_CLASS, _
                          BYVAL %NULL, _
                          BYVAL %NULL, _
                          Si, _
                          Pi)
                         
                          IF Pid THEN
                             FUNCTION = WaitForSingleObject(pi.hProcess, TimeOutInMilliseconds)
                             CALL CloseHandle(pi.hProcess)
                             CALL CloseHandle(pi.hThread)
                          ELSE
                            ? "GetLastError" + STR$(GetLastError)
                          END IF
                        END FUNCTION
                        Last edited by Mike Doty; 21 Jul 2008, 05:49 PM.

                        Comment


                          #13
                          Got to work by moving program3.exe to current directory and
                          not passing the full name. This is not however what I want.
                          Want to CreateProcess to "c:\program files\something\program3.exe"
                          I'll now attempt to change directories before creating process to see results.

                          Comment


                            #14
                            Re-read post 11! The spaces in the file name are screwing up CreateProcess! (As documented).

                            Or, you can double quote the program file name if it contains spaces...
                            Code:
                            FUNCTION QooteIfContainsSpace(P As STRING ) AS STRING
                               FUNCTION = IIF$ (INSTR(P, $SPC), $DQ & P & $DQ, P)
                            END FUNCTION
                            MCM
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                              #15
                              I was just doing that!
                              You're the man.

                              Comment

                              Working...
                              X
                              😀
                              🥰
                              🤢
                              😎
                              😡
                              👍
                              👎