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);
            }
        }
Exemple #2
0
        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);
            }
        }
Exemple #3
0
            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
            }
Exemple #4
0
            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();
                        }
                    }
                });
            }
Exemple #6
0
            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("挖矿内核启动失败,请联系开发人员解决");
                        }
                    }
                });
            }
Exemple #7
0
 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();
     }
 }
Exemple #8
0
 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("内核启动失败,请重试");
                }
            }