How to use Process.WaitForExit - vb.net

I'm calling a 3rd part app which 'sometimes' works in VB.NET (it's a self-hosted WCF). But sometimes the 3rd party app will hang forever, so I've added a 90-second timer to it. Problem is, how do I know if the thing timed out?
Code looks like this:
Dim MyProcess as System.Diagnostics.Process = System.Diagnostics.Process.Start(MyInfo)
MyProcess.WaitForExit(90000)
What I'd like to do is something like this
If MyProcess.ExceededTimeout Then
MyFunction = False
Else
MyFunction = True
End If
Any ideas?
Thanks,
Jason

There have been known issues in the past where apps would freeze when using WaitForExit.
You need to use
dim Output as String = MyProcess.StandardOutput.ReadToEnd()
before calling
MyProcess.WaitForExit(90000)
Refer to Microsoft's snippet:
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "Write500Lines.exe";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput.aspx

Check the method return value - http://msdn.microsoft.com/en-us/library/ty0d8k56.aspx - if the call timed out, it will return False.

if(process.WaitForExit(timeout)) {
// user exited
} else {
// timeout (perhaps process.Kill();)
}
Async process start and wait for it to finish

Related

Net Framework - WaitForExit not working because I can't determine svchost.exe PID

I need to show the Windows Task Scheduler window and wait until the user closes it before continuing the main program.
I've tried with this method:
public static bool RunCommand (string command)
{
try
{
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Verb = "runas",
Arguments = "/C " + command,
UseShellExecute = false
};
Process process = new();
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
return true;
}
catch (Exception)
{
return false;
throw;
}
}
I've tried passing the following commands as the argument "command" in order to show up the Task Scheduler:
"taskschd.msc"
"start /wait taskschd.msc /s"
"C:\windows\system32\taskschd.msc /s"
"control schedtasks"
The idea is to continue the execution of the main program when the Task Scheduler is closed (its process is killed), but the "process.WaitForExit();" instruction is linked to the cmd command, so the main program continues after cmd process is closed, even when the Task Scheduler window is still being displayed.
The problem is that the "taskschd.msc" process, when launched, is wrapped into an "svchost.exe" process. I can't determine its PID because of the many different svchosts running at the same time, so I can't kill it manually either.
I've tried the solutions proposed here, but to no avail.
I've also been looking for a way to give an alias to the the "scvhost.exe" process launched with this cmd, but it seems that's not possible.
I've been thinking of compiling a new exe just to launch the Task Scheduler under a process name that I could control, but I don't think it is a good solution.
Any ideas, please?
Launching taskschd.msc through mmc.exe works:
ProcessStartInfo psi = new ProcessStartInfo()
{
FileName = "mmc.exe",
Arguments = "taskschd.msc",
Verb = "runas",
UseShellExecute = true,
CreateNoWindow = true
};
var process = Process.Start(psi);
process.WaitForExit();

TCP/IP Client in Kotlin that does not wait forever for server message

I have simple TCP/IP client code in Kotlin below.
This code works.
The client opens the socket and loops forever, first sending a message to the server, and then waiting forever for a response form the server.
I know this code isn’t great, looping forever, keeping the socket connection open etc., but it is just for test purposes right now.
fun tcp_client() {
thread {
val client1 = Socket(SERVER_IP_ADDRESS, SERVER_IP_PORT)
val output1 = PrintWriter(client1.getOutputStream(), true)
val input1 = BufferedReader(InputStreamReader(client1.inputStream))
while (true) {
output1.println(str_user_text)
str_rcvd_data = input1.readLine()
}
}
client1.close()
}
The line:
str_rcvd_data = input1.readLine()
waits forever for a server response.
My question: Is it possible to modify this code so that the client does NOT wait forvever for a server response? Something like this:
If (server data received) {
// process the data
} else {
// do something else for now and check again in a short while
}
Thanks in advance for any suggestions
Garrett
I eventually worked this out - I am not sure how 'correct' this solution is, but it works for me:
Connecting to the server....
My old code would hang if it couldn't connect, because the call to Socket() with the IP address and Port is a Blocking call - i.e.e wait forever:
val client1 = Socket(SERVER_IP_ADDRESS, SERVER_IP_PORT)
So I replaced the code with this:
try {
client1 = Socket()
client1.connect(InetSocketAddress(SERVER_IP_ADDRESS, SERVER_IP_PORT), 3000)
output1 = DataOutputStream (client1.getOutputStream())
input1 = DataInputStream (client1.getInputStream())
} catch (ex : Exception) {
// do something
} finally {
// do something
}
This isn't perfect, but it works.
For reading the data, my old code called readline() which is blocking:
str_rcvd_data = input1.readLine()
Now, my code first checks if there is any data and then grabs each byte
iRxDataAvailable = input1.available()
while (iRxDataAvailable > 0)
{
iRxDataAvailable--
// Take a copy of the received byte
byRcvdByte = input1.readByte()
// Do something with this data byte...
}
Finally, to send data to the server, the data is placed in a byte array, and then:
output1.write(byArray)

