vb.net中进程的实时输出

时间:2015-01-19 21:00:41

标签: vb.net process

我有以下类用于磁盘分区和成像电脑。表单有一个常规文本框(tb1),它列出了进程的每一步(输出)和一个输出实时进程信息的富文本框(rtb1)。我遇到的问题是app在开始下一个子例程之前没有等待实时输出完成。见附件:

Imports System
Imports System.IO
Imports System.Management
Imports System.Text.RegularExpressions

Public Class Form1

Private Property pcSerial As Object = GetBiosSerialNumber()
Private Property title As String = "Ross PC Imaging"
Private Property pcModel As Object
Private Property wkstn As String
Private Property srvr As Object

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    'Call ross()
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Call ross()
End Sub

Private Sub ross()
    Dim objCS As ManagementObjectSearcher
    Dim objMgmt As ManagementObject
    objCS = New ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem")

    For Each objMgmt In objCS.Get
        pcModel = objMgmt("model").ToString()
    Next

    Output(pcModel)
    Output(pcSerial)

    'Map network drive
    Call MapDrive()

    'Diskpart
    Output("[ " & Now & " ] PC - " & pcSerial & " physical drives being partitioned and formatted")
    If pcModel = "Server" Then
        Call diskpart("srvr")
    Else
        Call diskpart("wkstn")
    End If
    Output("[ " & Now & " ] PC - " & pcSerial & " physical drives have been partitioned and formatted")
    Dim msgDiskPart As String : msgDiskPart = ("[ " & Now & " ] PC - " & pcSerial & " physical drives partitioned and formatted")
    Call WriteToLog(title, msgDiskPart)

    'Dism
    Output("[ " & Now & " ] PC - " & pcSerial & " imaging started")
    If pcModel = "Server" Then
        Call dism("srvr")
    Else
        Call dism("wkstn")
    End If
    Output("[ " & Now & " ] PC - " & pcSerial & " imaging completed")
    Dim msgImgStop As String : msgImgStop = ("[ " & Now & " ] PC - " & pcSerial & " imaged")
    Call WriteToLog(title, msgImgStop)

    'Reboot
    'Call reboot()
End Sub

Private Sub MapDrive()
    'Map network drive
    Dim map As New Process()
    map.StartInfo.FileName = "net.exe"
    map.StartInfo.Arguments = " use t: \\172.47.3.254\wims"
    map.StartInfo.CreateNoWindow = True
    map.StartInfo.UseShellExecute = False
    map.StartInfo.RedirectStandardOutput = True
    map.Start()
    map.WaitForExit()
End Sub

Private Sub diskpart(ByVal pctype As String)
    'Diskpart disk partitioning
    Dim dp As New Process()
    dp.StartInfo.FileName = "diskpart.exe"
    dp.StartInfo.Arguments = " /s x:\" & pctype & "_diskpart.txt"
    dp.StartInfo.CreateNoWindow = True
    dp.StartInfo.UseShellExecute = False
    dp.StartInfo.RedirectStandardOutput = True
    dp.StartInfo.RedirectStandardError = True
    dp.EnableRaisingEvents = True
    Application.DoEvents()
    AddHandler dp.ErrorDataReceived, AddressOf proc_OutputDataReceived
    AddHandler dp.OutputDataReceived, AddressOf proc_OutputDataReceived
    dp.Start()
    dp.BeginErrorReadLine()
    dp.BeginOutputReadLine()
End Sub

