在C#中为远程安装程序应用程序创建准确的进度条

时间:2016-01-17 05:39:08

标签: c# windows-installer progress-bar

这里对C#来说很新,我在学习的过程中学到了很多东西。

我正在创建一个远程安装补丁的Winforms应用。基本上,你给它一个文件(.msi或.exe)和一个计算机列表,它在列表中下去,直到所有补丁都已安装。它似乎适用于我想要它做的事情。只需点击一下即可进行漏洞/补丁管理。为了记录,我使用PSexec和powershell来完成同样的任务,他们很棒。只是摆弄我自己,希望在这个过程中做一些学习。

我想为应用程序创建一个准确的进度条,因此管理员可以大致了解当时正在处理的进程。可能需要修补的系统数量非常广泛,从10个系统到1K +。

我已经查看了进度条实现的教程,但大多数是基于代码编写器估计特定作业的任务完成时间。由于每个补丁大小,安装时间和计算机数量都不同,这似乎对我没什么帮助。

private void Start_Click(object sender, EventArgs e)
    {
        string complist = openFileDialog2.FileName;
        string patch = textBox2.Text;
        string fileName = patch;
        string patchfile = Path.GetFileName(fileName);

        foreach (string line in File.ReadLines(complist))
        {
            //Checks if C:\PatchUpdates exists on remote machine. If not, a folder is created.
            if (!Directory.Exists(@"\\" + line + @"\C$\PatchUpdates"))
            {
                Directory.CreateDirectory(@"\\" + line + @"\C$\PatchUpdates");
            }

            //XCOPY patch to every computer
            System.Diagnostics.Process processCopy = new System.Diagnostics.Process();
            ProcessStartInfo StartInfo = new ProcessStartInfo();
            StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            StartInfo.FileName = "cmd";
            StartInfo.Arguments = string.Format("/c xcopy " + patch + " " + @"\\{0}\C$\PatchUpdates /K /Y", line);
            processCopy.StartInfo = StartInfo;
            processCopy.Start();
            processCopy.WaitForExit();


            //Checks filename and installs according to file type.
            if (patch.Contains(".msi"))
            {
                //Uses WMI to execute a remote command to install using msiexec.
                ConnectionOptions options = new ConnectionOptions();
                options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
                ManagementScope WMIscope = new ManagementScope(
                string.Format("\\\\{0}\\root\\cimv2", line));
                WMIscope.Connect();
                ManagementClass WMIprocess = new ManagementClass(
                    WMIscope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
                object[] processmsi = { @"cmd.exe /c msiexec /qn /i " + @"C:\PatchUpdates\" + patchfile + @" /norestart" };
                object result = WMIprocess.InvokeMethod("Create", processmsi);
            }

            else if (patch.Contains(".exe"))
            {
                //Uses WMI to execute a remote command to install using commandline.
                ConnectionOptions options = new ConnectionOptions();
                options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
                ManagementScope WMIscope = new ManagementScope(
                    string.Format("\\\\{0}\\root\\cimv2", line));
                WMIscope.Connect();
                ManagementClass WMIprocess = new ManagementClass(
                    WMIscope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
                object[] processexe = { @"cmd.exe /c C:\PatchUpdates\" + patchfile + @" /silent /norestart" };
                object result = WMIprocess.InvokeMethod("Create", processexe);
            }

            else if (patch.Contains(".msu"))
            {
                //Uses WMI to execute a remote command to install using WUSA.
                ConnectionOptions options = new ConnectionOptions();
                options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
                ManagementScope WMIscope = new ManagementScope(
                    string.Format("\\\\{0}\\root\\cimv2", line));
                WMIscope.Connect();
                ManagementClass WMIprocess = new ManagementClass(
                    WMIscope, new ManagementPath("Win32_Process"), new ObjectGetOptions());
                object[] processmsu = { @"wusa " + patchfile + " /quiet /norestart" };
                object result = WMIprocess.InvokeMethod("Create", processmsu);
            }
        }
    }

上面的代码是完成大部分工作的地方。当用户单击“开始”时,修补程序将复制到每台计算机上的C:\ PatchUpdates,并使用WMI进行安装。

如何创建基于计算执行每项任务所用时间的进度条,并在修补最后一台计算机时以100%结束? 我假设需要做很多工作才能做到这一点。

感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

您需要先获取行数(系统计数)。

如果您使用的是.Net 4.0或更高版本,则可以使用

mDrawerLayout.setScrimColor(Color.TRANSPARENT);

否则你可以先做

var lineCount = File.ReadLines(@"C:\file.txt").Count();

之后,将progressbars minimum设置为0,将Maximum设置为此计数。在foreach中,您只需要执行progressbar.PerformStep。

var lineCount = 0;
using (var reader = File.OpenText(@"C:\file.txt"))
{
    while (reader.ReadLine() != null)
    {
        lineCount++;
    }
}