VB.Net shell output sometimes not returning - vb.net

for 99% of all my Shell commands this code works fine, but for just one command I don't get the returned text, which is normally visible in the Shell window. Here is the code I use to execute commands and read back the results:
Function RunCommandCom(command As String, arguments As String) As String()
Dim p As Process = New Process()
Dim pi As ProcessStartInfo = New ProcessStartInfo()
Dim output As String
pi.Arguments = " " + "/c" + " " + command + " " + arguments
pi.FileName = "cmd.exe"
pi.RedirectStandardOutput = True 'pi.CreateNoWindow = True
pi.WindowStyle = ProcessWindowStyle.Normal
pi.UseShellExecute = False
p.StartInfo = pi
p.Start()
output = p.StandardOutput.ReadToEnd()
p.WaitForExit()
p.Close()
If output Is ""
Then
Return Nothing
Else
Return output.Replace(Chr(13), "").Split(Chr(10))
End If
End Function
The command making Problems is executed fine. It shall create a entry in a database, which defintly is existing after calling my funciton. Executing the command directly in a Shell generates the same entry and I can see the returned text.
Does anyone has an idea why the streamreader does not read/contain anything for exactly this one special command?

Arg. I found the problem. These two commands send their output to the StandardError stream. I don't know why, as no error occured.

Related

How to start a visible process

I have the following code to start the program R (even though I think that the program is not relevent for the problem here) and run a script:
Public Shared Sub RunRScript(rCodeFilePath As String, rScriptExecutablePath As String, args As String)
Dim file As String = rCodeFilePath
Dim result As String = String.Empty
Try
Dim info = New ProcessStartInfo()
info.FileName = rScriptExecutablePath
info.WorkingDirectory = Path.GetDirectoryName(rScriptExecutablePath)
info.Arguments = rCodeFilePath & " " & args
info.RedirectStandardInput = False
info.RedirectStandardOutput = True
info.UseShellExecute = False
info.CreateNoWindow = True
Using proc = New Process()
proc.StartInfo = info
proc.Start()
result = proc.StandardOutput.ReadToEnd()
proc.Close()
End Using
Catch ex As Exception
Throw New Exception("R Script failed: " & result, ex)
End Try
End Sub
Problem is, if there is an error in the script I run within R I dont get an error message because the instance is invisible. I tried to make it visible with
.WindowStyle = ProcessWindowStyle.Normal
in all combinations of .UseShellExcecute and .CreateNoWindow but this is not working. Could anyone help me to can make my process visible?
Since you are redirecting StandardInput and StandardOutput, you should now redirect StandardError to trap the errors also.
More info available on MSDN

Displaying the output of Process.Start

I have a Process.Start command that I would like to see the output of, but the new window is opening and closing too quickly for me to see anything. Here is the code I have so far that I'm working with:
System.Diagnostics.Process.Start(Environment.GetEnvironmentVariable("VS110COMNTOOLS") & "..\Ide\MSTEST.EXE", "/Testsettings: """ & rwSettings & "" & " /Testcontainer: """ & rwContainer & "" & " /Resultsfile: """ & rwResults & "")
Unfortunately as I try to debug this if I allow this to run it flashes up the window but doesn't let me see what the error is, or if it's running successfully at all. I'm using VS2012 so I might just not be looking at the right view when I'm debugging.
Here is some code taen out of the middle of some logic, so it is not standalone. You can use ProcessStartInfo() and Process() to have more control:
Dim start_info As New ProcessStartInfo("sqlcmd", cmd)
start_info.UseShellExecute = False
start_info.CreateNoWindow = True
start_info.RedirectStandardOutput = True
start_info.RedirectStandardError = True
' Make the process and set its start information.
Dim proc As New Process()
proc.StartInfo = start_info
Dim dt As Date = Now()
' Start the process.
proc.Start()
' Attach to stdout and stderr.
Dim std_out As StreamReader = proc.StandardOutput() ' will not continue until process stops
Dim std_err As StreamReader = proc.StandardError()
' Retrive the results.
Dim sOut As String = std_out.ReadToEnd()
Dim sErr As String = std_err.ReadToEnd()

cmd process not exiting

