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 == 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 (_sDaemon != null)
                                {
                                    VirtualRoot.UnPath(_sDaemon);
                                    clear?.Invoke();
                                }
                            }
                        }
                    }
                    else
                    {
                        if (_sDaemon != null)
                        {
                            VirtualRoot.UnPath(_sDaemon);
                            clear?.Invoke();
                        }
                    }
                });
            }
Exemple #2
0
            private static void Daemon(IMineContext mineContext, Action clear)
            {
                string processName = mineContext.Kernel.GetProcessName();

                Bus.DelegateHandler <Per1MinuteEvent> daemon = null;
                daemon = Global.Access <Per1MinuteEvent>(
                    Guid.Parse("a4761e90-dc3c-4483-b055-546084863640"),
                    "周期性检查挖矿内核是否消失,如果消失尝试重启",
                    LogEnum.None,
                    action: message => {
                    if (mineContext == Current.CurrentMineContext)
                    {
                        if (!string.IsNullOrEmpty(processName))
                        {
                            Process[] processes = Process.GetProcessesByName(processName);
                            if (processes.Length == 0)
                            {
                                mineContext.ProcessDisappearedCound = mineContext.ProcessDisappearedCound + 1;
                                Global.Logger.WarnWriteLine(processName + $"挖矿内核进程消失");
                                if (Current.MinerProfile.IsAutoRestartKernel && mineContext.ProcessDisappearedCound <= 3)
                                {
                                    Global.Logger.WarnWriteLine($"尝试第{mineContext.ProcessDisappearedCound}次重启,共3次");
                                    Current.RestartMine();
                                    Current.CurrentMineContext.ProcessDisappearedCound = mineContext.ProcessDisappearedCound;
                                }
                                else
                                {
                                    Current.StopMine();
                                }
                                Global.UnAccess(daemon);
                                clear?.Invoke();
                            }
                        }
                    }
                    else
                    {
                        Global.UnAccess(daemon);
                        clear?.Invoke();
                    }
                });
            }
            // 创建管道,将输出通过管道转送到日志文件,然后读取日志文件内容打印到控制台
            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($"内核启动失败,请重试"));
                }
            }
Exemple #4
0
            // 创建管道,将输出通过管道转送到日志文件,然后读取日志文件内容打印到控制台
            private static void CreatePipProcess(IMineContext mineContext, string cmdLine)
            {
                SECURITY_ATTRIBUTES saAttr = new SECURITY_ATTRIBUTES();
                IntPtr hReadOut, hWriteOut;

                //set the bInheritHandle flag so pipe handles are inherited

                saAttr.bInheritHandle       = true;
                saAttr.lpSecurityDescriptor = IntPtr.Zero;
                saAttr.length = Marshal.SizeOf(typeof(SECURITY_ATTRIBUTES));
                saAttr.lpSecurityDescriptor = IntPtr.Zero;
                //get handle to current stdOut

                bool bret;

                IntPtr mypointer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(STARTUPINFO)));

                Marshal.StructureToPtr(saAttr, mypointer, true);
                bret = CreatePipe(out hReadOut, out 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
                };
                PROCESS_INFORMATION lpProcessInformation;

                if (CreateProcess(
                        lpApplicationName: null,
                        lpCommandLine: new StringBuilder(cmdLine),
                        lpProcessAttributes: IntPtr.Zero,
                        lpThreadAttributes: IntPtr.Zero,
                        bInheritHandles: true,
                        dwCreationFlags: NORMAL_PRIORITY_CLASS,
                        lpEnvironment: IntPtr.Zero,
                        lpCurrentDirectory: null,
                        lpStartupInfo: ref lpStartupInfo,
                        lpProcessInformation: out lpProcessInformation))
                {
                    if (bret == false)
                    {
                        int lasterr = Marshal.GetLastWin32Error();
                    }
                    else
                    {
                        Bus.DelegateHandler <MineStopedEvent> closeHandle = null;
                        bool isHWriteOutHasClosed = false;
                        Daemon(mineContext, () => {
                            if (!isHWriteOutHasClosed)
                            {
                                CloseHandle(hWriteOut);
                                isHWriteOutHasClosed = true;
                            }
                            Global.UnAccess(closeHandle);
                        });
                        closeHandle = Global.Access <MineStopedEvent>(
                            Guid.Parse("91642027-fd28-4bdd-a05a-31caac6609b1"),
                            "挖矿停止后关闭非托管的日志句柄",
                            LogEnum.Log,
                            action: message => {
                            if (!isHWriteOutHasClosed)
                            {
                                CloseHandle(hWriteOut);
                                isHWriteOutHasClosed = true;
                            }
                            Global.UnAccess(closeHandle);
                        });
                        string pipLogFileFullName = Path.Combine(SpecialPath.LogsDirFullName, mineContext.PipeFileName);
                        Task.Factory.StartNew(() => {
                            using (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);
                        });
                        Task.Factory.StartNew(() => {
                            ReadPrintLoopLogFile(mineContext, pipLogFileFullName);
                        });
                    }
                }
                else
                {
                    Global.Logger.WarnWriteLine("内核启动失败,请重试");
                }
            }
            // 创建管道,将输出通过管道转送到日志文件,然后读取日志文件内容打印到控制台
            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("内核启动失败,请重试");
                }
            }