formMinecraft.xaml.vb 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. Public Class formMinecraft
  2. Public Minecraft As Process = Nothing
  3. Public MinecraftVersion As MCVersion
  4. Public IsHidden As Boolean = False
  5. Public Logs As New ArrayList(10000)
  6. Public WaitToAppend As New ArrayList()
  7. Public MaxLength As Integer = 50 '最多显示的日志条数
  8. Public LogLastCount As Integer = 0 '上次显示时的日志条数,如果一样就不刷新
  9. Public DontExit As Boolean = False
  10. Public SendWarn As Boolean = ReadIni("setup", "LaunchLogWarn", "False") = "True"
  11. Public Sub New(ByVal MinecraftProcess As Process, ByVal Version As MCVersion, ByVal Hidden As Boolean)
  12. Try
  13. UseControlAnimation = False
  14. InitializeComponent()
  15. UseControlAnimation = True
  16. log("[Minecraft] 开始 Minecraft 日志监控")
  17. Minecraft = MinecraftProcess
  18. MinecraftVersion = Version
  19. IsHidden = Hidden
  20. Me.Title = "Minecraft 日志输出 - " & MinecraftVersion.Name
  21. AddHandler Minecraft.OutputDataReceived, AddressOf MinecraftDataReceived
  22. AddHandler Minecraft.ErrorDataReceived, AddressOf MinecraftDataReceived
  23. If IsHidden Then
  24. Me.Left = 100000
  25. Me.Visibility = Visibility.Collapsed
  26. Me.Show()
  27. Else
  28. Me.Show()
  29. log("[Minecraft] 显示 Minecraft 日志窗体")
  30. Try
  31. Me.Icon = BitmapFrame.Create(New Uri(PATH_IMAGE & "icon.ico"))
  32. Catch ex As Exception
  33. ExShow(ex, "创建 MC 监控窗口图标失败")
  34. End Try
  35. Me.ShowInTaskbar = True
  36. Me.WindowStyle = Windows.WindowStyle.SingleBorderWindow
  37. Me.Visibility = Visibility.Visible
  38. textOutput.Focus()
  39. '加载默认进程优先级
  40. Select Case Val(ReadReg("LaunchLevel", "1"))
  41. Case 0
  42. raHigh.Checked = True
  43. Case 1
  44. raMiddle.Checked = True
  45. Case 2
  46. raLow.Checked = True
  47. End Select
  48. End If
  49. Catch ex As Exception
  50. ExShow(ex, "创建 MC 监控窗口失败", ErrorLevel.MsgboxAndFeedback)
  51. End Try
  52. End Sub
  53. Private Sub MinecraftDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
  54. If Minecraft.HasExited Then Exit Sub
  55. WaitToAppend.Add(e.Data)
  56. End Sub
  57. Private Function AppendText(ByVal Text As String) As Boolean
  58. If IsNothing(Text) Or IsNothing(textOutput) Then Return True
  59. Text = Text.Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr, vbCrLf)
  60. Logs.Add(Text)
  61. If Text.StartsWith("[PCL]") Then log(Text.Replace("[PCL]", "[Minecraft]"))
  62. '转发日志
  63. If Text.ToLower.Contains("error") Or Text.ToLower.Contains("exception") Or Text.Contains("错误") Then
  64. If Not (Text.Contains("THIS IS NOT A ERROR") Or Text.Contains("[CHAT]")) Then log("[Minecraft] 错误信息:" & Text)
  65. End If
  66. If Text.ToLower.Contains("warn") Or Text.Contains("警告") Then
  67. If SendWarn And Not Text.Contains("[CHAT]") Then log("[Minecraft] 警告信息:" & Text)
  68. End If
  69. If (Text.Contains("Game crashed! Crash report saved to:") Or Text.Contains("This crash report has been saved to:")) And Not Text.Contains("[CHAT]") Then
  70. On Error Resume Next
  71. Dim ReportAddress As String = RegexSearch(Text, "[A-N]{1}:\\.*")(0)
  72. log("[Minecraft] Minecraft 已崩溃,崩溃日志:" & ReportAddress)
  73. DontExit = True
  74. If File.Exists(ReportAddress) Then
  75. On Error Resume Next
  76. WriteFile(ReportAddress, ReadFileToEnd(ReportAddress).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Replace(vbCr, vbCrLf))
  77. Shell("notepad", ReportAddress)
  78. ShowHintWindow("Minecraft " & If(MinecraftVersion.Version = "未知", "", MinecraftVersion.Version & " ") & "已崩溃", "PCL 将会为你打开崩溃报告。")
  79. Else
  80. ShowHintWindow("Minecraft " & If(MinecraftVersion.Version = "未知", "", MinecraftVersion.Version & " ") & "已崩溃", "崩溃报告未找到。")
  81. End If
  82. MinecraftCrash()
  83. Return False
  84. End If
  85. Return True
  86. End Function
  87. Private Sub timerRefresh_Tick() Handles timerRefresh.Tick
  88. Try
  89. '输出文本
  90. Dim Copyed As New ArrayList(WaitToAppend)
  91. WaitToAppend.Clear()
  92. For Each Str As String In Copyed
  93. If Not AppendText(Str) Then Exit Sub '如果是崩溃文本结束刷新
  94. Next
  95. '游戏退出检查
  96. If Minecraft.HasExited Then
  97. AppendText("[PCL] Minecraft 已退出,返回值:" & Minecraft.ExitCode)
  98. btnClose.IsEnabled = False
  99. raHigh.IsEnabled = False
  100. raMiddle.IsEnabled = False
  101. raLow.IsEnabled = False
  102. timerRefresh.IsEnabled = False
  103. If timerTitle.IsEnabled Then
  104. '尚未捕获到 Minecraft 窗口
  105. AppendText("[PCL] Minecraft 窗口未出现")
  106. DontExit = True
  107. MinecraftCrash()
  108. End If
  109. timerTitle.IsEnabled = False
  110. If (Not (Val(ReadIni("setup", "LaunchVisibility", "3")) = 2 Or Val(ReadIni("setup", "LaunchVisibility", "3")) = 4)) And Not DontExit Then
  111. EndNormal()
  112. End If
  113. End If
  114. '显示日志
  115. If Not (Logs.Count = LogLastCount Or IsHidden) Then
  116. LogLastCount = Logs.Count
  117. Dim resText As String = ""
  118. For i = Logs.Count - 1 To Math.Max(0, Logs.Count - MaxLength) Step -1
  119. resText = If(resText = "", "", resText & vbCrLf) & Logs(i)
  120. Next
  121. textOutput.Text = resText
  122. textOutput.Focus()
  123. End If
  124. Catch ex As Exception
  125. ExShow(ex, "MC 监控窗口主时钟出错")
  126. End Try
  127. End Sub
  128. Private Sub formMinecraft_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Closed
  129. If Not ReadIni("setup", "LaunchVisibility", "3") = "2" Then EndNormal()
  130. End Sub
  131. Private Sub btnClose_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnClose.Click
  132. 'RunCMD("taskkill /PID " & Minecraft.Id & " /F /T", False)
  133. btnClose.IsEnabled = False
  134. raHigh.IsEnabled = False
  135. raMiddle.IsEnabled = False
  136. raLow.IsEnabled = False
  137. timerTitle.IsEnabled = False
  138. On Error Resume Next
  139. Minecraft.Kill()
  140. AppendText("[PCL] 已发出强制关闭命令")
  141. If GameWindowState = LoadState.Loading Then GameWindowState = LoadState.Loaded
  142. End Sub
  143. Private Sub LevelChange(ByVal sender As Object, ByVal e As EventArgs) Handles raHigh.MouseUp, raMiddle.MouseUp, raLow.MouseUp
  144. Try
  145. If sender.Equals(raHigh) Then
  146. If Not Minecraft.PriorityClass = ProcessPriorityClass.AboveNormal Then
  147. Minecraft.PriorityClass = ProcessPriorityClass.AboveNormal
  148. AppendText("[PCL] Minecraft 进程优先级被设置为 高于正常")
  149. End If
  150. ElseIf sender.Equals(raMiddle) Then
  151. If Not Minecraft.PriorityClass = ProcessPriorityClass.Normal Then
  152. Minecraft.PriorityClass = ProcessPriorityClass.Normal
  153. AppendText("[PCL] Minecraft 进程优先级被设置为 正常")
  154. End If
  155. Else
  156. If Not Minecraft.PriorityClass = ProcessPriorityClass.BelowNormal Then
  157. Minecraft.PriorityClass = ProcessPriorityClass.BelowNormal
  158. AppendText("[PCL] Minecraft 进程优先级被设置为 低于正常")
  159. End If
  160. End If
  161. Catch ex As Exception
  162. AppendText("[PCL] Minecraft 进程优先级设置失败:" & GetStringFromException(ex))
  163. End Try
  164. End Sub
  165. Private Sub LengthChange(ByVal sender As Object, ByVal e As EventArgs) Handles raUnlimited.MouseUp, ra150.MouseUp, ra50.MouseUp
  166. If sender.Equals(raUnlimited) Then
  167. MaxLength = Integer.MaxValue
  168. ElseIf sender.Equals(ra150) Then
  169. MaxLength = 150
  170. Else
  171. MaxLength = 50
  172. End If
  173. LogLastCount = 0 '强制刷新
  174. timerRefresh_Tick()
  175. End Sub
  176. Private Sub timerTitle_Tick() Handles timerTitle.Tick
  177. If Minecraft.HasExited Then Exit Sub
  178. If Minecraft.MainWindowHandle = 0 Then Exit Sub
  179. If Minecraft.MainWindowTitle.Contains("Machine") Or Minecraft.MainWindowTitle.Contains("JVM") Then Exit Sub
  180. '找到窗口
  181. timerTitle.IsEnabled = False
  182. AppendText("[PCL] Minecraft 窗口已加载")
  183. GameWindowState = LoadState.Loaded
  184. '改变窗口标题
  185. Dim th As New Thread(Sub()
  186. Try
  187. Thread.Sleep(2000)
  188. If ReadReg("LaunchTopmost", "False") = "True" Then
  189. AppendText("[PCL] 已设置窗口置顶")
  190. SetWindowPos(Minecraft.MainWindowHandle, -1, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
  191. End If
  192. Dim NewTitle As String = ReadIni("setup", "LaunchTitle", "")
  193. If NewTitle = "" Then Exit Sub
  194. If NewTitle.Contains("\\r") And File.Exists(PATH & "PCL\RandomTitle.txt") Then
  195. Dim AllText As String() = ReadFileToEnd(PATH & "PCL\RandomTitle.txt", Encoding.Default).Replace(vbCrLf, vbCr).Replace(vbLf, vbCr).Split(vbCr)
  196. NewTitle = NewTitle.Replace("\\r",
  197. If(AllText.Length = 0, "", AllText(RandomInteger(0, AllText.Length - 1))))
  198. End If
  199. NewTitle = NewTitle.Replace("\\v", If(MinecraftVersion.Version = "未知", "", MinecraftVersion.Version))
  200. AppendText("[PCL] 已将窗口标题修改为:" & NewTitle)
  201. SetWindowText(Minecraft.MainWindowHandle, NewTitle)
  202. Catch ex As Exception
  203. AppendText("[PCL] 设置窗口标题失败:" & GetStringFromException(ex, MODE_DEBUG))
  204. End Try
  205. End Sub)
  206. th.Start()
  207. End Sub
  208. Private Sub MinecraftCrash()
  209. SendStat("启动", "Crash", MinecraftVersion.Name)
  210. If GameWindowState = LoadState.Loading Then GameWindowState = LoadState.Failed
  211. timerRefresh.IsEnabled = False
  212. '强制显示日志内容
  213. LogLastCount = Logs.Count
  214. Dim resText As String = ""
  215. For i = 0 To Logs.Count - 1
  216. resText = If(resText = "", "", resText & vbCrLf) & Logs(i)
  217. Next
  218. textOutput.Text = resText
  219. '显示日志窗口
  220. textOutput.Margin = New Thickness(0) '隐藏下边栏
  221. If Len(textOutput.Text) > 60 Then
  222. textOutput.Text = textOutput.Text & vbCrLf & "[PCL] 如果你需要其它人的帮助,请将本窗口内的所有内容都发送给对方"
  223. If Not Me.ShowInTaskbar Then
  224. Me.Left = 200
  225. Me.ShowInTaskbar = True
  226. Me.WindowStyle = Windows.WindowStyle.SingleBorderWindow
  227. Me.Visibility = Visibility.Visible
  228. End If
  229. End If
  230. '输出 PCL 调试信息
  231. Dim CurrentRam As Integer = Int((New Devices.ComputerInfo).AvailablePhysicalMemory / 1024 / 1024)
  232. textOutput.Text = textOutput.Text &
  233. vbCrLf &
  234. vbCrLf & "Plain Craft Launcher 诊断信息" &
  235. vbCrLf & "——————————————————" &
  236. vbCrLf & "启动器版本:" & VERSION_NAME & "(" & VERSION_CODE & ")" &
  237. vbCrLf & "Java 路径:" & PATH_JAVA &
  238. vbCrLf & "Java 版本:" & GetFileVersion(PATH_JAVA & "\javaw.exe") &
  239. vbCrLf & "关闭 MC 后的内存剩余:" & CurrentRam & "M / " & Int((New Devices.ComputerInfo).TotalPhysicalMemory / 1024 / 1024) & "M" &
  240. vbCrLf & "分配的内存:" & ReadReg("LaunchMaxRam", "1024") & "M" &
  241. vbCrLf & "Minecraft 文件夹:" & PATH_MC &
  242. vbCrLf & "Minecraft 版本文件夹名:" & MinecraftVersion.Name & "(" & MinecraftVersion.Version & ")" &
  243. vbCrLf
  244. '输出错误处理建议
  245. Dim Advices As New ArrayList
  246. If textOutput.Text.Contains("Could not reserve enough space") Then Advices.Add("分配的内存过多,尝试在启动设置中减少分配的内存空间。")
  247. If CurrentRam < ReadReg("LaunchMaxRam", "1024") Then Advices.Add("电脑内存不足,尝试关闭一些程序再试。(剩余 " & CurrentRam & " M,需要至少 " & ReadReg("LaunchMaxRam", "1024") & " M)")
  248. '显示错误处理建议
  249. If Advices.Count > 0 Then
  250. textOutput.Text = textOutput.Text &
  251. vbCrLf & "错误处理建议" &
  252. vbCrLf & "——————————————————"
  253. For i As Integer = 1 To Advices.Count
  254. textOutput.Text = textOutput.Text & vbCrLf & If(Advices.Count = 1, "", i & ". ") & Advices(i - 1)
  255. Next
  256. textOutput.Text = textOutput.Text & vbCrLf
  257. End If
  258. '末处理
  259. Me.Title = "Minecraft 日志 - " & MinecraftVersion.Name & "(已崩溃)"
  260. 'textOutput.ScrollToEnd()
  261. textOutput.SelectionStart = textOutput.Text.Length
  262. textOutput.SelectionLength = 0
  263. textOutput.Focus()
  264. End Sub
  265. End Class