I am having trouble creating a simple app in Visual C#, that does the following:
- Insistently seek for a specific process.
- When that process starts running, copy a resource to a folder.
- When the process ends, copy another resource to that folder.
I tried using timers+threads, with no success. I think that a BackgroundWorker would help here, but the documentation is rather unclear. Here is my current code:
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);
}
}
}
As I mentioned in the comments, your current code only runs the check once and then the BackgroundWorker finishes. You could either:
use a timer to look for the process intermittently (say every minute), along the lines of the code you currently have in
Loop. When the process has started, you can then useProcess.WaitForExit()to pause your code until the process finishes. To continue to have your program be responsive, this part should be in aBackgroundWorker. Of course, there is a risk with this method that the process starts and finishes quickly, between timer ticks.Use
ManagementEventWatcherwithin WMI. This article on CodeProject defines a class that simplifies using WMI to be notified when a process starts and stops:The underlying code they are using is below: