private static void UiElement_Closed(object sender, EventArgs e) { Window uiElement = (Window)sender; List <IMessagePathId> messageIds = (List <IMessagePathId>)uiElement.Resources[messagePathIdsResourceKey]; foreach (var handler in messageIds) { VirtualRoot.DeletePath(handler); } }
private static void ReleaseKernelProcessDaemon(IMineContext mineContext) { if (mineContext.Data.TryGetValue("_kernelProcessDaemon", out object obj)) { VirtualRoot.DeletePath((IMessagePathId)obj); mineContext.Data.Remove("_kernelProcessDaemon"); } if (mineContext.Data.TryGetValue("_clear", out obj)) { ((Action)obj)?.Invoke(); mineContext.Data.Remove("_clear"); } }
private static void KernelProcessDaemon(IMineContext mineContext, Action clear) { if (_kernelProcessDaemon != null) { VirtualRoot.DeletePath(_kernelProcessDaemon); _kernelProcessDaemon = null; clear?.Invoke(); } string processName = mineContext.Kernel.GetProcessName(); _kernelProcessDaemon = VirtualRoot.BuildEventPath <Per1MinuteEvent>("周期性检查挖矿内核是否消失,如果消失尝试重启", LogEnum.DevConsole, action: message => { if (mineContext == Instance.LockedMineContext) { if (!string.IsNullOrEmpty(processName)) { Process[] processes = Process.GetProcessesByName(processName); if (processes.Length == 0) { mineContext.AutoRestartKernelCount += 1; VirtualRoot.ThisLocalWarn(nameof(NTMinerRoot), processName + $"挖矿内核进程消失", toConsole: true); if (Instance.MinerProfile.IsAutoRestartKernel && mineContext.AutoRestartKernelCount <= Instance.MinerProfile.AutoRestartKernelTimes) { VirtualRoot.ThisLocalInfo(nameof(NTMinerRoot), $"尝试第{mineContext.AutoRestartKernelCount.ToString()}次重启,共{Instance.MinerProfile.AutoRestartKernelTimes.ToString()}次", toConsole: true); Instance.RestartMine(); Instance.LockedMineContext.AutoRestartKernelCount = mineContext.AutoRestartKernelCount; } else { Instance.StopMineAsync(StopMineReason.KernelProcessLost); } if (_kernelProcessDaemon != null) { VirtualRoot.DeletePath(_kernelProcessDaemon); clear?.Invoke(); } } } } else { if (_kernelProcessDaemon != null) { VirtualRoot.DeletePath(_kernelProcessDaemon); _kernelProcessDaemon = null; clear?.Invoke(); } } }); }
public static void CreateProcessAsync(IMineContext mineContext) { Task.Factory.StartNew(() => { lock (_locker) { try { #if DEBUG Write.Stopwatch.Restart(); #endif // 清理除当前外的Temp/Kernel Cleaner.Instance.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()); // N卡超频当cpu性能非常差时较耗时,所以这里弄个回调 IMessagePathId callback = null; callback = VirtualRoot.BuildEventPath <CoinOverClockDoneEvent>("超频完成后继续流程", LogEnum.DevConsole, message => { if (mineContext != Instance.CurrentMineContext) { VirtualRoot.DeletePath(callback); } else if (message.CmdId == cmd.Id) { VirtualRoot.DeletePath(callback); ContinueCreateProcess(mineContext); } }); VirtualRoot.Execute(cmd); } else { ContinueCreateProcess(mineContext); } } catch (Exception e) { Logger.ErrorDebugLine(e); Write.UserFail("挖矿内核启动失败,请联系开发人员解决"); } } }); }
private void ContextReInit(bool isWork) { foreach (var handler in _serverContextHandlers) { VirtualRoot.DeletePath(handler); } _serverContextHandlers.Clear(); if (isWork) { ReInitServerJson(); } ServerContextInit(isWork); // CoreContext的视图模型集此时刷新 VirtualRoot.RaiseEvent(new ServerContextReInitedEvent()); // CoreContext的视图模型集已全部刷新,此时刷新视图界面 VirtualRoot.RaiseEvent(new ServerContextVmsReInitedEvent()); if (isWork) { // 有可能是由非作业切换为作业,所以需要对IsJsonLocal赋值 IsJsonLocal = true; 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); if (!bret) { int lasterr = Marshal.GetLastWin32Error(); VirtualRoot.RaiseEvent(new StartingMineFailedEvent($"管道型进程创建失败 lasterr:{lasterr.ToString()}")); return; } const uint STARTF_USESHOWWINDOW = 0x00000001; const uint STARTF_USESTDHANDLES = 0x00000100; const uint NORMAL_PRIORITY_CLASS = 0x00000020; //const short SW_SHOW = 5; const short SW_HIDE = 0; const int HANDLE_FLAG_INHERIT = 1; //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 }; 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($"\"{kernelExeFileFullName}\" {arguments}"), lpProcessAttributes: IntPtr.Zero, lpThreadAttributes: IntPtr.Zero, bInheritHandles: true, dwCreationFlags: NORMAL_PRIORITY_CLASS, lpEnvironment: lpEnvironment, lpCurrentDirectory: Path.GetDirectoryName(kernelExeFileFullName), lpStartupInfo: ref lpStartupInfo, lpProcessInformation: out PROCESS_INFORMATION processInfo)) { try { mineContext.KernelProcess = Process.GetProcessById((int)processInfo.dwProcessId); } catch { CloseHandle(hReadOut); VirtualRoot.RaiseEvent(new StartingMineFailedEvent($"内核已退出")); return; } IMessagePathId closeHandle = null; KernelProcessDaemon(mineContext, () => { CloseHandle(hWriteOut); VirtualRoot.DeletePath(closeHandle); }); closeHandle = VirtualRoot.AddOnecePath <MineStopedEvent>("挖矿停止后关闭非托管的日志句柄", LogEnum.DevConsole, action: message => { ReleaseKernelProcessDaemon(mineContext); }, location: typeof(MinerProcess), pathId: Guid.Empty); Task.Factory.StartNew(() => { using (FileStream fs = new FileStream(mineContext.LogFileFullName, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { const byte r = (byte)'\r'; byte[] buffer = new byte[1024]; int ret; // Read会阻塞,直到读取到字符或者hWriteOut被关闭 while ((ret = Read(buffer, 0, buffer.Length, hReadOut)) > 0) { byte[] data = new byte[ret]; int n = 0; for (int i = 0; i < ret; i++) { if (buffer[i] != r) { data[n] = buffer[i]; n++; } } fs.Write(data, 0, n); fs.Flush(); } } CloseHandle(hReadOut); }, TaskCreationOptions.LongRunning); ReadPrintLoopLogFileAsync(mineContext, isWriteToConsole: true); }