Menu

WScript.Shell stdout/stderr

2008-11-21
2012-11-29
  • Michael Pitoniak

    team,

    i have created a utils class that allows me to execute a command and read the stdout/err streams on separate threads. if i collect just stdout the class works, but if i start the stderr reader thread the call blocks when i timout and try to destroy the session. it appears that when the stdout thread begins to collect it stops the stdout thread from commecting. any comments/help greatly appreciated, or if anyone has a class that executes a cli command and collects both streams plase post it.

    many thanks,

    mike

    [CODE]
    /*
    * Copyright (C) 2002 by Michael Pitoniak (pitoniakm@msn.com).
    *
    * This program is free software; you can redistribute it and/or
    * modify it under the terms of the GNU General Public License
    * as published by the Free Software Foundation; either version 2
    * of the License, or (at your option) any later version.
    *
    * This program is distributed in the hope that it will be useful,
    * but WITHOUT ANY WARRANTY; without even the implied warranty of
    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    * GNU General Public License for more details.
    *
    * You should have received a copy of the GNU General Public License
    * along with this program; if not, write to:
    *
    *   The Free Software Foundation, Inc.,
    *   59 Temple Place - Suite 330
    *   Boston, MA 02111-1307
    *   USA
    */

    package utils.dcomServices;

    import java.net.UnknownHostException;
    import java.util.logging.Level;

    import org.jinterop.dcom.common.JIException;
    import org.jinterop.dcom.common.JISystem;
    import org.jinterop.dcom.core.IJIComObject;
    import org.jinterop.dcom.core.JIComServer;
    import org.jinterop.dcom.core.JIProgId;
    import org.jinterop.dcom.core.JISession;
    import org.jinterop.dcom.core.JIString;
    import org.jinterop.dcom.core.JIVariant;
    import org.jinterop.dcom.impls.JIObjectFactory;
    import org.jinterop.dcom.impls.automation.IJIDispatch;

    /*
    * You create a WshShell object whenever you want to run a program locally, manipulate the contents of the registry,
    * create a shortcut, or access a system folder. The WshShell object provides the Environment collection.
    * This collection allows you to handle environmental variables (such as WINDIR, PATH, or PROMPT).
    * Microsoft® Windows® Script Host (WSH) is a language-independent scripting host for Windows Script compatible
    * scripting engines. It brings simple, powerful, and flexible scripting to the Windows 32-bit platform, allowing
    * you to run scripts from both the Windows desktop and the command prompt. Windows Script Host is ideal for
    * non-interactive scripting needs, such as logon scripting, administrative scripting, and machine automation.
    * A Windows script is a text file. You can create a script with any text editor as long as you save your script
    * with a WSH-compatible script extension (.js, vbs, or .wsf). In addition, WMI, for the most part, works exactly the same on remote computers as it does on the local computer. WSH, by contrast, is designed to work only on the local computer. To run WSH scripts remotely, you must use the WshController object and actually create two scripts: the script to be run and the script that allows that script to run remotely. (The WshController object is discussed in detail later in this chapter.)
    * In addition, WMI, for the most part, works exactly the same on remote computers as it does on the local
    * computer. WSH, by contrast, is designed to work only on the local computer. To run WSH scripts remotely,
    * you must use the WshController object and actually create two scripts: the script to be run and the script
    * that allows that script to run remotely. (The WshController object is discussed in detail later in this
    * chapter.)
    */

    public class DcomWScriptServices {
        private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(DcomWScriptServices.class);
        private JIComServer comServer = null;
        private IJIDispatch dispatch = null;
        private IJIComObject unknown = null;
        private JISession session = null;
       
       
        public DcomWScriptServices(String hostIp, String domain, String userName, String passWord) throws JIException, UnknownHostException{
            //to debug DCOM change this level
            JISystem.getLogger().setLevel(Level.SEVERE);
            /*Let the j-Interop library do this for you. You can set the "autoRegistration" flag in the
              JISystem class. When the library encounters a "Class not registered" exception, it will
              perform all the registry changes if the autoRegistration flag is set. And then re-attempt
              loading the COM Server. Please have a look at MSSysInfo,MSWMI examples.*/
            JISystem.setAutoRegisteration(true);
            session = JISession.createSession(domain, userName, passWord);
            comServer = new JIComServer(JIProgId.valueOf("WScript.Shell"), hostIp, session);
            unknown = comServer.createInstance();
            dispatch = (IJIDispatch)JIObjectFactory.narrowObject(unknown.queryInterface(IJIDispatch.IID));
        }
       
        public void setCurrentDirectory(String path) throws JIException{
            logger.info(comServer.getProperties());
           
            JIVariant jv = (JIVariant)dispatch.get("CurrentDirectory");
            logger.info(jv.getObjectAsString().getString());
           
            int dispId = dispatch.getIDsOfNames("CurrentDirectory");
            logger.info(dispId);
            JIVariant variant = new JIVariant(path);
            dispatch.put(dispId,variant);
           
            jv = (JIVariant)dispatch.get("CurrentDirectory");
            logger.info(jv.getObjectAsString().getString());
        }
       
        //objShell.CurrentDirectory = "C:\Program Files\Microsoft Virtual PC\"
        //szRun = """Virtual PC.exe"" -singlepc -pc " & szImageName & " -launch"
        public void startVPC(String imageName) throws JIException, UnknownHostException{
           
            JIVariant jv = (JIVariant)dispatch.get("CurrentDirectory");
            logger.info(jv.getObjectAsString().getString());
           
            int dispId = dispatch.getIDsOfNames("CurrentDirectory");
            logger.info(dispId);
            JIVariant variant = new JIVariant("C:/Program Files/Microsoft Virtual PC/");
            dispatch.put(dispId,variant);
           
            jv = (JIVariant)dispatch.get("CurrentDirectory");
            logger.info(jv.getObjectAsString().getString());
           
            //get short file name with dir /x
            //String appName = "VIRTUA~1.EXE -singlepc -pc " + imageName + " -launch";
            //String appName = "\"Virtual PC.exe\" -singlepc -pc " + imageName + " -launch";
            //String appName = "notepad.exe";
            //logger.info(appName);
           
            //"""Virtual PC.exe"" -singlepc -pc " & szImageName & " -launch"
            JIVariant[] b = dispatch.callMethodA("Run", new Object[]{new JIString("\"Virtual PC.exe\" -singlepc -pc " + imageName + " -launch"),new JIVariant(1), new JIVariant(Boolean.FALSE)});
            logger.info(b[0].getObjectAsInt());
           
            //dispatch.callMethod("Exec", new Object[]{new JIString("\"Virtual PC.exe\" -singlepc -pc " + imageName + " -launch")});
        }
       
        /*Runs a program in a new process.

         * object.Run(strCommand, [intWindowStyle], [bWaitOnReturn]) 

         Arguments
        object
        WshShell object.

        strCommand
        String value indicating the command line you want to run. You must include any parameters you want to pass to the executable file.

        intWindowStyle
        Optional. Integer value indicating the appearance of the program's window. Note that not all programs make use of this information.

        bWaitOnReturn
        Optional. Boolean value indicating whether the script should wait for the program to finish executing before continuing to the next statement in your script. If set to true, script execution halts until the program finishes, and Run returns any error code returned by the program. If set to false (the default), the Run method returns immediately after starting the program, automatically returning 0 (not to be interpreted as an error code).

         Remarks
        The Run method returns an integer. The Run method starts a program running in a new Windows process. You can have your script wait for the program to finish execution before continuing. This allows you to run scripts and programs synchronously. Environment variables within the argument strCommand are automatically expanded. If a file type has been properly registered to a particular program, calling run on a file of that type executes the program. For example, if Word is installed on your computer system, calling Run on a *.doc file starts Word and loads the document. The following table lists the available settings for intWindowStyle.

        intWindowStyle
         Description
        
        0
         Hides the window and activates another window.
        
        1
         Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
        
        2
         Activates the window and displays it as a minimized window.
        
        3
         Activates the window and displays it as a maximized window.
        
        4
         Displays a window in its most recent size and position. The active window remains active.
        
        5
         Activates the window and displays it in its current size and position.
        
        6
         Minimizes the specified window and activates the next top-level window in the Z order.
        
        7
         Displays the window as a minimized window. The active window remains active.
        
        8
         Displays the window in its current state. The active window remains active.
        
        9
         Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window.
        
        10
         Sets the show-state based on the state of the program that started the application.
         */
        

        public int run(String command) throws Exception{
            JIVariant[] jvArr = dispatch.callMethodA("Run", new Object[]{new JIString(command), new JIVariant(1), new JIVariant(Boolean.TRUE)});
            return jvArr[0].getObjectAsInt();
        }
       
        /*
         * Runs an application in a child command-shell, providing access to the stdin/stdout/stderr channels,
         * and the sharing of environment variables.
         */
        public String exec(String command, long timeOuMs) throws Exception{
            ExecThread execThread = new ExecThread(command, timeOuMs);
            System.out.println("start");
            execThread.start();
            System.out.println("join");
            execThread.join(timeOuMs);
            System.out.println("exec done...");
            return execThread.getResponse();
        }
       
       
       
        /*Runs an application in a child command-shell, providing access to the StdIn/StdOut/StdErr streams.

    object.Exec(strCommand)

    Arguments
    object
    WshShell object.

    strCommand
    String value indicating the command line used to run the script. The command line should appear exactly as it would if you typed it at the command prompt.

    Remarks
    The Exec method returns a WshScriptExec object, which provides status and error information about a script run with Exec along with access to the StdIn, StdOut, and StdErr channels. The Exec method allows the execution of command line applications only. The Exec method cannot be used to run remote scripts. Do not confuse the Exec method with the Execute method (of the WshRemote object).

    */
       
       
        public void destroySession() throws Exception{
            JISession.destroySession(session);
        }
       
        private class ExecThread extends Thread{
            String command = null;
            long timeOuMs = -1;
            StdOutThread stdOutThread = null;
            StdErrThread stdErrThread = null;
           
            public ExecThread(String command, long timeOuMs){
                this.command = command;
                this.timeOuMs =timeOuMs;
            }
           
            public void run(){
                IJIDispatch wshScriptExec = null;
                try{
                    JIVariant[] jvArr =  dispatch.callMethodA("Exec", new Object[]{new JIString(command)});
                    wshScriptExec = (IJIDispatch)JIObjectFactory.narrowObject(jvArr[0].getObjectAsComObject());
                    System.out.println("here");
                    try{Thread.sleep(5000);}catch(Exception e){}
                    stdOutThread = new StdOutThread(wshScriptExec);
                    stdOutThread.start();
                    System.out.println("started StdOutThread");
                    stdErrThread = new StdErrThread(wshScriptExec);
                    stdErrThread.start();
                    System.out.println("started StdErrThread");
                    stdOutThread.join(timeOuMs);
                    System.out.println("joined up on StdOutThread");
                    stdOutThread.stop();
                    //stdErrThread.join(timeOuMs);
                    System.out.println("joined up on StdErrThread");
                }catch(Exception e){
                    logger.error(e, e);
                }finally{
                    System.out.println("Terminating");
                    try{wshScriptExec.callMethodA("Terminate");}catch(Exception e){}
                    System.out.println("Done Terminating");
                    System.out.println("destroyed");
                }
            }
           
            public String getResponse(){
                return stdOutThread.getResponse() + stdErrThread.getResponse();
            }
        }
       
        private class StdOutThread extends Thread{
            IJIDispatch wshScriptExec = null;
            private StringBuffer sb = new StringBuffer();
           
            public StdOutThread(IJIDispatch wshScriptExec){
                this.wshScriptExec = wshScriptExec;
            }
           
            public void run(){
                try{
                    JIVariant jIVariant =  wshScriptExec.get("StdOut");
                    IJIDispatch stdOut = (IJIDispatch)JIObjectFactory.narrowObject(jIVariant.getObjectAsComObject());
                    JIVariant[] jvArr = null;//stdOut.callMethodA("Read", new Object[]{new JIVariant(1)});
                    while(!((JIVariant)stdOut.get("AtEndOfStream")).getObjectAsBoolean()){
                        jvArr = stdOut.callMethodA("Read", new Object[]{new JIVariant(1)});
                        String s = jvArr[0].getObjectAsString().getString();
                        System.out.println(s);
                        sb.append(s);
                    }
                }catch(Exception e){
                    logger.error(e, e);
                }
            }
           
            public String getResponse(){
                return sb.toString();
            }
        }
       
        private class StdErrThread extends Thread{
            IJIDispatch wshScriptExec = null;
            private StringBuffer sb = new StringBuffer();
           
            public StdErrThread(IJIDispatch wshScriptExec){
                this.wshScriptExec = wshScriptExec;
            }
           
            public void run(){
                try{
                    JIVariant jIVariant =  wshScriptExec.get("StdErr");
                    IJIDispatch stdErr = (IJIDispatch)JIObjectFactory.narrowObject(jIVariant.getObjectAsComObject());
                    JIVariant[] jvArr = null;//stdErr.callMethodA("Read", new Object[]{new JIVariant(1)});
                    while(!((JIVariant)stdErr.get("AtEndOfStream")).getObjectAsBoolean()){
                        jvArr = stdErr.callMethodA("Read", new Object[]{new JIVariant(1)});
                        String s = jvArr[0].getObjectAsString().getString();
                        System.out.println(s);
                        sb.append(s);
                    }
                }catch(Exception e){
                    logger.error(e, e);
                }
            }
           
            public String getResponse(){
                return sb.toString();
            }
        }
       
       
        //"localhost", "ctron", "mpitonia", "ChrisSarah1"
        //"VPC003", "automation" , "automated_user", "@utom@tion"
        //"automationsvr01", "AUTOMATION", "Automated_User", "@utom@tion"
        public static void main(String[] args) {
            DcomWScriptServices wScriptServices = null;
           
            try{
                wScriptServices = new DcomWScriptServices("localhost", "ctron", "mpitonia", "TestHarness!");
                //wScriptServices.startVPC("VPC002");
                //logger.info(wScriptServices.exec("ping -n 3 -w 2000 localhost"));
                //logger.info(wScriptServices.exec("ipconfig"));
                logger.info(wScriptServices.exec("cmd /C dir c:\\a /s", 10000));
                //logger.info(wScriptServices.exec("cmd /C echo test >> c:\\a.txt"));
                //logger.info(wScriptServices.run("cmd /C attrib +r  c:\\a.txt"));
                //logger.info(wScriptServices.run("notepad.exe"));
                //logger.info(wScriptServices.run("cmd /k"));
                //logger.info(wScriptServices.ping("localhost"));
            }catch (Exception e) {
                logger.error(e, e);
            }finally{
                try{
                    wScriptServices.destroySession();
                }catch(Exception e){
                    //silent
                }
            }
        }
       
       
    }

    [/CODE]

     
    • Michael Pitoniak

      correction in last post:

      it appears that when the stderr thread begins to collect it stops the stdout thread from collecting.

       
    • Michael Pitoniak

      team,

      here is a version that works using just one thread to read the streams...it appears that reading stdio/stferr is not thread safe. i am not happy with how the streams are collected, as i believe it is still a bit eror prone. any suggestions/enhancements welcome.

      thx,

      mike

      [CODE]

      /*
      * Copyright (C) 2002 by Michael Pitoniak (pitoniakm@msn.com).
      *
      * This program is free software; you can redistribute it and/or
      * modify it under the terms of the GNU General Public License
      * as published by the Free Software Foundation; either version 2
      * of the License, or (at your option) any later version.
      *
      * This program is distributed in the hope that it will be useful,
      * but WITHOUT ANY WARRANTY; without even the implied warranty of
      * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      * GNU General Public License for more details.
      *
      * You should have received a copy of the GNU General Public License
      * along with this program; if not, write to:
      *
      * The Free Software Foundation, Inc.,
      * 59 Temple Place - Suite 330
      * Boston, MA 02111-1307
      * USA
      */

      package utils.dcomServices;

      import java.net.UnknownHostException;
      import java.util.logging.Level;

      import org.jinterop.dcom.common.JIException;
      import org.jinterop.dcom.common.JISystem;
      import org.jinterop.dcom.core.IJIComObject;
      import org.jinterop.dcom.core.JIComServer;
      import org.jinterop.dcom.core.JIProgId;
      import org.jinterop.dcom.core.JISession;
      import org.jinterop.dcom.core.JIString;
      import org.jinterop.dcom.core.JIVariant;
      import org.jinterop.dcom.impls.JIObjectFactory;
      import org.jinterop.dcom.impls.automation.IJIDispatch;

      /*
      * You create a WshShell object whenever you want to run a program locally, manipulate the contents of the registry, 
      * create a shortcut, or access a system folder. The WshShell object provides the Environment collection. 
      * This collection allows you to handle environmental variables (such as WINDIR, PATH, or PROMPT). 
      * Microsoft® Windows® Script Host (WSH) is a language-independent scripting host for Windows Script compatible 
      * scripting engines. It brings simple, powerful, and flexible scripting to the Windows 32-bit platform, allowing 
      * you to run scripts from both the Windows desktop and the command prompt. Windows Script Host is ideal for 
      * non-interactive scripting needs, such as logon scripting, administrative scripting, and machine automation. 
      * A Windows script is a text file. You can create a script with any text editor as long as you save your script 
      * with a WSH-compatible script extension (.js, vbs, or .wsf). In addition, WMI, for the most part, works exactly the same on remote computers as it does on the local computer. WSH, by contrast, is designed to work only on the local computer. To run WSH scripts remotely, you must use the WshController object and actually create two scripts: the script to be run and the script that allows that script to run remotely. (The WshController object is discussed in detail later in this chapter.)
      * In addition, WMI, for the most part, works exactly the same on remote computers as it does on the local 
      * computer. WSH, by contrast, is designed to work only on the local computer. To run WSH scripts remotely, 
      * you must use the WshController object and actually create two scripts: the script to be run and the script 
      * that allows that script to run remotely. (The WshController object is discussed in detail later in this 
      * chapter.)
      */

      public class DcomWScriptServices {
      private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(DcomWScriptServices.class);
      private JIComServer comServer = null;
      private IJIDispatch dispatch = null;
      private IJIComObject unknown = null; 
      private JISession session = null;

      public DcomWScriptServices(String hostIp, String domain, String userName, String passWord) throws JIException, UnknownHostException{
      //to debug DCOM change this level
      JISystem.getLogger().setLevel(Level.SEVERE);
      /*Let the j-Interop library do this for you. You can set the "autoRegistration" flag in the 
      JISystem class. When the library encounters a "Class not registered" exception, it will 
      perform all the registry changes if the autoRegistration flag is set. And then re-attempt 
      loading the COM Server. Please have a look at MSSysInfo,MSWMI examples.*/
      JISystem.setAutoRegisteration(true);
      session = JISession.createSession(domain, userName, passWord);
      comServer = new JIComServer(JIProgId.valueOf("WScript.Shell"), hostIp, session);
      unknown = comServer.createInstance();
      dispatch = (IJIDispatch)JIObjectFactory.narrowObject(unknown.queryInterface(IJIDispatch.IID));
      }

      public void setCurrentDirectory(String path) throws JIException{
      logger.info(comServer.getProperties());

      JIVariant jv = (JIVariant)dispatch.get("CurrentDirectory");
      logger.info(jv.getObjectAsString().getString());

      int dispId = dispatch.getIDsOfNames("CurrentDirectory");
      logger.info(dispId);
      JIVariant variant = new JIVariant(path);
      dispatch.put(dispId,variant);

      jv = (JIVariant)dispatch.get("CurrentDirectory");
      logger.info(jv.getObjectAsString().getString());
      }

      //objShell.CurrentDirectory = "C:\Program Files\Microsoft Virtual PC\"
      //szRun = """Virtual PC.exe"" -singlepc -pc " & szImageName & " -launch" 
      public void startVPC(String imageName) throws JIException, UnknownHostException{

      JIVariant jv = (JIVariant)dispatch.get("CurrentDirectory");
      logger.info(jv.getObjectAsString().getString());

      int dispId = dispatch.getIDsOfNames("CurrentDirectory");
      logger.info(dispId);
      JIVariant variant = new JIVariant("C:/Program Files/Microsoft Virtual PC/");
      dispatch.put(dispId,variant);

      jv = (JIVariant)dispatch.get("CurrentDirectory");
      logger.info(jv.getObjectAsString().getString());

      //get short file name with dir /x
      //String appName = "VIRTUA~1.EXE -singlepc -pc " + imageName + " -launch";
      //String appName = "\"Virtual PC.exe\" -singlepc -pc " + imageName + " -launch";
      //String appName = "notepad.exe";
      //logger.info(appName);

      //"""Virtual PC.exe"" -singlepc -pc " & szImageName & " -launch" 
      JIVariant[] b = dispatch.callMethodA("Run", new Object[]{new JIString("\"Virtual PC.exe\" -singlepc -pc " + imageName + " -launch"),new JIVariant(1), new JIVariant(Boolean.FALSE)});
      logger.info(b[0].getObjectAsInt());

      //dispatch.callMethod("Exec", new Object[]{new JIString("\"Virtual PC.exe\" -singlepc -pc " + imageName + " -launch")});
      }

      /*Runs a program in a new process. 

      * object.Run(strCommand, [intWindowStyle], [bWaitOnReturn]) 

      Arguments 
      object
      WshShell object. 

      strCommand
      String value indicating the command line you want to run. You must include any parameters you want to pass to the executable file. 

      intWindowStyle
      Optional. Integer value indicating the appearance of the program's window. Note that not all programs make use of this information. 

      bWaitOnReturn
      Optional. Boolean value indicating whether the script should wait for the program to finish executing before continuing to the next statement in your script. If set to true, script execution halts until the program finishes, and Run returns any error code returned by the program. If set to false (the default), the Run method returns immediately after starting the program, automatically returning 0 (not to be interpreted as an error code). 

      Remarks 
      The Run method returns an integer. The Run method starts a program running in a new Windows process. You can have your script wait for the program to finish execution before continuing. This allows you to run scripts and programs synchronously. Environment variables within the argument strCommand are automatically expanded. If a file type has been properly registered to a particular program, calling run on a file of that type executes the program. For example, if Word is installed on your computer system, calling Run on a *.doc file starts Word and loads the document. The following table lists the available settings for intWindowStyle. 

      intWindowStyle 
      Description 


      Hides the window and activates another window. 


      Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time. 


      Activates the window and displays it as a minimized window. 


      Activates the window and displays it as a maximized window. 


      Displays a window in its most recent size and position. The active window remains active. 


      Activates the window and displays it in its current size and position. 


      Minimizes the specified window and activates the next top-level window in the Z order. 


      Displays the window as a minimized window. The active window remains active. 


      Displays the window in its current state. The active window remains active. 


      Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window. 

      10 
      Sets the show-state based on the state of the program that started the application. 
      */

      public int run(String command) throws Exception{
      JIVariant[] jvArr = dispatch.callMethodA("Run", new Object[]{new JIString(command), new JIVariant(1), new JIVariant(Boolean.TRUE)});
      return jvArr[0].getObjectAsInt();
      }

      /* 
      * Runs an application in a child command-shell, providing access to the stdin/stdout/stderr channels, 
      * and the sharing of environment variables.
      */
      public String exec(String command, long timeOuMs) throws Exception{
      /*IJIDispatch wshScriptExec = null;
      StdOutThread stdOutThread = null;
      try{
      JIVariant[] jvArr = dispatch.callMethodA("Exec", new Object[]{new JIString(command)});
      wshScriptExec = (IJIDispatch)JIObjectFactory.narrowObject(jvArr[0].getObjectAsComObject());
      System.out.println("here");
      try{Thread.sleep(5000);}catch(Exception e){}
      stdOutThread = new StdOutThread(wshScriptExec);
      stdOutThread.start();
      System.out.println("started StdOutThread");
      stdOutThread.join(timeOuMs);
      System.out.println("joined up on StdOutThread");
      stdOutThread.stop();
      }catch(Exception e){
      logger.error(e, e);
      }finally{
      System.out.println("Terminating");
      try{wshScriptExec.callMethodA("Terminate");}catch(Exception e){}
      System.out.println("Done Terminating");
      System.out.println("destroyed");
      }

      return stdOutThread.getStdOut() + stdOutThread.getStdErr();*/

      ExecThread execThread = new ExecThread(command, timeOuMs);
      execThread.start();
      execThread.join(timeOuMs);
      return execThread.getResponse();
      }

      /*Runs an application in a child command-shell, providing access to the StdIn/StdOut/StdErr streams. 

      object.Exec(strCommand) 

      Arguments 
      object
      WshShell object. 

      strCommand
      String value indicating the command line used to run the script. The command line should appear exactly as it would if you typed it at the command prompt. 

      Remarks 
      The Exec method returns a WshScriptExec object, which provides status and error information about a script run with Exec along with access to the StdIn, StdOut, and StdErr channels. The Exec method allows the execution of command line applications only. The Exec method cannot be used to run remote scripts. Do not confuse the Exec method with the Execute method (of the WshRemote object). 

      */

      public void destroySession() throws Exception{
      JISession.destroySession(session);
      }

      private class ExecThread extends Thread{
      String command = null;
      long timeOuMs;
      StreamReaderThread streamReaderThread = null;

      public ExecThread(String command, long timeOuMs){
      this.command = command;
      this.timeOuMs = timeOuMs;
      }

      public void run(){
      IJIDispatch wshScriptExec = null;
      try{
      JIVariant[] jvArr = dispatch.callMethodA("Exec", new Object[]{new JIString(command)});
      wshScriptExec = (IJIDispatch)JIObjectFactory.narrowObject(jvArr[0].getObjectAsComObject());
      streamReaderThread = new StreamReaderThread(wshScriptExec);
      streamReaderThread.start();
      streamReaderThread.join(timeOuMs);
      streamReaderThread.stop();
      }catch(Exception e){
      logger.error(e, e);
      }finally{
      try{wshScriptExec.callMethodA("Terminate");}catch(Exception e){}
      }
      }

      public String getResponse(){
      return streamReaderThread.getStdOut() + streamReaderThread.getStdErr();
      }
      }

      private class StreamReaderThread extends Thread{
      IJIDispatch wshScriptExec = null;
      private StringBuffer stdOutBuffer = null;
      private StringBuffer stdErrBuffer = null;

      public StreamReaderThread(IJIDispatch wshScriptExec){
      this.wshScriptExec = wshScriptExec;
      }

      public void run(){
      JIVariant[] jvArr = null;
      try{
      stdOutBuffer = new StringBuffer();
      stdErrBuffer = new StringBuffer();
      JIVariant stdOutJIVariant = wshScriptExec.get("StdOut");
      IJIDispatch stdOut = (IJIDispatch)JIObjectFactory.narrowObject(stdOutJIVariant.getObjectAsComObject()); 
      JIVariant stdErrJIVariant = wshScriptExec.get("StdErr");
      IJIDispatch stdErr = (IJIDispatch)JIObjectFactory.narrowObject(stdErrJIVariant.getObjectAsComObject()); 
      while(!((JIVariant)stdOut.get("AtEndOfStream")).getObjectAsBoolean()){
      stdOutBuffer.append(stdOut.callMethodA("ReadAll").getObjectAsString().getString());
      }
      while(!((JIVariant)stdErr.get("AtEndOfStream")).getObjectAsBoolean()){
      stdErrBuffer.append(stdErr.callMethodA("ReadAll").getObjectAsString().getString());
      }
      }catch(Exception e){
      logger.error(e, e);
      }
      }

      public String getStdOut(){
      return stdOutBuffer.toString();
      }

      public String getStdErr(){
      return stdErrBuffer.toString();
      }
      }

      //"localhost", "ctron", "mpitonia", "ChrisSarah1"
      //"VPC003", "automation" , "automated_user", "@utom@tion"
      //"automationsvr01", "AUTOMATION", "Automated_User", "@utom@tion"
      public static void main(String[] args) {
      DcomWScriptServices wScriptServices = null;

      try{
      wScriptServices = new DcomWScriptServices("localhost", "ctron", "mpitonia", "TestHarness!");
      //wScriptServices.startVPC("VPC002");
      //logger.info(wScriptServices.exec("ping -n 3 -w 2000 localhost"));
      //logger.info(wScriptServices.exec("ipconfig"));
      System.out.println((wScriptServices.exec("cmd /C dir c:\\ann /s", 10000)));
      //logger.info(wScriptServices.exec("cmd /C echo test >> c:\\a.txt"));
      //logger.info(wScriptServices.run("cmd /C attrib +r c:\\a.txt"));
      //logger.info(wScriptServices.run("notepad.exe"));
      //logger.info(wScriptServices.run("cmd /k"));
      //logger.info(wScriptServices.ping("localhost"));
      }catch (Exception e) {
      logger.error(e, e);
      }finally{
      try{
      wScriptServices.destroySession();
      }catch(Exception e){
      //silent
      }
      }
      }

      }

      {/CODE]

       
  • sai kumar

    sai kumar - 2010-04-07

    Hi ,
    I used your example to try some . "AtEndOfStream" is never returning true . It always hungs when you reach end of command output. Tried with  ver command , netstat -a command. If you have any suggestions plz pass in .

      while(!((JIVariant)stdOut.get("AtEndOfStream")).getObjectAsBoolean()){
        JIVariant j = stdOut.callMethodA("ReadLine");
        String s = j.getObjectAsString().getString()+"\n";
        System.out.println(s);
        sb.append(s);
        }

    Thanks
    Regards
    SK
       

     

Log in to post a comment.