I was running the following code to execute commands from vb.net app.
Dim CMDServer As Diagnostics.ProcessStartInfo
Dim CMDReply As Diagnostics.Process
CMDServer = New Diagnostics.ProcessStartInfo
CMDServer.WorkingDirectory = "C:/"
CMDServer.FileName = "cmd.exe"
CMDServer.UseShellExecute = False
CMDServer.RedirectStandardOutput = True
CMDServer.RedirectStandardError = True
CMDServer.CreateNoWindow = True
CMDServer.Arguments = "/C " + command
CMDReply = Process.Start(CMDServer)
MsgBox("START")
Dim Reply As String = ""
If Not CMDReply.HasExited Then
CMDReply.WaitForExit()
End If
MsgBox("EXIT")
Try
Dim ext = CMDReply.ExitCode
Reply = CMDReply.StandardOutput.ReadToEnd()
MsgBox(ext.ToString + " " + Reply)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
it works fine for almost all commands, but when the command="help" the program stucks on CMDReply.WaitForExit(). Can anyone explain what may be the problem here?
Standard deadlock. Read the output first and then wait for exit. The
program cannot exit until you've read all of its output. The code you
have can only work if there's little output that fits the buffer.
From Hans Passant's comment

Executing 7-zip from VB

Alright, I'm having a little trouble getting 7-zip to execute from VB.
Here's my current code:
ZipFileName = "\\network\path\PDFs\Test.zip "
PathToPDFs = "\\network\path\PDFs\*.pdf"
Arg1 = "a -tzip"
Process.Start("C:\Program Files\7-Zip\7z.exe" + Arg1 + Zipfilename + PathToPDFs)
The error I keep getting is The system cannot find the file specified and Win32Exception was unhandled
I know my path is correct and there are PDFs in that directory.
Any suggestions?
You have to use this
Process.Start(
"C:\Program Files\7-Zip\7z.exe",
Arg1 + Zipfilename + PathToPDFs)
First argument must be ONLY executable, while second one must be ProcessInfo or a string with arguments.
Tkae a look at this Microsoft page.
I did something similar with gzip like this:
Dim proc As System.Diagnostics.Process = New System.Diagnostics.Process()
proc.EnableRaisingEvents = False
proc.StartInfo.FileName = "d:\gnuwin32\bin\gzip"
proc.StartInfo.Arguments = My.Settings.GZIPFlags & " " & strDestDir & strFile
proc.Start()
proc.WaitForExit()

Reading Console Output to write out an error log VB

I am running some commands on computers and I would like to have them output a seperate text file if the command cannot run.
For Each strUserName As String In strLines
Dim ReplaceCommand As String = sCommand.Replace("*", strUserName).Replace("$$$", saveFileDialog3.FileName & ".txt").Replace("###", exeSearch)
Shell("cmd.exe /c" & ReplaceCommand, AppWinStyle.Hide, True, )
' If Command Cannot Execute, List Why and Move onto Next Command
Using swrr As New StreamWriter(File.Open(ErrorLog, FileMode.OpenOrCreate))
If Console.Readline = "blahblah" Then swrr.WriteLine("FAIL") Else swrr.WriteLine("PASS")
End Using
Next
Am I on the right track? I am getting an output to a text file but its just one line ans always says PASS.
Several things: you're creating a new StreamWriter every time you want to write a line to it, instead of creating one then just writing to it when you need to. You're still using shell which is really basic, and not really suited for what you need. You should really be using a process for this.
I've written a function for you to use to execute the process instead of using the shell, which will return the output from the command execution to the ConsoleOutput variable, which you can then check for output strings.
Lastly, you should be using String.Format instead of replace to create the correct string for the command to run. For example:
Dim FirstName As String = "Jay"
Dim Age As String = "twenty"
Dim Greeting As String = String.Format("Hello {0}, I know you're {1} years old", FirstName, Age)
' Greetings value would be "Hello Jay, I know you're twenty years old"
So tweak the below to suit, specifically the Args variable, USING THE STRING.FORMAT function :)
Sub DoWork()
Dim ConsoleOutput As String = String.Empty
Using swrr As New StreamWriter(ErrorLog, True)
For Each strUserName As String In StrLines
ConsoleOutput = GetCMDOuput(strUserName, saveFileDialog3.FileName, exeSearch)
' If Command Cannot Execute, List Why and Move onto Next Command
If ConsoleOutput = "blahblah" Then swrr.WriteLine("FAIL") Else swrr.WriteLine("PASS")
Next
End Using
End Sub
Function GetCMDOuput(ByVal strUserName As String, ByVal strFileName As String, ByVal strExeSearch As String) As String
Dim Args As String = String.Format("/c -paramzero {0} -paramone {1} -paramtwo {2}", strUserName, strFileName, strExeSearch)
Dim CMD As New Process
CMD.StartInfo.FileName = "cmd.exe"
CMD.StartInfo.Arguments = Args
CMD.StartInfo.UseShellExecute = False
CMD.StartInfo.RedirectStandardInput = True
CMD.StartInfo.RedirectStandardOutput = True
CMD.StartInfo.CreateNoWindow = True
CMD.Start()
Dim retval As String = CMD.StandardOutput.ReadToEnd
CMD.WaitForExit()
Return retval
End Function