【问题标题】:VB.NET: Code runs without error, but does not add item to listboxVB.NET:代码运行没有错误,但没有将项目添加到列表框
【发布时间】:2016-02-18 08:28:19
【问题描述】:

我的表单上有这个嵌入式 CMD,它是我使用其他人的代码创建的,并且一切正常。在其中一个 Private Subs 内(似乎每次在 CMD 输出文本框中写入新行时都会运行),我有一行在另一个标记为 Status 的表单上将项目添加到列表框(列表框名称为 txtPlayerList)。

当代码的这个区域运行时,它不会抛出任何错误(如果我将 msgbox() 放在同一行,则 msgbox() 可以工作)。如果我将添加到列表框行放在 form_load 上,它会完美工作吗?

这是我的代码,我已经包含了该表单中的所有内容以防万一(它在顶部的第三个子中,带有星号和评论“获取玩家,也许还有其他东西”

Imports System.IO

Public Class Console

Public WithEvents MyProcess As Process
Private Delegate Sub AppendOutputTextDelegate(ByVal text As String)
Public LastLine As String
Public LastLineFormatted As String

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    Dim LocalpathParent As String = Application.StartupPath() + "\MCserver"

    'loads embed cmd
    Me.AcceptButton = ExecuteButton
    MyProcess = New Process
    With MyProcess.StartInfo
        .FileName = "CMD.EXE"
        .UseShellExecute = False
        .CreateNoWindow = True
        .RedirectStandardInput = True
        .RedirectStandardOutput = True
        .RedirectStandardError = True
        .WorkingDirectory = LocalpathParent
    End With
    MyProcess.Start()

    MyProcess.BeginErrorReadLine()
    MyProcess.BeginOutputReadLine()
    AppendOutputText("Process Started at: " & MyProcess.StartTime.ToString)

    'Resize with parent mdi container. Needs to be anchored & StartPosition = manual in properties
    Me.WindowState = FormWindowState.Maximized

End Sub

Private Sub MyProcess_ErrorDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles MyProcess.ErrorDataReceived
    AppendOutputText(vbCrLf & "Error: " & e.Data)
End Sub

Private Sub MyProcess_OutputDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) Handles MyProcess.OutputDataReceived
    AppendOutputText(vbCrLf & e.Data)

    '*****************************************
    'Get Players and maybe other stuff as well
    '*****************************************

    LastLine = Me.OutputTextBox.Lines.Last
    If Status.ServerStarted = True Then

        If Me.LastLine.Contains(" joined the game") Then
            LastLineFormatted = Me.LastLine
            LastLineFormatted = LastLineFormatted.Replace(" joined the game", "")

            '***THIS LINE BELOW WORKS IN FORM LOAD, BUT NOT HERE FOR SOME REASON???***

            Status.txtPlayersList.Items.Add(LastLineFormatted)
            MsgBox("add lastlineformatted")

        ElseIf Me.LastLine.Contains(" left the game") Then
            LastLineFormatted = Me.LastLine
            LastLineFormatted = LastLineFormatted.Replace(" left the game", "")

            Status.txtPlayersList.Items.Remove(LastLineFormatted)
        End If
    End If
End Sub

Private Sub ExecuteButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExecuteButton.Click
    MyProcess.StandardInput.WriteLine(InputTextBox.Text)
    MyProcess.StandardInput.Flush()
    InputTextBox.Text = ""
End Sub

Private Sub AppendOutputText(ByVal text As String)
    If OutputTextBox.InvokeRequired Then
        Dim myDelegate As New AppendOutputTextDelegate(AddressOf AppendOutputText)
        Try
            Me.Invoke(myDelegate, text)
        Catch
        End Try
    Else
        Try
            OutputTextBox.AppendText(text)
        Catch
        End Try
    End If
End Sub
End Class

编辑:下面是我对每个请求的 form1 的代码

'代码

Public Class Form1
    Public Localpath As String
    Public Downloadpath As String
    Public LocalpathParent As String

    'when this form is closing, send stop to console to make sure it has closed and saved
    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        Console.MyProcess.StandardInput.WriteLine("stop") 'send an EXIT command to the Command Prompt
        Application.Exit()
        End
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'load stuff in background n stuff
        Me.Show()
        Me.Focus()
        Configure.Show()
        Configure.Hide()
        Status.Show()
        Status.Hide()
        Console.Show()
        Console.Hide()
    End Sub

    'CONSOLE.form
    Private Sub ConsoleToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles ConsoleToolStripMenuItem1.Click
        'Hide all forms
        Status.Hide()
        Configure.Hide()
        'Shown Form that you want to load
        Console.Opacity = 100
        Console.Show()
        WindowState = FormWindowState.Normal
        Console.MdiParent = Me

        Console.OutputTextBox.SelectionStart = Console.OutputTextBox.Text.Length
        Console.OutputTextBox.ScrollToCaret()
    End Sub

    'STATUS.form
    Private Sub StatusToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles StatusToolStripMenuItem1.Click
        'hide all forms
        Console.Hide()
        Configure.Hide()
        'Show Form that you want to load
        Status.Opacity = 100
        Status.Show()
        WindowState = FormWindowState.Maximized
        Configure.Size = Me.Size
        Status.MdiParent = Me
    End Sub

    'CONFIGURE.form
    Private Sub ConfigurationToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles ConfigurationToolStripMenuItem1.Click
        'hide all forms
        Status.Hide()
        Console.Hide()
        'Show form that you want to load
        Configure.Opacity = 100
        Configure.Show()
        WindowState = FormWindowState.Maximized
        Configure.Size = Me.Size
        Configure.MdiParent = Me
    End Sub
