Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    4

    [VB .net] Intercettare messaggi da programma esterno

    Ciao raga,
    mi sono appena iscritto in quanto nuovo utente di visual basic.... dopo vent'anni di programmazione in C.
    Stavo scrivendo un'applicazione che richiama un eseguibile esterno. Questo eseguibile, durante il funzionamento, scrive di tanto in tanto dei messaggi su standard output.
    Avrei necessita` di intercettare questi messaggi (prima che termini il programma) e scriverli in una apposita TextBox (in modo da far vedere all'utente l'avanzamento del programma).
    Il problema e` che non riesco in nessun modo ad intercettare questi messaggi quando vengono emessi ma solo alla fine e tutti insieme.

    Il pezzo di codice che si occupa di questo e` il seguente:

    codice:
    prg.StartInfo.UseShellExecute = False
    prg.StartInfo.FileName = <nome prog>
    prg.StartInfo.Arguments = <args>
    prg.StartInfo.RedirectStandardOutput = True
    prg.StartInfo.CreateNoWindow = True
    prg.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
    prg.Start()
    ....
    prg.WaitForExit()
    In sostanza mi manca tutto il pezzo di codice che sta tra Start() e WaitForExit().

    Come posso fare?

    Grazissime....

  2. #2

  3. #3
    Utente di HTML.it L'avatar di Vinsent
    Registrato dal
    May 2011
    Messaggi
    314
    Uso anch'io il codice indicato da ESSE-EFFE, se vuoi approfondire sulla "lettura asincrona" dell' output (credo sia quello che chiedi) puoi approfondire qui:
    http://msdn.microsoft.com/it-it/libr...ardoutput.aspx
    http://msdn.microsoft.com/it-it/libr...treadline.aspx

  4. #4
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    4
    La ReadToEnd l'ho gia` usata diverse volte ma non fa al caso mio: butta tutto l'output dentro una stringa in un colpo solo. E` utile per eseguire operazioni sull'output alla fine del processo ma a me serve visualizzare l'output riga per riga a mano a mano che viene generato.
    Penso anch'io che si tratti della lettura asincrona ma dagli esempi sul sito msdn (che avevo gia` letto) ottengo sempre una lettura sincrona. Boh....

  5. #5
    Utente di HTML.it L'avatar di Vinsent
    Registrato dal
    May 2011
    Messaggi
    314
    Ho preso l' occasione per imparare qualcosa di nuovo...tempo fa avevo dato un' occhiata ai link che ho postato ma visto che non mi serviva non ci avevo neanche provato...
    Ho "rimaneggiato" a modo mio.....l' esempio su msdn e il risultato è quello voluto:
    codice:
        Dim WithEvents pr As New Process()
    
        Private Sub Button1_Click() Handles Button1.Click
            Dim args As New ProcessStartInfo("cmd.exe")
            With args
                .Arguments = "/c ping -n 10 www.google.it"
                .RedirectStandardOutput = True
                .UseShellExecute = False
                .CreateNoWindow = True
            End With
            pr = Process.Start(args)
            pr.BeginOutputReadLine()
            pr.WaitForExit()
        End Sub
    
        Private Sub pr_outline(sendingProcess As Object, _
               outLine As DataReceivedEventArgs) Handles pr.OutputDataReceived
            If Not String.IsNullOrEmpty(outLine.Data) Then
                Console.WriteLine(outLine.Data)
            End If
        End Sub
    Sicuramente si può fare di meglio, ad esempio ho dichiarato 'Dim WithEvents pr As New Process()' perchè l' 'AddHandler' non rispondeva e non c' ho perso su del tempo.
    Vedi tu se l' esempio può aiutarti.

  6. #6
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    4
    Ecco.... e` piu` o meno quello che mi serviva... cosi` funziona anche usando l'AddHandler (che in effetti e` piu` elegante). Mi ero anche accorto che l'eseguibile esterno che lancio era un vecchio programma in C che stampava a video con una banale printf. Ho dovuto ricompilarlo cambiando tutte le printf con fprintf(stdout) e subito dopo un fflush. Cosi` facendo il tuo esempio funziona perfettamente. THANKS!!!

    Ancora una cosa: sempre nel tuo esempio hai usato nella sub pr_outline il Console.WritLine per scrivere i messaggi. Nel mio caso, la console e` "spenta" e dovrei scrivere il messaggio in una apposita text box. Ma se richiamo il comando per scrivere li dentro (<nome>.AppendText) mi esce il messaggio "....accessed from a thread other than the thread it was created on" In sostanza mi dice che non posso scrivere nella text box da un thread che non sia il principale. Esiste una scappatoia?
    Grazie ancora.....

  7. #7
    Utente di HTML.it L'avatar di Vinsent
    Registrato dal
    May 2011
    Messaggi
    314
    Con l' occasione ho rispolverato un mio vecchio progetto a scopo didattico...un' interfaccia a cmd...mi sono accorto del problema appena ho modificato il codice, inoltre mentre il processo lavora non si può interagire con il Form e se quest' ultimo si chiude il processo rimane attivo a causa di 'pr.WaitForExit()'.
    Nel codice sotto eseguo il processo in un nuovo Thread in modo da non "bloccare" il form e leggendo qui:
    http://msdn.microsoft.com/it-it/libr...(v=vs.90).aspx
    ho aggiunto il codice per ottenere il risultato voluto, funziona ma mi sembra un' accrocchio...stò usato Delegate e Invoke senza capirne appieno il reale utilizzo (stile codemonkey ), manca lo "stop" del processo/Thread e non riesco a capire perchè
    codice:
    AddHandler pr.OutputDataReceived, AddressOf pr_outline
    non funge....

    codice:
    Imports System.Threading
    
    Public Class Form1
    
        Dim WithEvents pr As New Process()
        Dim pr_Thread As Thread = Nothing
        Delegate Sub pr_tbox_deleg(ByVal riga As String)
    
        Private Sub Button1_Click() Handles Button1.Click
            pr_Thread = New Thread(New ThreadStart(AddressOf pr_ping))
            pr_Thread.Start()
        End Sub
    
        Private Sub pr_ping()
            Dim args As New ProcessStartInfo("cmd.exe")
            With args
                .Arguments = "/c ping -n 10 www.google.it"
                .RedirectStandardOutput = True
                .UseShellExecute = False
                .CreateNoWindow = True
            End With
            pr = Process.Start(args)
            pr.BeginOutputReadLine()
        End Sub
    
        Private Sub pr_outline(sendingProcess As Object, outLine As DataReceivedEventArgs) Handles pr.OutputDataReceived
            If Not String.IsNullOrEmpty(outLine.Data) Then
                tbox_appendtext(outLine.Data)
            End If
        End Sub
    
        Private Sub tbox_appendtext(ByVal riga As String)
            If TextBox1.InvokeRequired Then
                Dim a As New pr_tbox_deleg(AddressOf tbox_appendtext)
                Invoke(a, New Object() {riga})
            Else
                TextBox1.AppendText(riga & vbCrLf)
            End If
        End Sub
    
    End Class

  8. #8
    Utente di HTML.it
    Registrato dal
    Mar 2012
    Messaggi
    4
    I delegate non li ho ancora imparati. Avevo provato ad usare questo sistema ma non ero riuscito comunque a far funzionare come volevo il mio programma.
    Sai come l'ho risolto alla fine? Sempre grazie a msdn.... ho scoperto questo comando:
    codice:
    Control.CheckForIllegalCrossThreadCalls = False
    ...inibisce il controllo sui thread e mi permette di scrivere il messaggio nella mia finestra.
    Dicono che non e` bello usarlo perche` potrebbe comportare dei problemi ma nel mio caso lo uso in una parte di codice molto semplice per cui non dovrei avere alcuna controindicazione.
    In sostanza:
    codice:
    Sub.....
     Control.CheckForIllegalCrossThreadCalls = False
     prg.StartInfo.FileName = <nome prog>
     prg.StartInfo.Arguments = <args>
     prg.StartInfo.CreateNoWindow = True
     prg.StartInfo.UseShellExecute = False
     prg.StartInfo.RedirectStandardOutput = True
     prg.StartInfo.WindowStyle = ProcessWindowStyle.Normal
     AddHandler prg.OutputDataReceived, AddressOf prg_OutputDataReceived
     prg.Start()
     prg.BeginOutputReadLine()
     prg.WaitForExit()
    End Sub
    
    Private Sub prg_OutputDataReceived(ByVal sender As System.Object, ByVal e As System.Diagnostics.DataReceivedEventArgs)
     gr_msg.AppendText(e.Data & NewLine)
    End Sub
    Funge alla grande!!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.