简体   繁体   English

以编程方式调用批处理文件时输出不正确

[英]Output not proper when calling batch file programatically

I was trying to automate server patch installation for my product and I came to know about Wix Toolset. 我试图自动为我的产品安装服务器补丁,然后才了解Wix Toolset。 I was hoping to get the JBoss Version in my installer. 我希望在安装程序中获得JBoss版本。 The command to get the same is standalone.bat --version from cmd. 获得相同命令的命令是来自cmd的standalone.bat --version So from my installer I created one CustomAction where I tried to run it and get the output. 因此,从安装程序中,我创建了一个CustomAction,试图在其中运行它并获取输出。

public static string runRunnableBatch(string path){
    Process exploitVersionService = new Process();
    string runnableBinPath = path;
    exploitVersionService.StartInfo.WorkingDirectory = path + "bin";
    exploitVersionService.StartInfo.FileName = path + "bin\\standalone.bat";
    exploitVersionService.StartInfo.CreateNoWindow = false;
    exploitVersionService.StartInfo.Arguments = string.Format("--version");
    exploitVersionService.StartInfo.UseShellExecute = false;
    exploitVersionService.StartInfo.RedirectStandardOutput = true;
    exploitVersionService.StartInfo.RedirectStandardInput = false;
    exploitVersionService.Start();
    exploitVersionService.WaitForExit();
    // /*
    string opt = "";
    while (!exploitVersionService.StandardOutput.EndOfStream){
        opt += exploitVersionService.StandardOutput.ReadLine();
    }
    // */
    //using (StreamWriter writer = new StreamWriter("D:\\_log.txt"))
    //using (StreamReader reader = exploitVersionService.StandardOutput){
    //    writer.AutoFlush = true;
    //    for (; ; ){
    //        string textLine = reader.ReadLine();
    //        if (textLine == null)
    //            break;
    //        writer.WriteLine(textLine);
    //    }
    //}
    //StreamReader exploitVersionFeed = exploitVersionService.StandardOutput;
    //string output = exploitVersionFeed.ReadToEnd();
    return opt;
}

When I was doing that, all I got as output was the first line of the whole output string. 当我这样做时,我得到的所有输出就是整个输出字符串的第一行。

I needed the whole string in my code so that from regular expression I could extract the version. 我需要代码中的整个字符串,以便可以从正则表达式中提取版本。

Also tried with 也尝试过

public static string runRunnableBatch(string path){
    string executableBinPath = path + "bin";
    string executableBinPath_BatchCmd = "cd " + "\"" + executableBinPath + "\"";
    string outputFileName = "TempVerInfoHolder.txt";
    string outputFilePath = executableBinPath+@"\TempVerInfoHolder1.txt";
    string versionRetriever_BatchCmd = @"standalone.bat --version > " + "\""+outputFilePath+"\"";
    string partitionName_BatchCmd = @Strings.Utils.getPartitionFromPath(path);

    // Creating command sequence
    SortedList<int, string> commandSequence = new SortedList<int, string>();

    // ~ d:
    commandSequence.Add(1, partitionName_BatchCmd);
    // ~ cd %path%
    commandSequence.Add(2, executableBinPath_BatchCmd);
    // ~ standalone.bat --version > %filename%
    commandSequence.Add(3, versionRetriever_BatchCmd);
    runCommandFromSequence(commandSequence);

    // Run together

    return "";
}

private static void runCommandFromSequence(SortedList<int, string> commandSequence){
    Process seqCmdExecHost = new Process();

    ProcessStartInfo psi = new ProcessStartInfo();
    psi.FileName = "cmd.exe";
    psi.RedirectStandardInput = true;
    psi.RedirectStandardOutput = true;
    psi.UseShellExecute = false;
    psi.CreateNoWindow = false;

    seqCmdExecHost.StartInfo = psi;
    seqCmdExecHost.Start();

    using (StreamWriter writer = seqCmdExecHost.StandardInput) {
        if (writer.BaseStream.CanWrite) {
            foreach (int item in commandSequence.Keys){
                MessageBox.Show(seqCmdExecHost.Id.ToString());
                MessageBox.Show(commandSequence[item]);
                writer.WriteLine(commandSequence[item]);   
            }
        }

        string opt = "";
        while (!seqCmdExecHost.StandardOutput.EndOfStream){
            opt += seqCmdExecHost.StandardOutput.ReadLine();
        }
    MessageBox.Show("Exited? " + seqCmdExecHost.HasExited);
    MessageBox.Show("O/P? " + opt);
    }
}

I have tried some other way as well. 我也尝试过其他方法。 Switching the commented code of the above function was one of them. 切换上述功能的注释代码就是其中之一。

Output getting while doing it from code level 从代码级别执行时的输出获取

Calling "D:\\Servers\\VA\\XYZ\\JBoss-7.1.1-Final\\bin\\standalone.conf.bat 调用“ D:\\ Servers \\ VA \\ XYZ \\ JBoss-7.1.1-Final \\ bin \\ standalone.conf.bat

Output while running the same command manually from cmd 从cmd手动运行相同命令时输出

Calling D:\\Servers\\VA\\XYZ\\JBoss-7.1.1-Final\\bin\\standalone.conf.bat 调用D:\\ Servers \\ VA \\ XYZ \\ JBoss-7.1.1-Final \\ bin \\ standalone.conf.bat

====================================================================== JBoss Bootstrap Environment ================================================== ==================== JBoss引导环境

JBOSS_HOME: D:\\Servers\\VA\\XYZ\\JBoss-7.1.1-Final JBOSS_HOME:D:\\ Servers \\ VA \\ XYZ \\ JBoss-7.1.1-Final