End Class

'代码

【问题讨论】:

  • 你说你已经包含了你所有的代码,但是 Status 没有在它的任何地方定义。请问什么是状态,以便我们验证您的代码。谢谢哦,是的 - 我假设 Class Console 是您的主要形式?
  • 我有一个名为 form1 的主窗体,它还有其他三个窗体:控制台、状态和配置。我可以发布状态表,但似乎一切正常。
  • 您如何以及在何处创建 Status 实例?
  • 我不认为我必须这样做;但我刚刚写了 'dim status1 as new status' 并将行引用改为 status1 ......它仍然没有做任何不同的事情。感谢您迄今为止的帮助!
  • 是的。 Visual Studio 只创建类定义,而不是表单的实例。您需要对您的其他表单执行相同的操作 - 控制台和配置。并以与我在下面的答案相同的方式访问它们。我认为这对你有用 - 希望......手指交叉

标签: vb.net listbox


【解决方案1】:

您创建嵌入式 CMD 窗口的原始代码似乎干扰了在另一个 mdi 子项中更新列表框的代码。在找到另一种嵌入 cmd 控制台的方法后,有些摆弄,它似乎工作正常。不过,我还不能测试纯服务器输出。

对代码进行了相当多的更改,这些更改太大而无法在此处发布,但替代嵌入式 CMD 就是这样。

将其放在一般形式的声明中

'command prompt variables
Private strResults As String
Private intStop As Integer
Private swWriter As System.IO.StreamWriter
Friend thrdCMD As System.Threading.Thread
Private Delegate Sub cmdUpdate()
Private uFin As New cmdUpdate(AddressOf UpdateText)
Public WithEvents procCMDWin As New Process

这在你的 form_load Sub

    thrdCMD = New System.Threading.Thread(AddressOf Prompt)
    thrdCMD.IsBackground = True
    thrdCMD.Start()

以及表单类中的这些声明

Private Sub Prompt()
    AddHandler procCMDWin.OutputDataReceived, AddressOf CMDOutput
    AddHandler procCMDWin.ErrorDataReceived, AddressOf CMDOutput
    procCMDWin.StartInfo.RedirectStandardOutput = True
    procCMDWin.StartInfo.RedirectStandardInput = True
    procCMDWin.StartInfo.CreateNoWindow = True
    procCMDWin.StartInfo.UseShellExecute = False
    procCMDWin.StartInfo.FileName = "cmd.exe"
    procCMDWin.StartInfo.WorkingDirectory = LocalpathParent
    procCMDWin.Start()
    procCMDWin.BeginOutputReadLine()
    swWriter = procCMDWin.StandardInput
    Do Until (procCMDWin.HasExited)
    Loop
    procCMDWin.Dispose()
End Sub

Private Sub UpdateText()
    OutputTextBox.Text += strResults
    OutputTextBox.SelectionStart = OutputTextBox.TextLength - 1
    InputTextBox.Focus()
    intStop = OutputTextBox.SelectionStart
    OutputTextBox.ScrollToCaret()
    If OutputTextBox.Lines.Count > 2 Then
        LastLine = OutputTextBox.Lines.ElementAt(OutputTextBox.Lines.Count - 2)
        If Status.ServerStarted = True Then
            'get element 1 of split
            If LastLine.Contains(" joined the game") Then
                LastLineFormatted = ExtractName(LastLine, " joined the game")
                'If listlineformatted.contains(Players.allitems) then do
                Status.txtPlayersList.Items.Add(LastLineFormatted)
                Status.Show()
            ElseIf Me.LastLine.Contains(" left the game") Then
                LastLineFormatted = ExtractName(LastLine, " left the game")
                'If listlineformatted.contains(Players.allitems) then do
                Status.txtPlayersList.Items.Remove(LastLineFormatted)
                MsgBox("remove lastlineformatted")
            End If
        End If
    End If
End Sub

Private Function ExtractName(unformattedString As String, stringToRemove As String) As String
    Dim temp As String = Split(unformattedString, "Server]")(1).ToString
    ExtractName = temp.Replace(stringToRemove, "")
End Function

Private Sub CMDOutput(ByVal Sender As Object, ByVal OutputLine As DataReceivedEventArgs)
    strResults = OutputLine.Data & Environment.NewLine
    Invoke(uFin)
End Sub

【讨论】:

  • 我已经使用设计视图和项目创建了所有表单-->添加 Windows 表单。我在 form1 中真正做的就是使用菜单条显示和隐藏表单
  • 您能否编辑您的问题以包含 Form1 代码,我可以确保其他表单已正确声明?当然没有冒犯的意思。
  • 该睡觉了 - 现在是 00:38
  • 轻松搞定。如果您愿意的话,希望我们明天可以解决这个问题。我已经编辑了原始问题以获取来自 form1 的代码。
  • 好的,我正在尝试尽可能多地复制您的程序 - 但我在控制台表单的这一行上遇到了跨线程操作错误。LastLine = OutputTextBox.Lines.Last。错误是 InvalidOperationException ...跨线程操作无效:控件“OutputTextBox”是从创建它的线程以外的线程访问的。 ...你有没有得到这个?
猜你喜欢
  • 2012-05-05
  • 1970-01-01
  • 1970-01-01
  • 2019-06-17
  • 2022-07-27
  • 1970-01-01
  • 1970-01-01
  • 2017-10-30
  • 1970-01-01
相关资源
最近更新 更多