Visual C# - 如何在运行程序时将文件从资源复制到磁盘中的文件夹?

时间:2012-07-04 23:46:02

标签: c# process resources backgroundworker

我无法在Visual C#中创建一个简单的应用程序,它执行以下操作:

  1. 坚持不懈地寻求一个特定的过程。
  2. 当该进程开始运行时,将资源复制到文件夹。
  3. 当流程结束时,将另一个资源复制到该文件夹​​。
  4. 我尝试使用计时器+线程,但没有成功。我认为BackgroundWorker在这方面会有所帮助,但文档还不太清楚。这是我目前的代码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Resources;
    using System.Text;
    using System.Threading;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ResourceCopyApp
    {
        public partial class MainWindow : Window {
            BackgroundWorker bw;
            bool pcRunning = false;
            public MainWindow() {
                InitializeComponent();
                bw = new BackgroundWorker();
                bw.DoWork += new DoWorkEventHandler(Loop);
                bw.RunWorkerAsync();
            }
    
            private void Window_Loaded(object sender, RoutedEventArgs e) {
                cfgInstall.Text = Properties.Settings.Default.pcLocation;
                cfgLag.Value = Properties.Settings.Default.lag;
            }
    
            private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
                Properties.Settings.Default.pcLocation = cfgInstall.Text;
                Properties.Settings.Default.lag = (int)cfgLag.Value;
                Properties.Settings.Default.Save();
            }
    
            public void Loop(object sender, DoWorkEventArgs e) {
                pcRunning = false;
                bool pcWasRunning = pcRunning;
                if (pcRunning && !pcWasRunning) {
                    MessageBox.Show("Process found");
                    pcWasRunning = true;
                    Swap(true);
                }
                foreach (Process p in Process.GetProcesses()) {
                    if (p.ProcessName.Equals("Process")) {
                        pcRunning = true;
                    }
                }
                if (!pcRunning && pcWasRunning) {
                    MessageBox.Show("Process lost");
                    Swap(false);
                }
            }
            public void Swap(bool v) {
                byte[] file;
                Thread.Sleep(new TimeSpan((long)cfgLag.Value));
                if (v) {
                    file = Properties.Resources.NewRes;
                } else {
                    file = Properties.Resources.BackupRes;
                }
                string path = cfgInstall.Text;
                if (!cfgInstall.Text.EndsWith("/") && !cfgInstall.Text.EndsWith("\\")) {
                    path = cfgInstall.Text + "/test.txt";
                }
                File.WriteAllBytes(path, file);
    
            }
        }
    }
    

1 个答案:

答案 0 :(得分:1)

正如我在评论中提到的,您当前的代码只运行一次检查,然后BackgroundWorker完成。你可以:

  • 使用计时器间歇性地查找过程(比如说每分钟),沿着Loop中当前代码的行。该过程开始后,您可以使用Process.WaitForExit()暂停代码,直到该过程完成。要继续让您的程序响应,此部分应位于BackgroundWorker。当然,这种方法存在风险,即在计时器滴答之间,过程开始并快速完成。

  • 在WMI中使用ManagementEventWatcher。关于CodeProject的This文章定义了一个类,它简化了使用WMI在进程启动和停止时收到通知的信息:

    notePad = new ProcessInfo("notepad.exe");
    notePad.Started +=
        new Win32Process.ProcessInfo.StartedEventHandler(this.NotepadStarted);
    notePad.Terminated +=
        new Win32Process.ProcessInfo.TerminatedEventHandler(this.NotepadTerminated);
    

他们使用的基础代码如下:

  string queryString =
    "SELECT *" +
    "  FROM __InstanceOperationEvent " +
    "WITHIN  " + pol +
    " WHERE TargetInstance ISA 'Win32_Process' " +
    "   AND TargetInstance.Name = '" + appName + "'";

  // You could replace the dot by a machine name to watch to that machine
  string scope = @"\\.\root\CIMV2";

  // create the watcher and start to listen
  watcher = new ManagementEventWatcher(scope, queryString);
  watcher.EventArrived +=
          new EventArrivedEventHandler(this.OnEventArrived);
  watcher.Start();