Private Sub dism(ByVal imgFile As String)
    'Image C Drive
    Dim dismC As New Process
    dismC.StartInfo.FileName = "dism.exe"
    dismC.StartInfo.Arguments = " /Apply-Image /ImageFile:t:\" & imgFile & ".wim /index:1 /ApplyDir:c:\"
    dismC.StartInfo.CreateNoWindow = True
    dismC.StartInfo.UseShellExecute = False
    dismC.StartInfo.RedirectStandardOutput = True
    dismC.StartInfo.RedirectStandardError = True
    dismC.EnableRaisingEvents = True
    Application.DoEvents()
    AddHandler dismC.ErrorDataReceived, AddressOf proc_OutputDataReceived
    AddHandler dismC.OutputDataReceived, AddressOf proc_OutputDataReceived
    dismC.Start()
    dismC.BeginErrorReadLine()
    dismC.BeginOutputReadLine()
    dismC.Close()

    'Image D Drive
    Dim dismD As New Process
    dismD.StartInfo.FileName = "dism.exe"
    dismD.StartInfo.Arguments = " /Apply-Image /ImageFile:t:\" & imgFile & ".wim /index:2 /ApplyDir:d:\"
    dismD.StartInfo.CreateNoWindow = True
    dismD.StartInfo.UseShellExecute = False
    dismD.StartInfo.RedirectStandardOutput = True
    dismD.StartInfo.RedirectStandardError = True
    dismD.EnableRaisingEvents = True
    Application.DoEvents()
    AddHandler dismD.ErrorDataReceived, AddressOf proc_OutputDataReceived
    AddHandler dismD.OutputDataReceived, AddressOf proc_OutputDataReceived
    dismD.Start()
    dismD.BeginErrorReadLine()
    dismD.BeginOutputReadLine()
    dismD.Close()
End Sub

Private Sub reboot()
    'Reboots a pc while in WinPE
    Dim reset As New Process
    reset.StartInfo.FileName = "wpeutils.exe"
    reset.StartInfo.Arguments = " reboot"
    reset.Start()
End Sub

Private Sub WriteToLog(ByVal title As String, ByVal msg As String)
    'Check and make directory
    If Not System.IO.Directory.Exists("t:\logs\") Then
        System.IO.Directory.CreateDirectory("t:\logs\")
    End If

    'Check and make file
    Dim fs As FileStream = New FileStream("t:\logs\" & pcSerial & ".log", FileMode.OpenOrCreate, FileAccess.ReadWrite)
    Dim s As StreamWriter = New StreamWriter(fs)
    s.Close()
    fs.Close()

    'Logging
    Dim fs1 As FileStream = New FileStream("t:\logs\" & pcSerial & ".log", FileMode.Append, FileAccess.Write)
    Dim s1 As StreamWriter = New StreamWriter(fs1)
    s1.Write("Title: " & title & vbCrLf)
    s1.Write("Message: " & msg & vbCrLf)
    s1.Write("================================================" & vbCrLf)
    s1.Close()
    fs1.Close()
End Sub

Private Sub Output(s As String)
    'Output to form window
    If s <> "" Then
        tb1.AppendText(vbCrLf & ">> " & s)
    End If
End Sub

Public ReadOnly Property Model()
    Get
        Model = pcModel
    End Get
End Property

Public Function GetBiosSerialNumber() As String
    Dim OutputString As String = String.Empty
    Using Process As New Process
        AddHandler Process.OutputDataReceived,
    Sub(sender As Object, e As DataReceivedEventArgs)
        OutputString = OutputString & e.Data & vbCrLf
    End Sub
        With Process.StartInfo
            .FileName = "cmd"
            .UseShellExecute = False
            .CreateNoWindow = True
            .RedirectStandardInput = True
            .RedirectStandardOutput = True
            .RedirectStandardError = True
        End With
        With Process
            .Start()
            .BeginOutputReadLine()
        End With
        Using InputStream As System.IO.StreamWriter = Process.StandardInput
            With InputStream
                .AutoFlush = True
                .Write("wmic bios get serialnumber" & vbCrLf)
            End With
        End Using
        Do
            Application.DoEvents()
        Loop Until Process.HasExited
    End Using
    Return Replace(OutputString.Split(CChar(vbCrLf)).ToList(6).Substring(1), " ", "")
End Function

Delegate Sub UpdateTextBoxDelg(text As String)
Public myDelegate As UpdateTextBoxDelg = New UpdateTextBoxDelg(AddressOf UpdateTextBox)
Public Sub UpdateTextBox(text As String)
    rtb1.Text += text & Environment.NewLine
    rtb1.SelectionStart = rtb1.Text.Length
    rtb1.ScrollToCaret()
End Sub

Public Sub proc_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
    If Me.InvokeRequired = True Then
        Me.Invoke(myDelegate, e.Data)
    Else
        UpdateTextBox(e.Data)
    End If
End Sub

结束班

我感谢任何建议。

1 个答案:

答案 0 :(得分:0)

Imports System
Imports System.IO
Imports System.Management
Imports System.Text.RegularExpressions

Public Class Form1

Delegate Sub UpdateTextBoxDelg(text As String)
Public myDelegate As UpdateTextBoxDelg = New UpdateTextBoxDelg(AddressOf UpdateTextBox)

Private Property pcSerial As Object = GetBiosSerialNumber()
Private Property title As String = "Ross PC Imaging"
Private Property pcModel As Object
Private Property wkstn As String
Private Property srvr As Object
Private Property pctype As String

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Call ross()
End Sub

Private Sub ross()
    Dim objCS As ManagementObjectSearcher
    Dim objMgmt As ManagementObject
    objCS = New ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem")

    For Each objMgmt In objCS.Get
        pcModel = objMgmt("model").ToString()
    Next

    Output(pcModel)
    Output(pcSerial)

    'Map network drive
    DriveMap.RunWorkerAsync()
End Sub

Private Sub DriveMap_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) Handles DriveMap.DoWork
    'Map network drive
    Dim map As New Process()
    map.StartInfo.FileName = "net.exe"
    map.StartInfo.Arguments = " use t: \\172.47.3.254\wims"
    map.StartInfo.CreateNoWindow = True
    map.StartInfo.UseShellExecute = False
    map.StartInfo.RedirectStandardOutput = True
    map.Start()
    map.WaitForExit()
End Sub

Private Sub DriveMap_RunWorkerCompleted(sender As Object, e As ComponentModel.RunWorkerCompletedEventArgs) Handles DriveMap.RunWorkerCompleted
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - partitioning and formatting drives")
    Dim msgDiskPart As String : msgDiskPart = ("[ " & Now & " ] PC - *" & pcSerial & "* - partitioning and formatting drives")
    Call WriteToLog(title, msgDiskPart)

    DiskPart.RunWorkerAsync()
End Sub

Private Sub DiskPart_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) Handles DiskPart.DoWork
    If pcModel = "Server" Then
        pctype = "srvr"
    Else
        pctype = "wkstn"
    End If

    'Diskpart disk partitioning
    Dim dp As New Process()
    dp.StartInfo.FileName = "diskpart.exe"
    dp.StartInfo.Arguments = " /s x:\" & pctype & "_diskpart.txt"
    dp.StartInfo.CreateNoWindow = True
    dp.StartInfo.UseShellExecute = False
    dp.StartInfo.RedirectStandardOutput = True
    dp.StartInfo.RedirectStandardError = True
    dp.EnableRaisingEvents = True
    Application.DoEvents()
    AddHandler dp.ErrorDataReceived, AddressOf proc_OutputDataReceived
    AddHandler dp.OutputDataReceived, AddressOf proc_OutputDataReceived
    dp.Start()
    dp.BeginErrorReadLine()
    dp.BeginOutputReadLine()
    dp.WaitForExit()
End Sub

Private Sub DiskPart_RunWorkerCompleted(sender As Object, e As ComponentModel.RunWorkerCompletedEventArgs) Handles DiskPart.RunWorkerCompleted
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - drives have been partitioned and formatted")
    Dim msgDiskPart As String : msgDiskPart = ("[ " & Now & " ] PC - *" & pcSerial & "* - drives have been partitioned and formatted")
    Call WriteToLog(title, msgDiskPart)
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - running disk check on drive C")
    Dim msgChkDskC As String : msgChkDskC = ("[ " & Now & " ] PC - *" & pcSerial & "* - running disk check on drive C")
    Call WriteToLog(title, msgChkDskC)

    ChkDskC.RunWorkerAsync()
End Sub

Private Sub ChkDskC_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) Handles ChkDskC.DoWork
    Dim dc As New Process
    dc.StartInfo.FileName = "chkdsk.exe"
    dc.StartInfo.Arguments = " c: /f"
    dc.StartInfo.CreateNoWindow = True
    dc.StartInfo.UseShellExecute = False
    dc.StartInfo.RedirectStandardOutput = True
    dc.StartInfo.RedirectStandardError = True
    dc.EnableRaisingEvents = True
    Application.DoEvents()
    AddHandler dc.ErrorDataReceived, AddressOf proc_OutputDataReceived
    AddHandler dc.OutputDataReceived, AddressOf proc_OutputDataReceived
    dc.Start()
    dc.BeginErrorReadLine()
    dc.BeginOutputReadLine()
    dc.WaitForExit()
End Sub

Private Sub ChkDskC_RunWorkerCompleted(sender As Object, e As ComponentModel.RunWorkerCompletedEventArgs) Handles ChkDskC.RunWorkerCompleted
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - drive C had no errors")
    Dim msgChkDskC As String : msgChkDskC = ("[ " & Now & " ] PC - *" & pcSerial & "* - drive C had no errors")
    Call WriteToLog(title, msgChkDskC)
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - running disk check on drive D")
    Dim msgChkDskD As String : msgChkDskD = ("[ " & Now & " ] PC - *" & pcSerial & "* - running disk check on drive D")
    Call WriteToLog(title, msgChkDskD)

    ChkDskD.RunWorkerAsync()
End Sub

Private Sub ChkDskD_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) Handles ChkDskD.DoWork
    Dim dc As New Process
    dc.StartInfo.FileName = "chkdsk.exe"
    dc.StartInfo.Arguments = " d: /f"
    dc.StartInfo.CreateNoWindow = True
    dc.StartInfo.UseShellExecute = False
    dc.StartInfo.RedirectStandardOutput = True
    dc.StartInfo.RedirectStandardError = True
    dc.EnableRaisingEvents = True
    Application.DoEvents()
    AddHandler dc.ErrorDataReceived, AddressOf proc_OutputDataReceived
    AddHandler dc.OutputDataReceived, AddressOf proc_OutputDataReceived
    dc.Start()
    dc.BeginErrorReadLine()
    dc.BeginOutputReadLine()
    dc.WaitForExit()
End Sub

Private Sub ChkDskD_RunWorkerCompleted(sender As Object, e As ComponentModel.RunWorkerCompletedEventArgs) Handles ChkDskD.RunWorkerCompleted
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - drive D had no errors")
    Dim msgChkDskD As String : msgChkDskD = ("[ " & Now & " ] PC - *" & pcSerial & "* - drive D had no errors")
    Call WriteToLog(title, msgChkDskD)
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - imaging C drive")
    Dim msgDismC As String : msgDismC = ("[ " & Now & " ] PC - *" & pcSerial & "* - imaging C drive")
    Call WriteToLog(title, msgDismC)

    DismC.RunWorkerAsync()
End Sub

Private Sub DismC_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) Handles DismC.DoWork
    If pcModel = "Server" Then
        pctype = "srvr"
    Else
        pctype = "wkstn"
    End If

    'Image C Drive
    Dim dismC As New Process
    dismC.StartInfo.FileName = "dism.exe"
    dismC.StartInfo.Arguments = " /Apply-Image /ImageFile:t:\" & pctype & ".wim /index:1 /ApplyDir:c:\"
    dismC.StartInfo.CreateNoWindow = True
    dismC.StartInfo.UseShellExecute = False
    dismC.StartInfo.RedirectStandardOutput = True
    dismC.StartInfo.RedirectStandardError = True
    dismC.EnableRaisingEvents = True
    Application.DoEvents()
    AddHandler dismC.ErrorDataReceived, AddressOf proc_OutputDataReceived
    AddHandler dismC.OutputDataReceived, AddressOf proc_OutputDataReceived
    dismC.Start()
    dismC.BeginErrorReadLine()
    dismC.BeginOutputReadLine()
    dismC.WaitForExit()
End Sub

Private Sub DismC_RunWorkerCompleted(sender As Object, e As ComponentModel.RunWorkerCompletedEventArgs) Handles DismC.RunWorkerCompleted
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - drive C imaged")
    Dim msgDismC As String : msgDismC = ("[ " & Now & " ] PC - *" & pcSerial & "* - drive C imaged")
    Call WriteToLog(title, msgDismC)
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - imaging D drive")
    Dim msgDismD As String : msgDismD = ("[ " & Now & " ] PC - *" & pcSerial & "* - imaging D drive")
    Call WriteToLog(title, msgDismD)

    DismD.RunWorkerAsync()
End Sub

Private Sub DismD_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) Handles DismD.DoWork
    If pcModel = "Server" Then
        pctype = "srvr"
    Else
        pctype = "wkstn"
    End If

    'Image D Drive
    Dim dismD As New Process
    dismD.StartInfo.FileName = "dism.exe"
    dismD.StartInfo.Arguments = " /Apply-Image /ImageFile:t:\" & pctype & ".wim /index:2 /ApplyDir:d:\"
    dismD.StartInfo.CreateNoWindow = True
    dismD.StartInfo.UseShellExecute = False
    dismD.StartInfo.RedirectStandardOutput = True
    dismD.StartInfo.RedirectStandardError = True
    dismD.EnableRaisingEvents = True
    Application.DoEvents()
    AddHandler dismD.ErrorDataReceived, AddressOf proc_OutputDataReceived
    AddHandler dismD.OutputDataReceived, AddressOf proc_OutputDataReceived
    dismD.Start()
    dismD.BeginErrorReadLine()
    dismD.BeginOutputReadLine()
    dismD.WaitForExit()
End Sub

Private Sub DismD_RunWorkerCompleted(sender As Object, e As ComponentModel.RunWorkerCompletedEventArgs) Handles DismD.RunWorkerCompleted
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - drive D imaged")
    Dim msgDismD As String : msgDismD = ("[ " & Now & " ] PC - *" & pcSerial & "* - drive D imaged")
    Call WriteToLog(title, msgDismD)
    Output("[ " & Now & " ] PC - *" & pcSerial & "* - imaging complete, rebooting")

    'Call reboot()
End Sub

Private Sub reboot()
    'Reboots a pc while in WinPE
    Dim reset As New Process
    reset.StartInfo.FileName = "wpeutils.exe"
    reset.StartInfo.Arguments = " shutdown"
    reset.Start()
End Sub

Private Sub WriteToLog(ByVal title As String, ByVal msg As String)
    'Check and make directory
    If Not System.IO.Directory.Exists("t:\logs\") Then
        System.IO.Directory.CreateDirectory("t:\logs\")
    End If

    'Check and make file
    Dim fs As FileStream = New FileStream("t:\logs\" & pcSerial & ".log", FileMode.OpenOrCreate, FileAccess.ReadWrite)
    Dim s As StreamWriter = New StreamWriter(fs)
    s.Close()
    fs.Close()

    'Logging
    Dim fs1 As FileStream = New FileStream("t:\logs\" & pcSerial & ".log", FileMode.Append, FileAccess.Write)
    Dim s1 As StreamWriter = New StreamWriter(fs1)
    s1.Write("Title: " & title & vbCrLf)
    s1.Write("Message: " & msg & vbCrLf)
    s1.Write("================================================" & vbCrLf)
    s1.Close()
    fs1.Close()
End Sub

Private Sub Output(s As String)
    'Output to form window
    If s <> "" Then
        tb1.AppendText(vbCrLf & ">> " & s)
    End If
End Sub

Public ReadOnly Property Model()
    Get
        Model = pcModel
    End Get
End Property

Public Function GetBiosSerialNumber() As String
    Dim OutputString As String = String.Empty
    Using Process As New Process
        AddHandler Process.OutputDataReceived,
    Sub(sender As Object, e As DataReceivedEventArgs)
        OutputString = OutputString & e.Data & vbCrLf
    End Sub
        With Process.StartInfo
            .FileName = "cmd"
            .UseShellExecute = False
            .CreateNoWindow = True
            .RedirectStandardInput = True
            .RedirectStandardOutput = True
            .RedirectStandardError = True
        End With
        With Process
            .Start()
            .BeginOutputReadLine()
        End With
        Using InputStream As System.IO.StreamWriter = Process.StandardInput
            With InputStream
                .AutoFlush = True
                .Write("wmic bios get serialnumber" & vbCrLf)
            End With
        End Using
        Do
            Application.DoEvents()
        Loop Until Process.HasExited
    End Using
    Return Replace(OutputString.Split(CChar(vbCrLf)).ToList(6).Substring(1), " ", "")
End Function

Public Sub UpdateTextBox(text As String)
    rtb1.Text += text & Environment.NewLine
    rtb1.SelectionStart = rtb1.Text.Length
    rtb1.ScrollToCaret()
End Sub

Public Sub proc_OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
    If Me.InvokeRequired = True Then
        Me.Invoke(myDelegate, e.Data)
    Else
        UpdateTextBox(e.Data)
    End If
End Sub

结束班