访问Windows服务启动或关闭进度值

时间:2013-12-08 04:40:53

标签: c# winapi .net-4.0 windows-services

我想启动或停止任何服务并轮询dwCheckPoint SERVICE_STATUS,并使用它来填充进度条。或者使用任何其他方式访问您在服务控制面板中看到的进度值。

SERVICE_STATUS的{​​{3}}似乎意味着服务会填充这些值,因此也许可以访问它们。服务控制面板中显示的进度条为某些服务“跳转”,表示服务正在设置一个整数,并由监控应用程序读取。

dwCheckPoint

服务的检查点值会定期递增,以便在漫长的启动,停止,暂停或继续操作期间报告其进度。例如,服务应该在它启动时完成初始化的每个步骤时递增该值。 调用服务操作的用户界面程序使用此值来跟踪冗长操作期间服务的进度。此值无效,当服务没有启动时应该为零,停止,暂停或继续操作待定。

dwWaitHint

待处理的启动,停止,暂停或继续操作所需的估计时间(以毫秒为单位)。在指定的时间量过去之前,服务应该使用递增的dwCheckPoint值或dwCurrentState的更改来调用SetServiceStatus函数。如果dwWaitHint指定的时间量已经过去,并且dwCheckPoint尚未递增或dwCurrentState未更改,则服务控制管理器或服务控制程序可以假定发生了错误并且应该停止服务。但是,如果服务与其他服务共享进程,则服务控制管理器无法终止服务应用程序,因为它也必须终止共享该进程的其他服务。

这有什么例子吗?

1 个答案:

答案 0 :(得分:0)

这是部分答案。我可以得到进步;也可以随时跟踪最大进度。我仍在寻找调整它的最佳方法。现在可行;我希望让它变得完美...... 任何想法,将不胜感激。这就是为什么我还没有标出我自己的答案。

enter image description here 简单演示

