Check if Mage.exe batch manifest update was successful or not - ClickOnce - vb.net

I have created a console app that creates a batch file in code, that will automatically update and re-sign my app manifest file using mage.exe when a new version gets published.
This batch file then gets executed by the same console app after it has created it.
I want to know if there is a way to determine if the mage.exe batch file failed in updating or signing the manifest?
Any help or ideas will be appreciated.
UPDATE
As per TnTinMn's comment, I forced the batch to fail on updating the manifest. This returned a exit code of 1. How is it then possible for me to extract that exit code to do my error handling? Im doing the following:
Dim procInfo As New ProcessStartInfo()
procInfo.UseShellExecute = True
procInfo.FileName = (sDriveLetter & ":\updatemanifest.bat")
procInfo.WorkingDirectory = ""
procInfo.Verb = "runas"
procInfo.WindowStyle = ProcessWindowStyle.Hidden
Dim sval As Object = Process.Start(procInfo) 'I tested the object to see if there is indeed a value that i can use.
While debugging and looking at the sval object's properties, the exit code is set to 1 but i can't seem to extract it from there.

There are two ways (that I know of) that you can wait for the process to exit before retrieving the Process.ExitCode.
The first as is a blocking call: Process.WaitForExit
and the second is to use the Exit event.
Private Sub RunProcess()
Dim psi As New ProcessStartInfo()
psi.UseShellExecute = True
psi.WindowStyle = ProcessWindowStyle.Hidden
psi.FileName = "cmd.exe"
psi.Arguments = "/c Exit 100"
Dim proc As Process = Process.Start(psi)
proc.EnableRaisingEvents = True
AddHandler proc.Exited, AddressOf ProcessExited
End Sub
Private Sub ProcessExited(sender As Object, e As EventArgs)
Dim proc As Process = DirectCast(sender, Process)
proc.Refresh()
Dim code As Int32 = proc.ExitCode
Me.BeginInvoke(Sub() MessageBox.Show(String.Format("Process has exited with code: {0}", code)), Nothing)
proc.Dispose()
End Sub

Related

I cannot figure out ProcessStartInfo and to be able to use Process.Start.StandardOutput.ReadToEnd to display what is happening in Command line

I am trying to display what is going on in Command Line Interface without opening up command line. I know Process class has that ability but I am having a hard time with StandardOutput.ReadOnly. I have the process set to one button and then after I click, I want it to show a status that command line is in fact connecting. Thoughts?
Private Sub EstablishConnection_Click(sender As Object, e As EventArgs) Handles EstablishConnection.Click
' One file parameter to the executable
Dim sourceName1 As String = strXFileName
Dim sourceName2 As String = strYFileName
' New ProcessStartInfo created
Dim p As New ProcessStartInfo
' Specify the location of the binary
p.FileName = "C:\Software\John\Doe"
' Use these arguments for the process
p.Arguments = $"-Application -Connect -Example -E"" {stXFileName} "" -S"" {strYFileName} """
' Use a hidden window
p.WindowStyle = ProcessWindowStyle.Hidden
p.UseShellExecute = False
p.RedirectStandardOutput = True
p.RedirectStandardError = True
p.RedirectStandardInput = True
' Start the process
Process.Start(p)
'Dim output As String = p.StandardOutputEncoding
'Open the Status Screen form once connection is established
StatusScreen.Show()
Me.Hide()
End Sub

VB.net has process finished running

I have this code which prints files in vb.net:
' Create object, passing in text
Dim psi As New ProcessStartInfo
psi.UseShellExecute = True
psi.Verb = "print"
psi.WindowStyle = ProcessWindowStyle.Hidden
psi.FileName = fi.FullName
Process.Start(psi)
i want to be able to run more code once the printing process has completed, how can i see if it has completed?
I think you most likely want to wait for the process to finish. Try this:
Dim p = Process.Start("calc.exe")
p.WaitForExit()
If you really don't want to wait but just check for completion try this:
If p.HasExited() Then
' do something
End If

How to check when a powershell script is done running with Visual Studio

