Esempio n. 1
0
        public void AddSlot(ServiceStarterElement eleConfig, Process p, string signal)
        {
            ServiceSlot slot = new ServiceSlot()
            {
                Name = eleConfig.Name,
                Config = eleConfig,
                WorkProcess = p,
                Signal = signal
            };

            _Slots.Add(slot);
        }
        public static bool RunServiceProcess(string domain, ServiceStarterElement eleConfig, out string msg)
        {
            bool retValue = false;

            string signal = Guid.NewGuid().ToString();

            msg = "";

            try
            {
                string contentFullPath = eleConfig.ContentPath;

                if(!Path.IsPathRooted(contentFullPath))
                {
                    contentFullPath = Path.Combine(Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory.TrimEnd(new char[] { '\\' })).FullName, "services",
                        contentFullPath.TrimStart(new char[] { '~' }).TrimStart(new char[] { '/' }));
                }

                Process p = new Process();
                p.StartInfo.Arguments = string.Format(" -n={0} -g={1} -c=\"{2}\" -a={3} -t={4} -m={5} -d={6}", eleConfig.Name, signal, contentFullPath,
                    eleConfig.AssemblyName, eleConfig.TypeName, domain, ServiceContext.Current.IsDebug ? "Y" : "N");
                p.StartInfo.CreateNoWindow = true;
                p.StartInfo.FileName = "cstarter.exe";
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.RedirectStandardError = true;

                p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
                p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);

                p.Start();
                p.BeginErrorReadLine();
                p.BeginOutputReadLine();

                CancellationTokenSource token = new CancellationTokenSource();

                Task t = new Task(() =>
                {
                    while (!token.IsCancellationRequested)
                    {
                        if (p.HasExited)
                        {
                            "服务进程 {0} 已经退出 {1}".Formate(eleConfig.Name, p.ExitCode.ToString()).Error();
                            ServiceContext.Current.ServiceStartedComplete();
                            break;
                        }
                    }
                }, token.Token);

                string.Format("等待服务 {0} 启动完成", eleConfig.Name).Info();

                t.Start();

                if (ServiceContext.Current.WaitServiceStarting(30))
                {
                    token.Cancel();

                    if (!p.HasExited)
                    {
                        "服务{0}已经成功启动".Formate(eleConfig.Name).Info();

                        ServiceContext.Current.AddSlot(eleConfig, p, signal);

                        retValue = true;
                    }
                    else
                    {
                        switch (p.ExitCode)
                        {
                            case 0:
                                "程序已退出,但是未返回错误码".Error();
                                break;
                            case -1:
                                "必须指定一个服务名称".Error();
                                break;
                            case -2:
                                "必须给定服务域".Error();
                                break;
                            case -3:
                                "必须指定一个信号量".Error();
                                break;
                            case -4:
                                "必须指定运行的路径".Error();
                                break;
                            case -5:
                                "运行路径必须是绝对路径".Error();
                                break;
                            case -6:
                                "必须指定入口类库".Error();
                                break;
                            case -7:
                                "必须指定入口类".Error();
                                break;
                            case -100:
                                "服务进程启动过程中发生错误,请查看服务进程启动日志获取详细信息".Error();
                                break;
                            default:
                                ("启动发生未知错误:" + p.ExitCode.ToString()).Error();
                                break;
                        }
                    }
                }
                else
                {
                    token.Cancel();

                    "在限定的时间内,启动的服务无响应,服务{0}可能没有成功启动".Formate(eleConfig.Name).Warn();

                    ServiceContext.Current.AddSlot(eleConfig, p, signal);

                    retValue = true;
                }
            }
            catch(Exception eX)
            {
                msg = eX.Message;
                eX.Exception();
            }

            return retValue;
        }