private static void UiElement_Unloaded(object sender, RoutedEventArgs e) { FrameworkElement uiElement = (FrameworkElement)sender; List <IDelegateHandler> contextHandlers = (List <IDelegateHandler>)uiElement.Resources["ntminer_contextHandlers"]; foreach (var handler in contextHandlers) { VirtualRoot.UnPath(handler); } }
private static void UiElement_Closed(object sender, EventArgs e) { Window uiElement = (Window)sender; List <IDelegateHandler> contextHandlers = (List <IDelegateHandler>)uiElement.Resources["ntminer_contextHandlers"]; foreach (var handler in contextHandlers) { VirtualRoot.UnPath(handler); } }
private StartStopMineButtonViewModel() { if (Design.IsInDesignMode) { return; } #if DEBUG VirtualRoot.Stopwatch.Restart(); #endif this.StartMine = new DelegateCommand(() => { this.MinerProfile.IsMining = true; NTMinerRoot.Instance.StartMine(); BtnStopText = "正在挖矿"; }); this.StopMine = new DelegateCommand(() => { if (!NTMinerRoot.Instance.IsMining) { this.MinerProfile.IsMining = false; } NTMinerRoot.IsAutoStartCanceled = true; NTMinerRoot.Instance.StopMineAsync(() => { if (!NTMinerRoot.Instance.IsMining) { this.MinerProfile.IsMining = false; } }); }); if (NTMinerRoot.IsAutoStart && !this.MinerProfile.IsMining && VirtualRoot.SecondCount < MinerProfile.AutoStartDelaySeconds) { this.MinerProfile.IsMining = true; int n = MinerProfile.AutoStartDelaySeconds; Bus.IDelegateHandler handler = null; handler = On <Per1SecondEvent>("挖矿倒计时", LogEnum.None, action: message => { BtnStopText = $"倒计时({--n})"; if (n <= 0) { BtnStopText = "正在挖矿"; VirtualRoot.UnPath(handler); if (!NTMinerRoot.IsAutoStartCanceled) { NTMinerRoot.Instance.StartMine(); } } }); } #if DEBUG Write.DevWarn($"耗时{VirtualRoot.Stopwatch.ElapsedMilliseconds}毫秒 {this.GetType().Name}.ctor"); #endif }
private static void KernelProcessDaemon(IMineContext mineContext, Action clear) { if (_kernelProcessDaemon != null) { VirtualRoot.UnPath(_kernelProcessDaemon); _kernelProcessDaemon = null; clear?.Invoke(); } string processName = mineContext.Kernel.GetProcessName(); _kernelProcessDaemon = VirtualRoot.On <Per1MinuteEvent>("周期性检查挖矿内核是否消失,如果消失尝试重启", LogEnum.DevConsole, action: message => { if (mineContext == Instance.CurrentMineContext) { if (!string.IsNullOrEmpty(processName)) { Process[] processes = Process.GetProcessesByName(processName); if (processes.Length == 0) { mineContext.AutoRestartKernelCount = mineContext.AutoRestartKernelCount + 1; Logger.ErrorWriteLine(processName + $"挖矿内核进程消失"); if (Instance.MinerProfile.IsAutoRestartKernel && mineContext.AutoRestartKernelCount <= Instance.MinerProfile.AutoRestartKernelTimes) { Logger.WarnWriteLine($"尝试第{mineContext.AutoRestartKernelCount}次重启,共{Instance.MinerProfile.AutoRestartKernelTimes}次"); Instance.RestartMine(); Instance.CurrentMineContext.AutoRestartKernelCount = mineContext.AutoRestartKernelCount; } else { Instance.StopMineAsync(); } if (_kernelProcessDaemon != null) { VirtualRoot.UnPath(_kernelProcessDaemon); clear?.Invoke(); } } } } else { if (_kernelProcessDaemon != null) { VirtualRoot.UnPath(_kernelProcessDaemon); _kernelProcessDaemon = null; clear?.Invoke(); } } }); }
private static void Daemon(IMineContext mineContext, Action clear) { if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); _sDaemon = null; clear?.Invoke(); } string processName = mineContext.Kernel.GetProcessName(); _sDaemon = VirtualRoot.On <Per1MinuteEvent>("周期性检查挖矿内核是否消失,如果消失尝试重启", LogEnum.DevConsole, action: message => { if (mineContext == Current.CurrentMineContext) { if (!string.IsNullOrEmpty(processName)) { Process[] processes = Process.GetProcessesByName(processName); if (processes.Length == 0) { mineContext.ProcessDisappearedCound = mineContext.ProcessDisappearedCound + 1; Logger.ErrorWriteLine(processName + $"挖矿内核进程消失"); if (Current.MinerProfile.IsAutoRestartKernel && mineContext.ProcessDisappearedCound <= 3) { Logger.WarnWriteLine($"尝试第{mineContext.ProcessDisappearedCound}次重启,共3次"); Current.RestartMine(); Current.CurrentMineContext.ProcessDisappearedCound = mineContext.ProcessDisappearedCound; } else { Current.StopMineAsync(); } if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); clear?.Invoke(); } } } } else { if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); clear?.Invoke(); } } }); }
public static void CreateProcessAsync(IMineContext mineContext) { Task.Factory.StartNew(() => { lock (_locker) { try { #if DEBUG Write.Stopwatch.Restart(); #endif // 清理除当前外的Temp/Kernel Cleaner.Clear(); #if DEBUG Write.DevTimeSpan($"耗时{Write.Stopwatch.ElapsedMilliseconds}毫秒 {nameof(MinerProcess)}.{nameof(CreateProcessAsync)}[{nameof(Cleaner)}.{nameof(Cleaner.Clear)}]"); #endif Write.UserOk("场地打扫完毕"); // 应用超频 if (Instance.GpuProfileSet.IsOverClockEnabled(mineContext.MainCoin.GetId())) { Write.UserWarn("应用超频,如果CPU性能较差耗时可能超过1分钟,请耐心等待"); var cmd = new CoinOverClockCommand(mineContext.MainCoin.GetId()); DelegateHandler <CoinOverClockDoneEvent> callback = null; callback = VirtualRoot.On <CoinOverClockDoneEvent>("超频完成后继续流程", LogEnum.DevConsole, message => { if (mineContext != Instance.CurrentMineContext) { VirtualRoot.UnPath(callback); } else if (message.CmdId == cmd.Id) { VirtualRoot.UnPath(callback); Continue(mineContext); } }); VirtualRoot.Execute(cmd); } else { Continue(mineContext); } } catch (Exception e) { Logger.ErrorDebugLine(e); Write.UserFail("挖矿内核启动失败,请联系开发人员解决"); } } }); }
private void ContextReInit(bool isWork) { foreach (var handler in ContextHandlers) { VirtualRoot.UnPath(handler); } ContextHandlers.Clear(); if (isWork) { ReInitServerJson(); } ContextInit(isWork); OnContextReInited?.Invoke(); OnReRendContext?.Invoke(); if (isWork) { ReInitMinerProfile(); } }
private void ContextReInit(bool isWork) { foreach (var handler in _serverContextHandlers) { VirtualRoot.UnPath(handler); } _serverContextHandlers.Clear(); if (isWork) { ReInitServerJson(); } ServerContextInit(isWork); // CoreContext的视图模型集此时刷新 VirtualRoot.Happened(new ServerContextReInitedEvent()); // CoreContext的视图模型集已全部刷新,此时刷新视图界面 VirtualRoot.Happened(new ServerContextVmsReInitedEvent()); if (isWork) { ReInitMinerProfile(); } }
// 创建管道,将输出通过管道转送到日志文件,然后读取日志文件内容打印到控制台 private static void CreatePipProcess(IMineContext mineContext, string kernelExeFileFullName, string arguments) { 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 }; string cmdLine = $"\"{kernelExeFileFullName}\" {arguments}"; Write.UserOk(cmdLine); Write.UserInfo("有请内核上场"); StringBuilder lpEnvironment = new StringBuilder(); // 复制父进程的环境变量 IDictionary dic = Environment.GetEnvironmentVariables(); // 追加环境变量 foreach (var item in mineContext.CoinKernel.EnvironmentVariables) { dic.Add(item.Key, item.Value); } foreach (var key in dic.Keys) { if (key == null || key.ToString().Contains("\0")) { continue; } var value = dic[key]; if (value == null || value.ToString().Contains("\0")) { continue; } lpEnvironment.Append($"{key.ToString()}={value.ToString()}\0"); } if (CreateProcess( lpApplicationName: null, lpCommandLine: new StringBuilder(cmdLine), lpProcessAttributes: IntPtr.Zero, lpThreadAttributes: IntPtr.Zero, bInheritHandles: true, dwCreationFlags: NORMAL_PRIORITY_CLASS, lpEnvironment: lpEnvironment, lpCurrentDirectory: Path.GetDirectoryName(kernelExeFileFullName), lpStartupInfo: ref lpStartupInfo, lpProcessInformation: out _)) { if (bret == false) { int lasterr = Marshal.GetLastWin32Error(); VirtualRoot.Happened(new StartingMineFailedEvent($"管道型进程创建失败 lasterr:{lasterr}")); } 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); }, TaskCreationOptions.LongRunning); ReadPrintLoopLogFileAsync(mineContext, pipLogFileFullName); } } else { VirtualRoot.Happened(new StartingMineFailedEvent($"内核启动失败,请重试")); } }
// 创建管道,将输出通过管道转送到日志文件,然后读取日志文件内容打印到控制台 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("内核启动失败,请重试"); } }