I am running a powershell script from within my app. I can start it and it completes without problem, but how do I check when its done? I need to do other actions, Only once its complete. Here is what I have, for a bit of reference:
Public Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
If requiredEnd = True And requiredPass = True And requiredPath = True And requiredSheet = True And requiredStart = True And requiredUser = True Then
For I = 0 To 7
objWriter.WriteLine(aryText(I))
Next
objWriter.Close()
Dim p As Process
p.Start("powershell", "-ExecutionPolicy ByPass -windowstyle hidden -file .\\Excel.ps1")
p.WaitForExit()
If p.HasExited = True Then
MsgBox("The Process Has Been Completed!")
Application.Exit()
End If
Else
If requiredEnd = False Or requiredPass = False Or requiredSheet = False Or requiredStart = False Or requiredUser = False Then
MessageBox.Show("You Have Missing Required Fields!")
Else
MessageBox.Show("That Is Not A Valid File!")
End If
End If
End Sub
Thanks for the help! Also, I am a beginner at this, so could you do a bit of an explanation on how it works if it isn't super straight forward? Thanks again.
Edit: I realize I forgot the key point: I can close the script, but I need to know if it exited successfully. So a way to check errors, basically.
Why not use a runspace to execute your powershell code in-process, instead of shelling out to an external application? Most of the code you see for this is in C# but you can of course do it in VB.net as well:
' create Powershell runspace
Dim MyRunSpace As Runspace = RunspaceFactory.CreateRunspace()
' open it
MyRunSpace.Open()
' create a pipeline and feed it the script text
Dim MyPipeline As Pipeline = MyRunSpace.CreatePipeline()
MyPipeline.Commands.AddScript(scriptText)
' add an extra command to transform the script output objects into nicely formatted strings
' remove this line to get the actual objects that the script returns. For example, the script
' "Get-Process" returns a collection of System.Diagnostics.Process instances.
MyPipeline.Commands.Add("Out-String")
' execute the script
Dim results As Collection(Of PSObject) = MyPipeline.Invoke()
' close the runspace
MyRunSpace.Close()
This code is taken from this MSDN blog which has a much more thorough and complete example application, but the basic idea here is to run the code natively in your application and then you can get the output any way you like to test for errors.

How to get Output of a Command Prompt Window line by line in Visual Basic?