JAVA: C:\\Program Files\\Java\\jdk1.7.0_67\\bin\\java JAVA:C:\\ Program Files \\ Java \\ jdk1.7.0_67 \\ bin \\ java

JAVA_OPTS JAVA_OPTS

====================================================================== Listening for transport dt_socket at address: 8787 ================================================== ====================在地址8787上监听传输dt_socket

19:08:08,333 INFO [org.jboss.modules] JBoss Modules version 1.1.1.GA 19:08:08,333 INFO [org.jboss.modules] JBoss Modules 1.1.1.GA版本

JBoss AS 7.1.1.Final "Brontes" JBoss AS 7.1.1.Final“ Brontes”

Press any key to continue . 按任意键继续 。 . .

My observation is, the stream is getting closed once the nested standalone.conf.bat is getting called from standalone.bat. 我的观察是,一旦从standalone.bat调用了嵌套的standalone.conf.bat,流就会关闭。

If any workaround available to get the full output in string/buffer/stream, would be appreciated. 如果有任何变通办法可以获取字符串/缓冲区/流中的完整输出,将不胜感激。

Thanks 谢谢

What you could do is call the Command line Application instead of calling the batch file 您可以做的是调用命令行应用程序,而不是调用批处理文件

exploitVersionService.StartInfo.WorkingDirectory = path + "bin";
exploitVersionService.StartInfo.FileName = "cmd.exe";
exploitVersionService.StartInfo.CreateNoWindow = false;
exploitVersionService.StartInfo.Arguments = string.Format(" /c \"{0}\" --version",path + "bin\\standalone.bat");

I found one work around to do achieve this. 我找到了解决这一问题的方法。 I created the batch file programmatically and ran it with cmd. 我以编程方式创建了批处理文件,并使用cmd运行了该文件。

public static void createBatchToGetVersion(string path)
            {
                CustomLogger.getInstance().debug("Started creating batch file");
                BatchOps.executableBinPath = path + "bin";
                CustomLogger.getInstance().debug("Ëxecutable bin path: " + BatchOps.executableBinPath);
                BatchOps.tempBatchFileName = "JBossVerCmd.bat";
                BatchOps.holderFileName = @"JBossVerHolder.txt";
                BatchOps.absoluteHolderPath = Strings.Utils.normalize(executableBinPath) + holderFileName;
                CustomLogger.getInstance().debug("Normalized absoluteHolderPath: " + BatchOps.absoluteHolderPath);

                CustomLogger.getInstance().debug("Checking if JBOSS_HOME entered by user actuallty points to JBOSS");
                if (!File.Exists(Strings.Utils.normalize(executableBinPath) + "standalone.bat"))
                {
                    CustomLogger.getInstance().error("standalone.bat not found. JBOSS_HOME Dir is not correctly entered");
                    throw new CustomExceptions.DirectoryNotAcceptableException("Bad directory is assigned to JBOSS_HOME or JBOSS_HOME structure corrupted");
                }

                /*
                 * Batch file formation.
                 * Contains:
                 * Start file
                 * D:
                 * cd D:\Fusion Server\jboss 7.1.1\bin
                 * @echo | call standalone.bat --version > sample.txt   
                 * @echo Done
                 * End file
                 * @echo is required here because it exits the cmd when completed whithout having the user pressing any key
                */
                string changePartition_cmd = Strings.Utils.getPartitionFromPath(path);
                string changeDirectory_cmd = @"cd " + BatchOps.executableBinPath;
                string getVersion_cmd = @"@echo | call standalone.bat --version > " + holderFileName;
                string exitCmd = @"@echo Done";

                CustomLogger.getInstance().debug("Command to be written on batch file");
                CustomLogger.getInstance().debug("\r\n" + changePartition_cmd + "\r\n" + changeDirectory_cmd + "\r\n" + getVersion_cmd + "\r\n" + exitCmd);

                SortedList<int, string> commandSequence = new SortedList<int, string>();
                CustomLogger.getInstance().debug("Initializing command sequence.");
                commandSequence.Add(1, changePartition_cmd);
                commandSequence.Add(2, changeDirectory_cmd);
                commandSequence.Add(3, getVersion_cmd);
                commandSequence.Add(4, exitCmd);

                // Will create one if file never existed and open one delete the content and set the pointer to the begnning
                // if already existed
                StreamWriter batchFileWriter = null;
                try
                {
                    CustomLogger.getInstance().debug("Establishing stream to and from temp batch file");
                    batchFileWriter = new StreamWriter(tempBatchFileName);
                    CustomLogger.getInstance().debug("Command sequence ready to be written on temp batch file.");
                    Perform.writeToStreamFromSequence(batchFileWriter, commandSequence);
                    CustomLogger.getInstance().debug("Command sequence successfully written");
                }
                catch (IOException ex)
                {
                    CustomLogger.getInstance().error("Error while writing command sequence.\n" + ex.ToString());
                    // throw exception to CustomAction
                    throw new IOException("Error while writing commandSequence");

                }
                finally
                {
                    // Not required. Stream already closed in writeToStreamFromSequence
                }
            }


            public static void runTempBatchFile()
            {
                Process seqCmdExecHost = new Process();
                ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", @"/c " + BatchOps.tempBatchFileName);
                procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                seqCmdExecHost.StartInfo = procStartInfo;
                seqCmdExecHost.Start();
                seqCmdExecHost.WaitForExit();
                seqCmdExecHost.Close();
            }

I found the moment i was doing 我发现我正在做的那一刻

procStartInfo.UseShellExecute=true;
procStartInfo.RedirectStandardOutput=true

It was giving the first line of output. 它给出了输出的第一行。 Dont know why?. 不知道为什么? If anyone has any idea about it please explain. 如果有人对此有任何想法,请解释。

Thanks 谢谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM