2015-01-19 3 views
0

나는 diskparting 및 이미징 PC를위한 다음과 같은 클래스가 있습니다. 이 양식에는 프로세스의 각 단계 (출력)를 나열하는 일반 텍스트 상자 (tb1)와 실시간 프로세스 정보를 출력하는 리치 텍스트 상자 (rtb1)가 있습니다. 내가 겪고있는 문제는 앱이 다음 서브 루틴을 시작하기 전에 실시간 출력이 끝나기를 기다리지 않고 있다는 것입니다. 내가 어떤 조언을 주셔서 감사합니다vb.net에서 프로세스의 실시간 출력

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

당신이 프로세스를 산란 한 다음 기다리고있어 같이 여러 번 당신의 UI 스레드를 차단하고 있습니다. 백그라운드 작업을 수행하려면 별도의 스레드를 사용해야합니다. – xxbbcc

+0

용서해주세요. 나는 여전히 vb.net을 처음 사용합니다. 어떻게 그들을 별도의 스레드로 만들 수 있습니까? –

+0

그리고 그것은 실제로 배경 작업이 아닙니다. 1 프로세스가 다음 호출 전에 완료되어야합니다. –

답변

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 

최종 클래스