I am trying to get a command line output line by line till the end of the output but I am not able to do so. I am using it in my Form and this code executes on click of a button.
Can you tell me whats wrong with my code?
Dim proc As ProcessStartInfo = New ProcessStartInfo("cmd.exe")
Dim pr As Process
proc.CreateNoWindow = True
proc.UseShellExecute = False
proc.RedirectStandardInput = True
proc.RedirectStandardOutput = True
pr = Process.Start(proc)
pr.StandardInput.WriteLine("cd C:\sdk\platform-tools\")
pr.StandardInput.WriteLine("adb help")
Dim helpArray(20) as String
For i as Integer 1 To 7
helpArray(i) = pr.StandardOutput.ReadLine()
Next
pr.StandardOutput.Close()
The program stops responding when this code is executed.
I've done some research. adb help writes output into STDERR. So you need something like:
Dim proc As ProcessStartInfo = New ProcessStartInfo("cmd.exe")
Dim pr As Process
proc.CreateNoWindow = True
proc.UseShellExecute = False
proc.RedirectStandardInput = True
proc.RedirectStandardOutput = True
pr = Process.Start(proc)
pr.StandardInput.WriteLine("C:\sdk\platform-tools")
pr.StandardInput.WriteLine("adb help 2>&1")
pr.StandardInput.Close()
Console.WriteLine(pr.StandardOutput.ReadToEnd())
pr.StandardOutput.Close()
to catch it.
You need no 2>&1 if you call ipconfig, for example.
Do not interate over the output and do not read it! Normally you don't know how long the output (same goes for error output too) would be, so you need to prepare for an unknown length. Since you are telling the Process class, that you want to handle the standard output and the standard error by yourself, you also need to bind to the events, in this case:
OutputDataReceived
ErrorDataReceived
or to block the current process and read the complete output at once like #Dmitry Kurilo does in his answer. I find the first approach better because I do not need to wait for the process to end to see it's output. The MSDN documentation of the ProcessStartInfo.RedirectstandardError property gives a good explanation of the different possibilities with a lot of examples.
If you want to take a specific line, there are a lot of possibilities. One would be to store each output (line) in the delegate and use it later, using a List(Of String) and output the specific line when the process is done (= all output lines are present).
A possible solution could look like this:
' store error output lines
dim lines = new List(of String)
dim executable = "c:\temp\android\sdk\platform-tools\adb.exe"
dim arguments = " help"
dim process = new Process()
process.StartInfo = createStartInfo(executable, arguments)
process.EnableRaisingEvents = true
addhandler process.Exited, Sub (ByVal sender As Object, ByVal e As System.EventArgs)
Console.WriteLine(process.ExitTime)
Console.WriteLine(". Processing done.")
' output line n when output is ready (= all lines are present)
Console.WriteLine(lines(4))
end sub
' catch standard output
addhandler process.OutputDataReceived, Sub (ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs)
if (not String.IsNullOrEmpty(e.Data))
Console.WriteLine(String.Format("{0}> {1}", DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") ,e.Data))
end if
end sub
' catch errors
addhandler process.ErrorDataReceived, Sub (ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs)
'Console.WriteLine(String.Format("! {0}", e.Data))
' add every output line to the list of strings
lines.Add(e.Data)
end sub
' start process
dim result = process.Start()
' and wait for output
process.BeginOutputReadLine()
' and wait for errors :-)
process.BeginErrorReadLine()
private function createStartInfo(byval executable as String, byval arguments as String) as ProcessStartInfo
dim processStartInfo = new ProcessStartInfo(executable, arguments)
processStartInfo.WorkingDirectory = Path.GetDirectoryName(executable)
' we want to read standard output
processStartInfo.RedirectStandardOutput = true
' we want to read the standard error
processStartInfo.RedirectStandardError = true
processStartInfo.UseShellExecute = false
processStartInfo.ErrorDialog = false
processStartInfo.CreateNoWindow = true
return processStartInfo
end function
Now even if the adb writes to the error output, you will be able to see it. It will also be complete.
The output in this case looks like this:
14.10.2014 12:49:10
. Processing done.
-e - directs command to the only running emulator.
Another possibility would be to put everything into one string and after the process has finished split the single string on line endings (CRLF \r\n) and you will gain the lines you want to filter.

Visual Basic (Visual Studio 2005) redirect inputstream to process

I've been searching around the net for roughly three hours now w/o getting forward. I don't know VB very well, but I need to create a wrapper program for any executable that logs the arguments, all input, output and err information:
My wrapper is called: e.g. someApp.exe arg1 arg2
Logs to someApp.log: arg1 arg2
Calls original executable: _someApp.exe arg1 arg2
Must log and forward any console input to _someApp process inputstream
Must log any output and error stream from _someApp process
Okay, I'm stuck at point 4 now:
Dim p As New ProcessStartInfo
p.FileName = execute
p.Arguments = Command()
p.UseShellExecute = False
p.CreateNoWindow = True
p.RedirectStandardInput = True
p.RedirectStandardError = True
p.RedirectStandardOutput = True
Dim process As System.Diagnostics.Process
process = Diagnostics.Process.Start(p)
process.WaitForExit()
After _someApp ends I am able to read out and err stream to log it, but I still need to provide my own wrappers input to the process and I want to read out and err stream as it happens.
Thanks for info/examples
Okay here the solution...
Variables needed:
Private process As System.Diagnostics.Process
Private threadOut As Thread
Private streamOut As System.IO.StreamReader
Private threadErr As Thread
Private streamErr As System.IO.StreamReader
Private threadIn As Thread
Private streamIn As System.IO.StreamWriter
Subs needed:
Private Sub ThreadTaskOut()
Dim line
While Not process.HasExited
line = streamOut.ReadToEnd
If line <> Nothing And line <> "" Then
log("Out: " & line)
Console.Out.Write(line)
End If
End While
End Sub
Private Sub ThreadTaskErr()
Dim line
While Not process.HasExited
line = streamErr.ReadToEnd
If line <> Nothing And line <> "" Then
log("Err: " & line)
Console.Error.Write(line)
End If
End While
End Sub
Private Sub ThreadTaskIn()
Dim line
While Not process.HasExited
line = Console.In.ReadLine
If line <> Nothing And line <> "" Then
log("In: " & line)
streamIn.WriteLine(line)
End If
End While
End Sub
Inside main:
' create process information
Dim p As New ProcessStartInfo
p.FileName = execute
p.Arguments = Command()
p.UseShellExecute = False
p.CreateNoWindow = True
p.RedirectStandardInput = True
p.RedirectStandardError = True
p.RedirectStandardOutput = True
' log process start
log("Execute: " & execute & " " & Command())
' start process
process = Diagnostics.Process.Start(p)
' start thread for output stream
streamOut = process.StandardOutput
threadOut = New Thread(AddressOf ThreadTaskOut)
threadOut.IsBackground = True
threadOut.Start()
' start thread for error stream
streamErr = process.StandardError
threadErr = New Thread(AddressOf ThreadTaskErr)
threadErr.IsBackground = True
threadErr.Start()
' start thread for input stream
streamIn = process.StandardInput
threadIn = New Thread(AddressOf ThreadTaskIn)
threadIn.IsBackground = True
threadIn.Start()
' wait for the process to finish
process.WaitForExit()
log is another sub to log to file, execute is the variable holding the _someApp.exe frommy initial post. I still don't know if the console to inputstream thread dows it right, because my wrapped app had no input as it seems. May someone spotts an error...
For my purposes, hmm it works like I need it
Greetz,
GHad
Code inside main
How about for writing to the app:
Dim sw as IO.StreamWriter = process.StandardInput
sw.WriteLine("Boo")
and for reading from the standard output:
Dim sr As IO.StreamReader = process.StandardOutput
Do
aString = sr.ReadLine()
Loop Until (sr.EndOfStream)