代码:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DeveloperWorkbench.UI
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();

            this.ProgressChanged += Service_ProgressChanged;
            this.MaxProgressChanged += Service_MaxProgressChanged;
        }

        private delegate void IntDelegate(int value);

        private event IntDelegate ProgressChanged;
        private event IntDelegate MaxProgressChanged;

        private void Service_ProgressChanged(int value)
        {
            if (InvokeRequired)
                this.Invoke(new IntDelegate(Service_ProgressChanged), value);
            else
            {
                lblProgress.Text = value.ToString();
                progressBar1.Value = value;
            }
        }

        private void Service_MaxProgressChanged(int value)
        {
            if (InvokeRequired)
                this.Invoke(new IntDelegate(Service_MaxProgressChanged), value);
            else
            {
                progressBar1.Maximum = value;
            }            
        }

        private void UpdateServiceProgress(ServiceController serviceController)
        {
            int progress = 0;
            var maxProgressList = new List<int>(){119,120,744,745, 746};
            int maxProgressIndex = 0;
            int maxProgress = 747;
            bool tripped =  false;

            MaxProgressChanged(maxProgress);
            try
            {
                IntPtr smHandle = NativeMethods.OpenSCManager(null, null, NativeMethods.ServiceAccess.ENUMERATE_SERVICE);
                if (smHandle != IntPtr.Zero)
                {
                    IntPtr svHandle = NativeMethods.OpenService(smHandle, serviceController.ServiceName, NativeMethods.ServiceAccess.ENUMERATE_SERVICE);
                    if (svHandle != IntPtr.Zero)
                    {
                        var servStat = new NativeMethods.SERVICE_STATUS();
                        while (servStat.dwCurrentState != NativeMethods.ServiceState.Running)
                        {
                            if (NativeMethods.QueryServiceStatus(svHandle, servStat))
                            {
                                progress += servStat.dwCheckPoint;
                                if (progress > maxProgress)
                                {
                                    maxProgressIndex++;
                                    if (maxProgressIndex < maxProgressList.Count)
                                    {
                                        maxProgress = maxProgressList[maxProgressIndex];
                                        MaxProgressChanged(maxProgress);
                                    }
                                    else
                                        tripped = true;
                                }

                                ProgressChanged(progress);
                            }

                        }

                        NativeMethods.CloseServiceHandle(svHandle);
                    }
                    NativeMethods.CloseServiceHandle(smHandle);
                }
            }
            catch (System.Exception)
            {

            }
            if (tripped)
            {
                maxProgressList.Add(progress);
                Console.WriteLine("max progress {0}", progress);
            }

        }

        public static class NativeMethods
        {
            [DllImport("AdvApi32")]
            public static extern IntPtr OpenSCManager(string machineName, string databaseName, ServiceAccess access);
            [DllImport("AdvApi32")]
            public static extern IntPtr OpenService(IntPtr serviceManagerHandle, string serviceName, ServiceAccess access);
            [DllImport("AdvApi32")]
            public static extern bool CloseServiceHandle(IntPtr serviceHandle);
            [DllImport("AdvApi32")]
            public static extern bool QueryServiceStatus(IntPtr serviceHandle, [Out] SERVICE_STATUS status);

            [Flags]
            public enum ServiceAccess : uint
            {
                ALL_ACCESS = 0xF003F,
                CREATE_SERVICE = 0x2,
                CONNECT = 0x1,
                ENUMERATE_SERVICE = 0x4,
                LOCK = 0x8,
                MODIFY_BOOT_CONFIG = 0x20,
                QUERY_LOCK_STATUS = 0x10,
                GENERIC_READ = 0x80000000,
                GENERIC_WRITE = 0x40000000,
                GENERIC_EXECUTE = 0x20000000,
                GENERIC_ALL = 0x10000000
            }

            public enum ServiceState
            {
                Stopped = 1,
                StopPending = 3,
                StartPending = 2,
                Running = 4,
                Paused = 7,
                PausePending = 6,
                ContinuePending = 5
            }

            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public class SERVICE_STATUS
            {
                public int dwServiceType;
                public ServiceState dwCurrentState;
                public int dwControlsAccepted;
                public int dwWin32ExitCode;
                public int dwServiceSpecificExitCode;
                public int dwCheckPoint;
                public int dwWaitHint;
            };
        }

        private void button1_Click(object sender, EventArgs e)
        {
            progressBar1.Value = 0;
            progressBar1.Maximum = 0;

            var service = new ServiceController("MSSQLSERVER");
            if (service.Status == ServiceControllerStatus.Running)
            {
                service.Stop(); 
                service.WaitForStatus(ServiceControllerStatus.Stopped);
            }
            service.Start();
            var task = new Task(() => UpdateServiceProgress(service));
            task.Start();
        }

    }
}

表单设计师代码:

namespace DeveloperWorkbench.UI
{
    partial class Form2
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form2));
            this.button1 = new System.Windows.Forms.Button();
            this.progressBar1 = new System.Windows.Forms.ProgressBar();
            this.lblProgress = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(13, 13);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(207, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "Start Sql Server";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // progressBar1
            // 
            this.progressBar1.Location = new System.Drawing.Point(13, 42);
            this.progressBar1.Name = "progressBar1";
            this.progressBar1.Size = new System.Drawing.Size(207, 23);
            this.progressBar1.TabIndex = 1;
            // 
            // lblProgress
            // 
            this.lblProgress.AutoSize = true;
            this.lblProgress.Location = new System.Drawing.Point(227, 22);
            this.lblProgress.Name = "lblProgress";
            this.lblProgress.Size = new System.Drawing.Size(35, 13);
            this.lblProgress.TabIndex = 2;
            this.lblProgress.Text = "label1";
            // 
            // Form2
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(303, 74);
            this.Controls.Add(this.lblProgress);
            this.Controls.Add(this.progressBar1);
            this.Controls.Add(this.button1);
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.Name = "Form2";
            this.Text = "Service Status";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.ProgressBar progressBar1;
        private System.Windows.Forms.Label lblProgress;
    }
}