Progressbar 的进程安装无法正常工作
Process installation with Progressbar not working properly
我知道我将进程放在 for 循环中的方法不正确,我只是想知道如何通过安装更新进度条,进度条相应地更新进程安装。当安装开始时进度条在我的情况下在后台安装 运行 后更新。
void _bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressbar1.Value = e.ProgressPercentage;
}
void _bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
this.textblock1.Text = "Completed";
}
else if (!(e.Error == null))
{
this.textblock1.Text = ("Error :" + e.Error.Message);
}
else
{
progressbar1.Maximum = 100;
progressbar1.Minimum = 1;
progressbar1.Value = progressbar1.Maximum;
textblock1.Text = "Completed";
}
}
private readonly BackgroundWorker _bw = new BackgroundWorker();
public ControlPanelFinal()
{
InitializeComponent();
SilverLightInstall();
_bw.DoWork += _bw_DoWork;
_bw.RunWorkerCompleted += _bw_RunWorkerCompleted;
_bw.ProgressChanged += _bw_ProgressChanged;
_bw.WorkerReportsProgress = true;
}
void _bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 100; i++)
{
(sender as BackgroundWorker).ReportProgress(i);
Thread.Sleep(100);
}
string filepath = Path.Combine(Path.GetTempPath(), "Silverlight.exe");
Process p = new Process();
p.StartInfo.FileName = filepath;
p.StartInfo.Arguments = string.Format(" /q /i \"{0}\" ALLUSERS=1", filepath);
p.StartInfo.Verb = "runas";
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();
}
您是否可以这样做取决于您的 Silverlight 进程实际在做什么以及它本身是否提供任何进度通知,例如通过写入标准输出或为目的。
例如,如果进程确实写入 stdout,您可以这样做:
void _bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker)sender;
string filepath = Path.Combine(Path.GetTempPath(), "Silverlight.exe");
Process p = new Process();
p.StartInfo.FileName = filepath;
p.StartInfo.Arguments = string.Format(" /q /i \"{0}\" ALLUSERS=1", filepath);
p.StartInfo.Verb = "runas";
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
string line;
while ((line = p.StandardOutput.ReadLine()) != null)
{
worker.ReportProgress(ConvertStdoutToProgress(line));
}
}
其中 ConvertStdoutToProgress()
方法是您编写的某种假设方法,可以解释流程的一行输出并将其转换为某个百分比进度值。
(注意:重定向 stdout 以便您可以阅读它需要将 UseShellExecute
设置为 false
,但这可能会干扰您的场景。我看到您正在设置 Verb
属性,如果不将 UseShellExecute
设置为 true
,我不确定是否可以使用它。如果不是,那么显然你不能使用 stdout 重定向来取得进展。但你可能不会无论如何都可以……以上只是一个说明基本技术的示例;无论如何,您都必须根据自己的具体情况对其进行自定义。
如果您没有办法从流程中可靠地检索进度信息,那么最好的方法是根本不要尝试指示真正的进度。您仍然可以使用 ProgressBar
,但将 Style
属性 设置为 ProgressBarStyle.Marquee
。这将导致 ProgressBar
显示 activity 的动画指示(具体指示因平台而异,但这通常是一个填充条,带有周期性移动的动画突出显示)。
你可以在开始这个过程后设置一个带有计时器的循环,将进度伪造到一个点(你不会'想要显示完全完成,但可能高达 80-90%),如果进程本身提前完成,则提前完成,如果定时循环在进程之前完成,则只需等待接近完全完成状态。但我不建议这样做。我个人觉得这种进度指示很烦人,因为它暗示呈现的信息实际上并不存在。
我知道我将进程放在 for 循环中的方法不正确,我只是想知道如何通过安装更新进度条,进度条相应地更新进程安装。当安装开始时进度条在我的情况下在后台安装 运行 后更新。
void _bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressbar1.Value = e.ProgressPercentage;
}
void _bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if ((e.Cancelled == true))
{
this.textblock1.Text = "Completed";
}
else if (!(e.Error == null))
{
this.textblock1.Text = ("Error :" + e.Error.Message);
}
else
{
progressbar1.Maximum = 100;
progressbar1.Minimum = 1;
progressbar1.Value = progressbar1.Maximum;
textblock1.Text = "Completed";
}
}
private readonly BackgroundWorker _bw = new BackgroundWorker();
public ControlPanelFinal()
{
InitializeComponent();
SilverLightInstall();
_bw.DoWork += _bw_DoWork;
_bw.RunWorkerCompleted += _bw_RunWorkerCompleted;
_bw.ProgressChanged += _bw_ProgressChanged;
_bw.WorkerReportsProgress = true;
}
void _bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i <= 100; i++)
{
(sender as BackgroundWorker).ReportProgress(i);
Thread.Sleep(100);
}
string filepath = Path.Combine(Path.GetTempPath(), "Silverlight.exe");
Process p = new Process();
p.StartInfo.FileName = filepath;
p.StartInfo.Arguments = string.Format(" /q /i \"{0}\" ALLUSERS=1", filepath);
p.StartInfo.Verb = "runas";
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();
}
您是否可以这样做取决于您的 Silverlight 进程实际在做什么以及它本身是否提供任何进度通知,例如通过写入标准输出或为目的。
例如,如果进程确实写入 stdout,您可以这样做:
void _bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker)sender;
string filepath = Path.Combine(Path.GetTempPath(), "Silverlight.exe");
Process p = new Process();
p.StartInfo.FileName = filepath;
p.StartInfo.Arguments = string.Format(" /q /i \"{0}\" ALLUSERS=1", filepath);
p.StartInfo.Verb = "runas";
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.Start();
string line;
while ((line = p.StandardOutput.ReadLine()) != null)
{
worker.ReportProgress(ConvertStdoutToProgress(line));
}
}
其中 ConvertStdoutToProgress()
方法是您编写的某种假设方法,可以解释流程的一行输出并将其转换为某个百分比进度值。
(注意:重定向 stdout 以便您可以阅读它需要将 UseShellExecute
设置为 false
,但这可能会干扰您的场景。我看到您正在设置 Verb
属性,如果不将 UseShellExecute
设置为 true
,我不确定是否可以使用它。如果不是,那么显然你不能使用 stdout 重定向来取得进展。但你可能不会无论如何都可以……以上只是一个说明基本技术的示例;无论如何,您都必须根据自己的具体情况对其进行自定义。
如果您没有办法从流程中可靠地检索进度信息,那么最好的方法是根本不要尝试指示真正的进度。您仍然可以使用 ProgressBar
,但将 Style
属性 设置为 ProgressBarStyle.Marquee
。这将导致 ProgressBar
显示 activity 的动画指示(具体指示因平台而异,但这通常是一个填充条,带有周期性移动的动画突出显示)。
你可以在开始这个过程后设置一个带有计时器的循环,将进度伪造到一个点(你不会'想要显示完全完成,但可能高达 80-90%),如果进程本身提前完成,则提前完成,如果定时循环在进程之前完成,则只需等待接近完全完成状态。但我不建议这样做。我个人觉得这种进度指示很烦人,因为它暗示呈现的信息实际上并不存在。