Announcement

Collapse
No announcement yet.

Spawning & Opening new Windows (PB/CC)

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

  • Spawning & Opening new Windows (PB/CC)

    Hi. In PB/CC, I'm using the SHELL function & the SHELL statement to call external command line utilities, which works fine for me. However, I want to make this multi-threaded and since the utility I'm calling output's stuff to the screen, multi-threading makes a messed display.

    So, I'd like to spawn each of these tasks in their own command prompt type window, but I'm confused on how to do that. The 'console' commands I've tried all seem to modify the existing console, and not open or close a new console window. Is this possible, and if so, how?

    Thanx.

  • #2
    The CreateProcess Api seems to be what's needed. Never used it myself. It appears that each process can have only one console, so I guess you'll have a number of console windows at once.

    From AllocConsole()

    A process can be associated with only one console, so the AllocConsole function fails if the calling process already has a console. A process can use the FreeConsole function to detach itself from its current console, and then it can call AllocConsole to create a new console. If the calling process creates a child process, the child inherits the new console.
    Fred
    "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

    Comment


    • #3
      Hi. In PB/CC, I'm using the SHELL function & the SHELL statement to call external command line utilities, which works fine for me. However, I want to make this multi-threaded and since the utility I'm calling output's stuff to the screen, multi-threading makes a messed display.
      SHELL creates multiple threads of execution, since it creates a new process.

      What you probably want to do is start your child process telling it to use your STDOUT as it's STDOUT.

      THRU 4x, SHELL has a "HANDLES" option which is explained (pick one) A) not at all or B) poorly.

      Check out this wording:
      The HANDLES option allows the child process to inherit the file handles opened by your program. This affects only Windows handles, not PowerBASIC file identifiers. It is an advanced option, for those who know it works and why they need it
      Um, if I know how it works and why I need it, I don't need the help file, do I?

      But I digress.

      If you use CreateProcess to start your child processes, you can use the standard handle members of the STARTUPINFO structure with the appropriate flags member bits.

      Or.....you can simply redirect the STDOUT of your child process to a file, and when the process completes, read that file and display its contents in YOUR console. (this is probably the easiest, although I am positive you want BEST, not EASIEST).

      Just don't tell me you are SHELLING to copy or delete or rename files... ie. things for which there are PB functions. That would compel me to say "Shame on You!" and we don't want that, do we?

      FWIW, hold off on the multiple threads. First you make it work; only then do you make it work better.

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

      Comment


      • #4
        Originally posted by Michael Mattias View Post
        SHELL creates multiple threads of execution, since it creates a new process. What you probably want to do is start your child process telling it to use your STDOUT as it's STDOUT.
        I probably should explain a bit more of what I'm doing. I'm writing an SNMP network application that polls via SNMP to tell what version of firmware is on each network device in a /24 IP range, and need it to also send firmware upgrades to the network devices. The first versions didn't use the THREAD statements at all, and were functional but very slow for certain things. Now that I've got things working, I'm translating certain portions creating THREADs, it's much faster and much more useful.

        However, when I use SHELL to call the manufacturer's firmware upgrade utility (an .exe written in C), it displays the status of the update process and that's so far limiting my ability to upgrade mutiple firmware's at once, without making an unreadable mess out of the display.

        THRU 4x, SHELL has a "HANDLES" option which is explained (pick one) A) not at all or B) poorly. Check out this wording:...
        Yea, I read that. It's pretty much what the Mercedes-Benz salesman told me... "If you have to ask the price, then you can't afford it."

        Generally speaking, I do understand what they're saying. I'm an ISP and we often say the same thing about Static/Public IP addresses. If you don't know what one is, then you don't need one. The only people that need them are the folks that know what they are and what they're for.

        If you use CreateProcess to start your child processes, you can use the standard handle members of the STARTUPINFO structure with the appropriate flags member bits.
        Sounds great.. I have no idea what that all means... I am using PB/CC and using the THREAD CREATE statements to launch threaded Functions, and for the functions that I've written, that's working OK.

        Or.....you can simply redirect the STDOUT of your child process to a file, and when the process completes, read that file and display its contents in YOUR console. (this is probably the easiest, although I am positive you want BEST, not EASIEST).
        Yes, I had tried this, but that didn't seem to work for me. That was exactly my initial plan, pipe the output to a file, and then watch that file for when it contains 'operation has completed successfuly', which is what the firmware upgrade utility ends execution with.

        So, from the command prompt, if I type

        fwupgrade.exe 1.2.3.4 password -f firmware.pkg > temp.txt
        of
        fwupgrade.exe > temp.txt 1.2.3.4 password -f firmware.pkg

        It'll run fine and pipe it's output to the temp.txt file.

        However, when I try..

        ProcessId = SHELL("fwupgrade.exe 1.2.3.4 password -f firmware.pkg > temp.txt")
        or
        ProcessID = SHELL("fwupgrade.exe > temp.txt 1.2.3.4 password -f firmware.pkg")

        from inside my PB/CC programs, it then displays fwupgrade.exe's 'usage' help file, as if I've provided it illegal parameters or something.

        PS. BEST is better, but EASIEST is OK too.

        Just don't tell me you are SHELLING to copy or delete or rename files... ie. things for which there are PB functions. That would compel me to say "Shame on You!" and we don't want that, do we?
        Nope, not to worry.
        FWIW, hold off on the multiple threads. First you make it work; only then do you make it work better.
        Agreed. I've got pretty much everything working as wanted, and parts (like pinging a Class-C or /24 block) that were very slow when single threaded, I've moved them to muti-threaded without a problem. However, when we need to do firmware upgrades on 20 network devices, we would like to spawn all these at the same time, and not to have to click & wait 20 individual times.

        So, I'd be glad to learn how I can redirect the output to a file, or how I can otherwise accomplish what I need. I feel 'so close' to having a great program here, but can't solve this last part..

        Comment


        • #5
          Code:
          SHELL("fwupgrade.exe 1.2.3.4 password -f firmware.pkg > temp.txt")
          If you want to use command-line redirection, you need to request the help of the command processor to parse out the command line .......
          Code:
          SHELL("CMD.EXE /C fwupgrade.exe 1.2.3.4 password -f firmware.pkg > temp.txt")
          (that's close anyway)

          Warning: you are at the mercy of "fwupgrade.exe" that it is sending its output to STDOUT when you do this. I know a lot of those utilities also send to STDERR, so you may want to redirect that as well. I think you can send to same file using the handle duplication available...



          ... but if not replacing "SHELL" with "CreateProcess" would certainly allow you to redirect both STDOUT and STDERR to the same file.

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

          Comment


          • #6
            OK Michael, thank you! That worked! I also then tried it with the SHELL FUNCTION as well, which also worked to redirect the output to a file and was synchronous code.

            Code:
            ProcessID = SHELL("CMD.EXE /C fwupgrade.exe 1.2.3.4 password -f firmware.pkg > temp.txt")
            Actually, since the user is selecting which network device and which firmware via a menu & mouse clicks, the actual code in my program looks like this.
            Code:
            ProcessID = SHELL("cmd.exe /c fwupgrade.exe " + cpe(T) + " " + password$ + " -f firmware\" + Firmware$(f) + " -a > temp.txt")
            ...replacing "SHELL" with "CreateProcess" would certainly allow you to redirect both STDOUT and STDERR to the same file.
            I think I may have a solution with the above and might not need to get into the API, which is a good thing. Thanx!
            Last edited by Todd Chamberlain; 18 Sep 2008, 02:54 AM.

            Comment


            • #7
              .... SHELL FUNCTION as well, which also worked to redirect the output to a file and was synchronous code.
              Is that a Typo?

              The SHELL FUNCTION ("X=SHELL(commandstring)") launches the target "A"-synchronously - it runs the targetr independent of your program, which continues immediately after the launch.

              SHELL STATEMENT ("SHELL commandstring") is synchronous... your program does not continue until the target process has completed.

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

              Comment

              Working...
              X