0

Visual C#で簡単なアプリを作成するのに問題があります。これは次のことを行います。

  1. しつこく特定のプロセスを探します。
  2. そのプロセスの実行が開始されたら、リソースをフォルダーにコピーします。
  3. プロセスが終了したら、別のリソースをそのフォルダーにコピーします。

タイマーとスレッドを使用してみましたが、成功しませんでした。ここでは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);

        }
    }
}
4

1 に答える 1

1

コメントで述べたように、現在のコードはチェックを1回だけ実行し、その後BackgroundWorkerが終了します。次のいずれかを実行できます。

  • タイマーを使用して、現在のコードの行に沿って、断続的に(たとえば、毎分)プロセスを探しますLoop。プロセスが開始されたら、プロセスがProcess.WaitForExit()終了するまでコードを一時停止するために使用できます。プログラムの応答性を維持するには、この部分をに含める必要がありBackgroundWorkerます。もちろん、この方法には、タイマーのティックの間にプロセスがすばやく開始および終了するリスクがあります。

  • ManagementEventWatcherWMI内で使用します。CodeProjectに関するこの記事では、プロセスの開始時と停止時に通知される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();
于 2012-07-04T23:56:10.607 に答える