Process with redirected standard input/output behaves differently depending on size of input

I have an odd behavior about running processes from F#. My basic problem was to run Graphviz's dot.exe with a generated graph, and visualize it.
When I restricted the graph to be small, everything worked fine. But with bigger graphs, it hanged on a specific line. I'm curious why is it happening, so maybe I can fix my issue. Tho I created an MVCE for the purpose.
I have 2 console programs. One is the simulator of dot.exe, where I would showel the input, and expect .jpg from. This version just streams 10 times the input to the output in blocks:
// Learn more about F# at http://fsharp.org
// See the 'F# Tutorial' project for more help.
open System
open System.IO
[<EntryPoint>]
let main argv =
let bufferSize = 4096
let mutable buffer : char [] = Array.zeroCreate bufferSize
// it repeats in 4096 blocks, but it doesn't matter. It's a simulation of outputing 10 times amount output.
while Console.In.ReadBlock(buffer, 0, bufferSize) <> 0 do
for i in 1 .. 10 do
Console.Out.WriteLine(buffer)
0 // return an integer exit code
So I have an .exe named C:\Users\MyUserName\Documents\Visual Studio 2015\Projects\ProcessInputOutputMVCE\EchoExe\bin\Debug\EchoExe.exe Than comes another console project, which uses it:
// Learn more about F# at http://fsharp.org
// See the 'F# Tutorial' project for more help.
open System.IO
[<EntryPoint>]
let main argv =
let si =
new System.Diagnostics.ProcessStartInfo(#"C:\Users\MyUserName\Documents\Visual Studio 2015\Projects\ProcessInputOutputMVCE\EchoExe\bin\Debug\EchoExe.exe", "",
// from Fake's Process handling
#if FX_WINDOWSTLE
WindowStyle = ProcessWindowStyle.Hidden,
#else
CreateNoWindow = true,
#endif
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true)
use p = new System.Diagnostics.Process()
p.StartInfo <- si
if p.Start() then
let input =
Seq.replicate 3000 "aaaa"
|> String.concat "\n"
p.StandardInput.Write input
// hangs on Flush()
p.StandardInput.Flush()
p.StandardInput.Close()
use outTxt = File.Create "out.txt"
p.StandardOutput.BaseStream.CopyTo outTxt
// double WaitForExit because of https://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput(v=vs.110).aspx
// saying first WaitForExit() waits for StandardOutput. Next is needed for the whole process.
p.WaitForExit()
p.WaitForExit()
0 // return an integer exit code
Which hangs on p.StandardInput.Flush(). Except if I change the volume of input to Seq.replicate 300 "aaaa". Why is it working differently?
Process.StandardOutput's reference states that reading from StandardOutput and child process writing to that stream in the same time might cause deadlock. Who is a child process in that case? Is it my p.StandardInput.Write input?
Other possible deadlock would be
read all text from both the standard output and standard error streams.
But I'm not reading the error stream. Anyway it suggests to handle the input/output with async so I have a following version:
// same as before
...
if p.Start() then
let rec writeIndefinitely (rows: string list) =
async {
if rows.Length = 0 then
()
else
do! Async.AwaitTask (p.StandardInput.WriteLineAsync rows.Head)
p.StandardInput.Flush()
do! writeIndefinitely rows.Tail
}
let inputTaskContinuation =
Seq.replicate 3000 "aaaa"
|> Seq.toList
|> writeIndefinitely
Async.Start (async {
do! inputTaskContinuation
p.StandardInput.Close()
}
)
let bufferSize = 4096
let mutable buffer : char array = Array.zeroCreate bufferSize
use outTxt = File.CreateText "out.txt"
let rec readIndefinitely() =
async {
let! readBytes = Async.AwaitTask (p.StandardOutput.ReadAsync (buffer, 0, bufferSize))
if readBytes <> 0 then
outTxt.Write (buffer, 0, buffer.Length)
outTxt.Flush()
do! readIndefinitely()
}
Async.Start (async {
do! readIndefinitely()
p.StandardOutput.Close()
})
// with that it throws "Cannot mix synchronous and asynchronous operation on process stream." on let! readBytes = Async.AwaitTask (p.StandardOutput.ReadAsync (buffer, 0, bufferSize))
//p.BeginOutputReadLine()
p.WaitForExit()
// using dot.exe, it hangs on the second WaitForExit()
p.WaitForExit()
Which doesn't hang, and writes out.txt. Except in the real code using dot.exe. It's as async as it gets. Why does it throw exception for p.BeginOutputReadLine()?
After some experimenting, the whole async out can stay p.StandardOutput.BaseStream.CopyTo outTxt where outTxt is File.Create not File.CreateText. Only the async input behaves correct against the synchronous input handling. Which is weird.
To sum it up. If I have asynchronous input handling, it works fine (except dot.exe, but if I figure it out, maybe I can fix that too), if it have synchronous input handling, it's depending on the size of the input. (300 works, 3000 doesn't) Why is that?
Update
Since I really not needed to redirect the standard error, I have removed RedirectStandardError = true. That solved the mysterious dot.exe problem.
I think that the deadlock here is following:
Host process writes too much data to the input buffer.
Child process reads from the buffer and writes to output.
Host process does not read from the buffer (it happens after sending all the data). When the output buffer of the child process is filled up, it blocks on writing and stops reading from the input. Two processes are now in the deadlock state.
It is not necessary to use completely asynchronous code. What I think would work is writing in chunks to dot's stdin and reading to the end of the dot's stdout before writing again.

