Search code examples
vb.netasynchronouspsexec

Console Application output is not shown


I have read several questions in StackOverflow about redirecting output/errors from application but It could not help me.

I have developed an executable in C# code. It recovers software from system registry and call a webservice to save it to our database.

Inside the executable we are printing messages with

Console.WriteLine("Message from Executable");

On the other hand we have a CRM application and I have written two win forms that call psexec.exe with the desired parameters and this .exe is remotely copied and launched on target machine.

If you use direct psexec call with that parameters in cmd.exe, we can see the psexec execution banners and OUR executable output

Something like:

PsExec v1.98 - Execute processes remotely

Copyright (C) 2001-2010

Mark Russinovich Sysinternals - www.sysinternals.com

Enterprise software @ 2012

Message from application

Starting task in machine "XXXXXXX"

Recovering software list from registry

Program.exe exited on MACHINE with error code 0.

When I make the psexec call with .NET, I cant recover my application output, It just shows:

PsExec v1.98 - Execute processes remotely

Copyright (C) 2001-2010

Mark Russinovich Sysinternals - www.sysinternals.com

Program.exe exited on MACHINE with error code 0.

I am assigning to Process class a delegate who is recovering async data from process, but this information, is not there.

I paste some code to see If you can find the reason my C# Console application output does not appear:

The command I launch is:

Dim CmdExe As String = "\\#MAQUINA# -u #USUARIO# -p #CLAVE# -s -c -f """ + executionPath + """"

Parametes -s (Run as system) -c (Copy local file to remote system) -f (force overwrite)

Private Sub LanzarProceso()
        CheckForIllegalCrossThreadCalls = False
        Dim Proceso As New Process
        AddHandler Proceso.OutputDataReceived, AddressOf CallbackProcesoAsync
        AddHandler Proceso.ErrorDataReceived, AddressOf ErrorDataReceivedAsync

        Dim startInfo As New ProcessStartInfo
        startInfo.FileName = execFile
        startInfo.Arguments = CmdExe.Replace("#MAQUINA#", txtFiltroMaquina.Text).Replace _
                                            ("#USUARIO#", txtUsuario.Text.Trim).Replace _
                                            ("#CLAVE#", txtClave.Text.Trim)
        Proceso.EnableRaisingEvents = True
        startInfo.UseShellExecute = False
        startInfo.RedirectStandardOutput = True
        startInfo.RedirectStandardError = True
        startInfo.CreateNoWindow = False
        Proceso.StartInfo = startInfo
        Proceso.Start()
        Proceso.BeginOutputReadLine()
        Proceso.BeginErrorReadLine()
        Proceso.WaitForExit()


    End Sub

Delegates handling data:

 Private Sub CallbackProcesoAsync(sender As Object, args As System.Diagnostics.DataReceivedEventArgs)

        If Not args.Data Is Nothing AndAlso Not String.IsNullOrEmpty(args.Data) Then
            If Not listtask.InvokeRequired Then
                listtask.Items.Add(args.Data.ToString)
            Else
                Dim d As New TextToControl(AddressOf AddToControl)
                listtask.Invoke(d, args.Data.ToString)
            End If

        End If

    End Sub

    Private Sub ErrorDataReceivedAsync(sender As Object, args As System.Diagnostics.DataReceivedEventArgs)
        If Not args.Data Is Nothing AndAlso Not String.IsNullOrEmpty(args.Data) Then
            If Not listtask.InvokeRequired Then
                listtask.Items.Add(args.Data.ToString)
            Else
                Dim d As New TextToControl(AddressOf AddToControl)
                listtask.Invoke(d, args.Data.ToString)
            End If

        End If
    End Sub

I checked the program is finishing correctly. THe c# executable has

Enviroment.Exit(0);

at the end of the execution


Solution

  • Ok, the best workaround I found to get all the output between psexec and my c# application after execution is:

    Dim CmdExe As String ="\#MAQUINA# -u #USUARIO# -p #CLAVE# -s -c -f """ + executionPath + """ > outputFileCode.txt"

    This allow me to parse the standard output without having to change anything or calling my program directly, because I can`t do it.