public static void CreateProcess(IMineContext mineContext)
            {
                Global.DebugLine("解压内核包");
                // 解压内核包
                mineContext.Kernel.ExtractPackage();

                string kernelExeFileFullName;
                string arguments;

                Global.DebugLine("组装命令");
                // 组装命令
                BuildCmdLine(mineContext, out kernelExeFileFullName, out arguments);
                bool isLogFile = arguments.Contains("{logfile}");

                // 这是不应该发生的,如果发生很可能是填写命令的时候拼写错误了
                if (!File.Exists(kernelExeFileFullName))
                {
                    Global.WriteLine(kernelExeFileFullName + "文件不存在,请检查是否有拼写错误", ConsoleColor.Red);
                }
                if (isLogFile)
                {
                    Global.DebugLine("创建日志文件型进程");
                    // 如果内核支持日志文件
                    // 推迟打印cmdLine,因为{logfile}变量尚未求值
                    CreateLogfileProcess(mineContext, kernelExeFileFullName, arguments);
                }
                else
                {
                    Global.DebugLine("创建管道型进程");
                    // 如果内核不支持日志文件
                    string cmdLine = $"\"{kernelExeFileFullName}\" {arguments}";
                    Global.DebugLine(cmdLine, ConsoleColor.Yellow);
                    CreatePipProcess(mineContext, cmdLine);
                }
            }
Beispiel #2
0
            private static void ReadPrintLoopLogFile(IMineContext mineContext, string logFile)
            {
                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)
                {
                    using (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))
                                    {
                                        Global.WriteLine(input, color);
                                    }
                                }
                            }
                        }
                    Global.Logger.WarnWriteLine("日志输出结束");
                }
            }
Beispiel #3
0
            private static void ReadPrintLoopLogFile(IMineContext mineContext, string logFile)
            {
                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)
                {
                    using (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   kernelId = mineContext.Kernel.GetId();
                                    Current.KernelOutputFilterSet.Filter(kernelId, ref input);
                                    ConsoleColor color = ConsoleColor.White;
                                    Current.KernelOutputTranslaterSet.Translate(kernelId, ref input, ref color, isPre: true);
                                    Current.KernelSet.Pick(kernelId, ref input, mineContext);
                                    Current.KernelOutputTranslaterSet.Translate(kernelId, ref input, ref color);
                                    if (!string.IsNullOrEmpty(input))
                                    {
                                        Global.WriteLine(input, color);
                                    }
                                }
                            }
                        }
                    Global.Logger.WarnWriteLine("日志输出结束");
                }
            }
            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.WriteLine(processName + $"挖矿内核进程消失", ConsoleColor.Red);
                                if (Current.MinerProfile.IsAutoRestartKernel && mineContext.ProcessDisappearedCound <= 3)
                                {
                                    Global.WriteLine($"尝试第{mineContext.ProcessDisappearedCound}次重启,共3次", ConsoleColor.Red);
                                    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 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.WriteLine("内核启动失败,请重试", ConsoleColor.Red);
                }
            }