UWP (VB.Net) StreamSocketListener not firing connected event

I'm trying to setup a socket listener in a Universal Windows Platform App. The app will run on a Raspberry PI and listen for communications from an in-motion scale.
I've setup a StreamSocketListener in my mainVM file. I've got commands to start and stop it. I've followed the few guides online i can find, but it won't fire the event when the scale sends the data. I've tested with a listener app that I downloaded, so i can confirm that the messages are being sent and my computer is able to receive them (no firewall issues). (I also know that only one app can listen to a port, so this tester is off when testing my program.)
I'll get one hit on the handler function when it first starts the connection, but i never get anything again. No errors, just nothing happening.
Commands:
Public Property cmdStart As New Command(Async Sub() Await StartListener(), True)
Public Property cmdStop As New Command(Sub() StopListener(), True)
Command Subroutines:
Private Async Function StopListener() As Task
If Connected Then
Await _prePriceListener.CancelIOAsync()
RemoveHandler _prePriceListener.ConnectionReceived, Nothing
_prePriceListener.Dispose()
Connected = False
End If
End Function
Private Async Function StartListener() As Task
If ValidateInput() Then
Try
_prePriceListener = New StreamSocketListener()
_prePriceListener.Control.KeepAlive = False
AddHandler _prePriceListener.ConnectionReceived, AddressOf HandlerReceived
Await _prePriceListener.BindServiceNameAsync("6021")
Connected = True
Catch ex As Exception
Message = ex.Message
End Try
End If
End Function
Event Handler:
Private Async Function HandlerReceived(sender As StreamSocketListener, args As StreamSocketListenerConnectionReceivedEventArgs) As Task
Dim msgReceived As String = ""
Dim inStream As Stream
Dim reader As StreamReader
Try
inStream = args.Socket.InputStream.AsStreamForRead()
reader = New StreamReader(inStream)
Catch ex As Exception
Return
End Try
Try
If reader IsNot Nothing Then
msgReceived = Await reader.ReadLineAsync()
HandlePrepriceRead(msgReceived)
End If
Catch ex As Exception
Return
End Try
End Function
I've tried with _prePriceListener.Control.KeepAlive set to both true and false. When true, it hangs on msgReceived = Await reader.ReadLineAsync() in the handler. I suspect that is the issue, but every fix i've found made no difference. My only other suspicion is incorrect use of Async/Await but i can't find much information to either confirm or deny that. (I think i know what i'm doing with that, but i may be at that level of knowing just enough to be dangerous...)
Anyway, any input would be greatly appreciated. Thanks.
Are you sure that the scale is sending an EOL (\n or \r or \r\n) HEX 13 and or 10 ? I could see your code waiting for an something the scale is never sending. *FYI I'm not sure what kind of scale you are using or how quickly it talks or your application but if the scale is on continuous feed this probably isn't going to work very well for you as the scale and all the parts along the way will buffer things and the weight will be gone by the time you process this event (after a while atleast)

How to make batch processing with Apex?

How can I create batch processing application with Apache Apex?
All the examples I've found were streaming applications, which means they are not ending and I would like my app to close once it has processed all the data.
Thanks
What is your use-case? Supporting batch natively is on the roadmap and is being worked on right now.
Alternately, till then, once you are sure that your processing is done, the input operator can send a signal as ShutdownException() and that will propogate through the DAG and shutdown the DAG.
Let us know if you need further details.
You can add an exit condition before running the app.
for example
public void testMapOperator() throws Exception
{
LocalMode lma = LocalMode.newInstance();
DAG dag = lma.getDAG();
NumberGenerator numGen = dag.addOperator("numGen", new NumberGenerator());
FunctionOperator.MapFunctionOperator<Integer, Integer> mapper
= dag.addOperator("mapper", new FunctionOperator.MapFunctionOperator<Integer, Integer>(new Square()));
ResultCollector collector = dag.addOperator("collector", new ResultCollector());
dag.addStream("raw numbers", numGen.output, mapper.input);
dag.addStream("mapped results", mapper.output, collector.input);
// Create local cluster
LocalMode.Controller lc = lma.getController();
lc.setHeartbeatMonitoringEnabled(false);
//Condition to exit the application
((StramLocalCluster)lc).setExitCondition(new Callable<Boolean>()
{
#Override
public Boolean call() throws Exception
{
return TupleCount == NumTuples;
}
});
lc.run();
Assert.assertEquals(sum, 285);
}
for the complete code refer https://github.com/apache/apex-malhar/blob/master/stream/src/test/java/org/apache/apex/malhar/stream/FunctionOperator/FunctionOperatorTest.java