private static void ReadPrintLoopLogFileAsync(IMineContext mineContext, string logFile) { Task.Factory.StartNew(() => { bool isLogFileCreated = true; int n = 0; while (!File.Exists(logFile)) { if (n >= 20) { // 20秒钟都没有建立日志文件,不可能 isLogFileCreated = false; Write.UserFail("呃!意外,竟然20秒钟未产生内核输出文件,请联系开发人员解决。"); break; } Thread.Sleep(1000); if (n == 0) { Write.UserInfo("等待内核出场"); } if (mineContext != Instance.CurrentMineContext) { Write.UserInfo("挖矿上下文变更,结束内核输出等待。"); isLogFileCreated = false; break; } n++; } if (isLogFileCreated) { Write.UserOk("内核已上场,下面把舞台交给内核。"); StreamReader sreader = null; try { sreader = new StreamReader(File.Open(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.Default); while (mineContext == Instance.CurrentMineContext) { string outline = sreader.ReadLine(); if (string.IsNullOrEmpty(outline) && sreader.EndOfStream) { Thread.Sleep(1000); } else { string input = outline; Guid kernelOutputId = mineContext.Kernel.KernelOutputId; Instance.KernelOutputFilterSet.Filter(kernelOutputId, ref input); ConsoleColor color = ConsoleColor.White; Instance.KernelOutputTranslaterSet.Translate(kernelOutputId, ref input, ref color, isPre: true); // 使用Claymore挖其非ETH币种时它也打印ETH,所以这里需要纠正它 if ("Claymore".Equals(mineContext.Kernel.Code, StringComparison.OrdinalIgnoreCase)) { if (mineContext.MainCoin.Code != "ETH" && input.Contains("ETH")) { input = input.Replace("ETH", mineContext.MainCoin.Code); } } Instance.KernelOutputSet.Pick(kernelOutputId, ref input, mineContext); if (IsUiVisible) { Instance.KernelOutputTranslaterSet.Translate(kernelOutputId, ref input, ref color); } if (!string.IsNullOrEmpty(input)) { if (Instance.KernelOutputSet.TryGetKernelOutput(kernelOutputId, out IKernelOutput kernelOutput)) { if (kernelOutput.PrependDateTime) { Write.UserLine($"{DateTime.Now} {input}", color); } else { Write.UserLine(input, color); } } else { Write.UserLine(input, color); } } } } } catch (Exception e) { Logger.ErrorDebugLine(e); } finally { sreader?.Close(); sreader?.Dispose(); } Write.UserInfo("内核表演结束"); } }, TaskCreationOptions.LongRunning); }
private static void ReadPrintLoopLogFileAsync(IMineContext mineContext, bool isWriteToConsole) { Task.Factory.StartNew(() => { bool isLogFileCreated = true; int n = 0; while (!File.Exists(mineContext.LogFileFullName)) { if (n >= 20) { // 20秒钟都没有建立日志文件,不可能 isLogFileCreated = false; Write.UserFail("呃!意外,竟然20秒钟未产生内核输出。常见原因:1.挖矿内核被杀毒软件删除; 2.没有磁盘空间了; 3.反馈给开发人员"); break; } Thread.Sleep(1000); if (n == 0) { Write.UserInfo("等待内核出场"); } if (mineContext != Instance.LockedMineContext) { Write.UserWarn("结束内核输出等待。"); isLogFileCreated = false; break; } n++; } if (isLogFileCreated) { StreamReader sreader = null; try { sreader = new StreamReader(File.Open(mineContext.LogFileFullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.Default); while (mineContext == Instance.LockedMineContext) { string outline = sreader.ReadLine(); if (string.IsNullOrEmpty(outline) && sreader.EndOfStream) { Thread.Sleep(1000); } else { string input = outline; Guid kernelOutputId = Guid.Empty; if (mineContext.KernelOutput != null) { kernelOutputId = mineContext.KernelOutput.GetId(); } // 前译 Instance.ServerContext.KernelOutputTranslaterSet.Translate(kernelOutputId, ref input, isPre: true); Instance.ServerContext.KernelOutputSet.Pick(ref input, mineContext); var kernelOutputKeywords = Instance.KernelOutputKeywordSet.GetKeywords(mineContext.KernelOutput.GetId()); if (kernelOutputKeywords != null && kernelOutputKeywords.Count != 0) { foreach (var keyword in kernelOutputKeywords) { if (input.Contains(keyword.Keyword)) { if (keyword.MessageType.TryParse(out LocalMessageType messageType)) { string content = input; if (!string.IsNullOrEmpty(keyword.Description)) { content += $" 大意:{keyword.Description}"; } VirtualRoot.LocalMessage(LocalMessageChannel.Kernel, nameof(MinerProcess), messageType, content, OutEnum.None, toConsole: false); } } } } if (isWriteToConsole) { if (!string.IsNullOrEmpty(input)) { Write.UserLine(input, ConsoleColor.White); } } } } } catch (Exception e) { Logger.ErrorDebugLine(e); } finally { sreader?.Close(); sreader?.Dispose(); } Write.UserWarn("内核表演结束"); } if (_kernelProcess != null) { lock (_kernelProcessLocker) { if (_kernelProcess != null) { _kernelProcess.Dispose(); _kernelProcess = null; } } } }, TaskCreationOptions.LongRunning); }
private static void ReadPrintLoopLogFileAsync(IMineContext mineContext, bool isWriteToConsole) { Task.Factory.StartNew(() => { bool isLogFileCreated = true; int n = 0; while (!File.Exists(mineContext.LogFileFullName)) { if (n >= 20) { // 20秒钟都没有建立日志文件,不可能 isLogFileCreated = false; Write.UserFail("呃!意外,竟然20秒钟未产生内核输出。常见原因:1.挖矿内核被杀毒软件删除; 2.没有磁盘空间了; 3.反馈给开发人员"); break; } Thread.Sleep(1000); if (n == 0) { Write.UserInfo("等待内核出场"); } if (mineContext != Instance.CurrentMineContext) { Write.UserWarn("结束内核输出等待。"); isLogFileCreated = false; break; } n++; } if (isLogFileCreated) { StreamReader sreader = null; try { sreader = new StreamReader(File.Open(mineContext.LogFileFullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.Default); while (mineContext == Instance.CurrentMineContext) { string outline = sreader.ReadLine(); if (string.IsNullOrEmpty(outline) && sreader.EndOfStream) { Thread.Sleep(1000); } else { string input = outline; Guid kernelOutputId = Guid.Empty; if (mineContext.KernelOutput != null) { kernelOutputId = mineContext.KernelOutput.GetId(); } Instance.KernelOutputFilterSet.Filter(kernelOutputId, ref input); ConsoleColor color = ConsoleColor.White; // 前译 Instance.KernelOutputTranslaterSet.Translate(kernelOutputId, ref input, ref color, isPre: true); // 使用Claymore挖其非ETH币种时它也打印ETH,所以这里需要纠正它 if ("Claymore".Equals(mineContext.Kernel.Code, StringComparison.OrdinalIgnoreCase)) { if (mineContext.MainCoin.Code != "ETH" && input.Contains("ETH")) { input = input.Replace("ETH", mineContext.MainCoin.Code); } } Instance.KernelOutputSet.Pick(ref input, mineContext); if (isWriteToConsole) { if (!string.IsNullOrEmpty(input)) { Write.UserLine(input, ConsoleColor.White); } } } } } catch (Exception e) { Logger.ErrorDebugLine(e); } finally { sreader?.Close(); sreader?.Dispose(); } Write.UserWarn("内核表演结束"); } if (_kernelProcess != null) { lock (_kernelProcessLocker) { if (_kernelProcess != null) { _kernelProcess.Dispose(); _kernelProcess = null; } } } }, TaskCreationOptions.LongRunning); }
// 创建管道,将输出通过管道转送到日志文件,然后读取日志文件内容打印到控制台 private static void CreatePipProcess(IMineContext mineContext, string cmdLine) { SECURITY_ATTRIBUTES saAttr = new SECURITY_ATTRIBUTES { bInheritHandle = true, lpSecurityDescriptor = IntPtr.Zero, length = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES)) }; //set the bInheritHandle flag so pipe handles are inherited saAttr.lpSecurityDescriptor = IntPtr.Zero; //get handle to current stdOut IntPtr mypointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(STARTUPINFO))); Marshal.StructureToPtr(saAttr, mypointer, true); var bret = CreatePipe(out var hReadOut, out var hWriteOut, mypointer, 0); //ensure the read handle to pipe for stdout is not inherited SetHandleInformation(hReadOut, HANDLE_FLAG_INHERIT, 0); ////Create pipe for the child process's STDIN STARTUPINFO lpStartupInfo = new STARTUPINFO { cb = (uint)Marshal.SizeOf(typeof(STARTUPINFO)), dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW, wShowWindow = SW_HIDE, // SW_HIDE; //SW_SHOW hStdOutput = hWriteOut, hStdError = hWriteOut, hStdInput = IntPtr.Zero }; if (CreateProcess( lpApplicationName: null, lpCommandLine: new StringBuilder(cmdLine), lpProcessAttributes: IntPtr.Zero, lpThreadAttributes: IntPtr.Zero, bInheritHandles: true, dwCreationFlags: NORMAL_PRIORITY_CLASS, lpEnvironment: IntPtr.Zero, lpCurrentDirectory: SpecialPath.KernelsDirFullName, lpStartupInfo: ref lpStartupInfo, lpProcessInformation: out _)) { if (bret == false) { int lasterr = Marshal.GetLastWin32Error(); Write.UserLine($"管道型进程创建失败 lasterr:{lasterr}", ConsoleColor.Red); } else { Bus.DelegateHandler <MineStopedEvent> closeHandle = null; bool isHWriteOutHasClosed = false; Daemon(mineContext, () => { if (!isHWriteOutHasClosed) { CloseHandle(hWriteOut); isHWriteOutHasClosed = true; } VirtualRoot.UnPath(closeHandle); }); closeHandle = VirtualRoot.On <MineStopedEvent>("挖矿停止后关闭非托管的日志句柄", LogEnum.DevConsole, action: message => { // 挖矿停止后摘除挖矿内核进程守护器 if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); _sDaemon = null; } if (!isHWriteOutHasClosed) { CloseHandle(hWriteOut); isHWriteOutHasClosed = true; } VirtualRoot.UnPath(closeHandle); }); string pipLogFileFullName = Path.Combine(SpecialPath.LogsDirFullName, mineContext.PipeFileName); Task.Factory.StartNew(() => { FileStream fs = new FileStream(pipLogFileFullName, FileMode.OpenOrCreate, FileAccess.ReadWrite); using (StreamReader sr = new StreamReader(fs)) { byte[] buffer = new byte[1024]; int ret; // Read会阻塞,直到读取到字符或者hWriteOut被关闭 while ((ret = Read(buffer, 0, buffer.Length, hReadOut)) > 0) { fs.Write(buffer, 0, ret); if (buffer[ret - 1] == '\r' || buffer[ret - 1] == '\n') { fs.Flush(); } } } CloseHandle(hReadOut); }); ReadPrintLoopLogFileAsync(mineContext, pipLogFileFullName); } } else { Logger.ErrorWriteLine("内核启动失败,请重试"); } }
private static void ReadPrintLoopLogFileAsync(IMineContext mineContext, string logFile) { Task.Factory.StartNew(() => { bool isLogFileCreated = true; int n = 0; while (!File.Exists(logFile)) { if (n >= 10) { // 10秒钟都没有建立日志文件,不可能 isLogFileCreated = false; break; } Thread.Sleep(1000); if (mineContext != Current.CurrentMineContext) { isLogFileCreated = false; break; } n++; } if (isLogFileCreated) { FileStream stream = File.Open(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); using (StreamReader sreader = new StreamReader(stream, Encoding.Default)) { while (mineContext == Current.CurrentMineContext) { string outline = sreader.ReadLine(); if (string.IsNullOrEmpty(outline)) { Thread.Sleep(1000); } else { string input = outline; Guid kernelOutputId = mineContext.Kernel.KernelOutputId; Current.KernelOutputFilterSet.Filter(kernelOutputId, ref input); ConsoleColor color = ConsoleColor.White; Current.KernelOutputTranslaterSet.Translate(kernelOutputId, ref input, ref color, isPre: true); // 使用Claymore挖其非ETH币种时它也打印ETH,所以这里需要纠正它 if ("Claymore".Equals(mineContext.Kernel.Code, StringComparison.OrdinalIgnoreCase)) { if (mineContext.MainCoin.Code != "ETH" && input.Contains("ETH")) { input = input.Replace("ETH", mineContext.MainCoin.Code); } } Current.KernelOutputSet.Pick(kernelOutputId, ref input, mineContext); Current.KernelOutputTranslaterSet.Translate(kernelOutputId, ref input, ref color); if (!string.IsNullOrEmpty(input)) { IKernelOutput kernelOutput; if (Current.KernelOutputSet.TryGetKernelOutput(kernelOutputId, out kernelOutput)) { if (kernelOutput.PrependDateTime) { Write.UserLine($"{DateTime.Now} {input}", color); } else { Write.UserLine(input, color); } } else { Write.UserLine(input, color); } } } } } Logger.WarnWriteLine("日志输出结束"); } }); }
/// <summary> /// 打开远程桌面窗口连接给定ip的windows主机 /// </summary> public static void OpenRemoteDesktop(RemoteDesktopInput input) { UIThread.Execute(() => { string serverIp = input.ServerIp; string userName = input.UserName; string password = input.Password; string description = input.Description; Action <string> onDisconnected = input.OnDisconnected; string[] serverIps = serverIp.Split(':'); serverIp = serverIps[0]; string id = serverIp.Replace(".", ""); string formName = $"form_{id}"; string formText = $"开源矿工远程桌面 - {description} ({serverIp})"; AxMsRdpClient7NotSafeForScripting axMsRdpc = null; string axMsRdpcName = $"axMsRdpc_{id}"; if (SFormsByName.ContainsKey(formName)) { Form form = SFormsByName[formName]; form.Show(); if (form.WindowState == FormWindowState.Minimized) { form.WindowState = FormWindowState.Normal; } form.Activate(); return; } else { axMsRdpc = new AxMsRdpClient7NotSafeForScripting(); } Form axMsRdpcForm = new Form { ShowIcon = false, Name = formName, Text = formText, Size = new Size(1200, 900), StartPosition = FormStartPosition.CenterScreen, MaximizeBox = false, WindowState = FormWindowState.Normal }; axMsRdpcForm.FormClosed += (object sender, FormClosedEventArgs e) => { Form frm = (Form)sender; foreach (Control ctrl in frm.Controls) { if (ctrl.GetType().Name == nameof(AxMsRdpClient7NotSafeForScripting)) { if (SFormsByName.ContainsKey(frm.Name)) { SFormsByName.Remove(frm.Name); } var axMsRdp = (AxMsRdpClient7NotSafeForScripting)ctrl; if (axMsRdp != null && axMsRdp.Connected != 0) { axMsRdp.Disconnect(); axMsRdp.Dispose(); } } } }; SFormsByName.Add(formName, axMsRdpcForm); ((System.ComponentModel.ISupportInitialize)(axMsRdpc)).BeginInit(); axMsRdpc.Dock = DockStyle.Fill; axMsRdpc.Enabled = true; axMsRdpc.OnConnecting += (object sender, EventArgs e) => { var axMsRdp = sender as AxMsRdpClient7NotSafeForScripting; axMsRdp.ConnectingText = axMsRdp.GetStatusText(Convert.ToUInt32(axMsRdp.Connected)); axMsRdp.FindForm().WindowState = FormWindowState.Normal; }; axMsRdpc.OnDisconnected += (object sender, IMsTscAxEvents_OnDisconnectedEvent e) => { var axMsRdp = sender as AxMsRdpClient7NotSafeForScripting; string disconnectedText = $"{formText}远程桌面连接已断开!"; axMsRdp.DisconnectedText = disconnectedText; axMsRdp.FindForm().Close(); Write.UserLine(disconnectedText, ConsoleColor.Red); onDisconnected?.Invoke(disconnectedText); }; axMsRdpcForm.Controls.Add(axMsRdpc); axMsRdpcForm.Show(); ((System.ComponentModel.ISupportInitialize)(axMsRdpc)).EndInit(); axMsRdpc.Name = axMsRdpcName; axMsRdpc.Server = serverIp; axMsRdpc.UserName = userName; axMsRdpc.AdvancedSettings7.RDPPort = serverIps.Length == 1 ? 3389 : Convert.ToInt32(serverIps[1]); // 启用CredSSP身份验证(有些服务器连接没有反应,需要开启这个) axMsRdpc.AdvancedSettings7.EnableCredSspSupport = true; axMsRdpc.AdvancedSettings7.ClearTextPassword = password; // 禁用公共模式 //axMsRdpc.AdvancedSettings7.PublicMode = false; // 颜色位数 8,16,24,32 axMsRdpc.ColorDepth = 32; axMsRdpc.FullScreen = false; axMsRdpc.DesktopWidth = axMsRdpcForm.ClientRectangle.Width; axMsRdpc.DesktopHeight = axMsRdpcForm.ClientRectangle.Height; axMsRdpc.Connect(); }); }