Beispiel #6
0
        public void Start()
        {
            BootLog.Log("开始启动Wcf服务");
            string      baseUrl = $"http://{MinerClientHost}:{Global.ClientPort}/";
            ServiceHost minerClientServiceHost = new ServiceHost(typeof(Core.Impl.MinerClientService));

            minerClientServiceHost.AddServiceEndpoint(typeof(IMinerClientService), ChannelFactory.BasicHttpBinding, new Uri(new Uri(baseUrl), nameof(IMinerClientService)));
            _serviceHosts = new List <ServiceHost>
            {
                minerClientServiceHost
            };
            foreach (var serviceHost in _serviceHosts)
            {
                ServiceMetadataBehavior serviceMetadata = serviceHost.Description.Behaviors.Find <ServiceMetadataBehavior>();
                if (serviceMetadata == null)
                {
                    serviceMetadata = new ServiceMetadataBehavior();
                    serviceHost.Description.Behaviors.Add(serviceMetadata);
                }
                serviceMetadata.HttpGetEnabled = false;

                serviceHost.Open();
            }

            Global.DebugLine($"服务启动成功: {DateTime.Now}.");
            Global.DebugLine("服务列表:");
            foreach (var serviceHost in _serviceHosts)
            {
                foreach (var endpoint in serviceHost.Description.Endpoints)
                {
                    Global.DebugLine(endpoint.Address.Uri.ToString());
                }
            }
            BootLog.Log("Wcf服务启动完成");

            Server.TimeService.GetTime((remoteTime) => {
                if (Math.Abs((DateTime.Now - remoteTime).TotalSeconds) < Global.DesyncSeconds)
                {
                    Global.DebugLine("时间同步");
                }
                else
                {
                    Global.WriteLine($"本机时间和服务器时间不同步,请调整,本地:{DateTime.Now},服务器:{remoteTime}", ConsoleColor.Red);
                }
            });

            Windows.Registry.SetValue(Registry.Users, ClientId.NTMinerRegistrySubKey, "Location", ClientId.AppFileFullName);
            Windows.Registry.SetValue(Registry.Users, ClientId.NTMinerRegistrySubKey, "Arguments", string.Join(" ", CommandLineArgs.Args));
            Windows.Registry.SetValue(Registry.Users, ClientId.NTMinerRegistrySubKey, "CurrentVersion", CurrentVersion.ToString());
            Windows.Registry.SetValue(Registry.Users, ClientId.NTMinerRegistrySubKey, "CurrentVersionTag", CurrentVersionTag);

            Report.Init(this);

            int      shareCount = 0;
            DateTime shareOn    = DateTime.Now;

            #region 挖矿开始时将无份额内核重启份额计数置0
            Global.Access <MineStartedEvent>(
                Guid.Parse("e69e8729-868b-4b5d-b120-2914fffddf90"),
                "挖矿开始时将无份额内核重启份额计数置0",
                LogEnum.None,
                action: message => {
                shareCount = 0;
                shareOn    = DateTime.Now;
            });
            #endregion
            #region 每10秒钟检查是否需要重启
            Global.Access <Per10SecondEvent>(
                Guid.Parse("16b3b7b4-5e6c-46b0-97a4-90e085614b78"),
                "每10秒钟检查是否需要重启",
                LogEnum.None,
                action: message => {
                #region 重启电脑
                try {
                    if (MinerProfile.IsPeriodicRestartComputer)
                    {
                        if ((DateTime.Now - shareOn).TotalHours > MinerProfile.PeriodicRestartComputerHours)
                        {
                            Global.WriteLine($"每运行{MinerProfile.PeriodicRestartKernelHours}小时重启电脑", ConsoleColor.Red);
                            Windows.Power.Restart();
                            return;    // 退出
                        }
                    }
                }
                catch (Exception e) {
                    Global.Logger.Error(e.Message, e);
                }
                #endregion

                #region 周期重启内核
                try {
                    if (IsMining && MinerProfile.IsPeriodicRestartKernel)
                    {
                        if ((DateTime.Now - shareOn).TotalHours > MinerProfile.PeriodicRestartKernelHours)
                        {
                            Global.WriteLine($"每运行{MinerProfile.PeriodicRestartKernelHours}小时重启内核", ConsoleColor.Red);
                            RestartMine();
                            return;    // 退出
                        }
                    }
                }
                catch (Exception e) {
                    Global.Logger.Error(e.Message, e);
                }
                #endregion

                #region 收益没有增加重启内核
                try {
                    if (IsMining && MinerProfile.IsNoShareRestartKernel)
                    {
                        if ((DateTime.Now - shareOn).TotalMinutes > MinerProfile.NoShareRestartKernelMinutes)
                        {
                            if (this.CurrentMineContext.MainCoin != null)
                            {
                                ICoinShare mainCoinShare = this.CoinShareSet.GetOrCreate(this.CurrentMineContext.MainCoin.GetId());
                                int totalShare           = mainCoinShare.TotalShareCount;
                                if ((this.CurrentMineContext is IDualMineContext dualMineContext) && dualMineContext.DualCoin != null)
                                {
                                    ICoinShare dualCoinShare = this.CoinShareSet.GetOrCreate(dualMineContext.DualCoin.GetId());
                                    totalShare += dualCoinShare.TotalShareCount;
                                }
                                if (shareCount == totalShare)
                                {
                                    Global.WriteLine($"{MinerProfile.NoShareRestartKernelMinutes}分钟收益没有增加重启内核", ConsoleColor.Red);
                                    RestartMine();
                                }
                                else
                                {
                                    shareCount = totalShare;
                                    shareOn    = DateTime.Now;
                                }
                            }