WatchFileActivity Windows Workflow
Статья описывает Windows Workflow WatchFileActivity. Программа разработана на языке C#. Activity получает путь отслеживаемого каталога, фильтр типов файлов, признак контроля вложенных каталогов. Далее программа отслеживает любые действия: по созданию, переименованию, удалению файлов. При выполнении этих действий Activity их распознает и выводит сообщение. Можно доработать Activity, например, так, чтобы она посылала сообщения на электронную почту при выполнении указанных выше действий.
Представлен рабочий проект MS Visual Studio 2010 WCF + WorkFlow, в котором применяется описываемая Activity. В состав проекта входят WorkFlow, класс расширения, Windows Form клиент, который выплолнет: удаление, переименование или создание файлов.
1. Входные данные WatchFileActivity.
Входными параметрами для Activity служат:
- Path - путь отслеживаемого каталога.
-
IncludeSubdirectories - признак, показывающий необходимость контроля вложенных каталогов по указанному пути.
-
Filter - фильтр, используемый для задания типов файлов, контролируемых в каталоге.
[RequiredArgument]
public InArgument<string> Path { get; set; }
[RequiredArgument]
public InArgument<bool> IncludeSubdirectories { get; set; }
[RequiredArgument]
public InArgument<string> Filter { get; set; }
2. Выходные данные WatchFileActivity.
Выходным аргументом Activity служит строка Result содержащая имя изменяемого обьекта.
[RequiredArgument]
public OutArgument<string> Result { get; set; }
3. Исходный текст WatchFileActivity.
Класс реализующий WatchFileActivity наследуется от класса NativeActivity и содержит методы определенные далее в тексте:
/* 09.08.2012
1. Пример Watch пргограммы в виде WatchFileActivity.
2. Activity отслеживает любые создание, переименование, удаления файлов.
3. Входными параметрами для Activity являются:
Path - получает путь отслеживаемого каталога.
IncludeSubdirectories - получает значение, показывающее необходимость контроля вложенных каталогов по указанному пути.
Filter - получает строку фильтра, используемую для определения файлов, контролируемых в каталоге.
4. Выходным параметром является Result содержащее имя изменяемого файла.
*/
using System;
using System.Collections.Generic;
using System.Activities;
using System.Activities.Hosting;
using System.IO;
using ClassLibrary;
namespace ActivityLibrary
{
public class WatchFileActivity : NativeActivity
{
[RequiredArgument]
public InArgument<string> Path { get; set; }
[RequiredArgument]
public InArgument<bool> IncludeSubdirectories { get; set; }
[RequiredArgument]
public InArgument<string> Filter { get; set; }
[RequiredArgument]
public OutArgument<string> Result { get; set; }
private FileSystemWatcher fileSystemWatcher = null;
private Bookmark bookmark = null;
private FileSystemWatcherExtension extension = null;
protected override void Execute(NativeActivityContext context)
{
try
{
// Create FileSystemWatcher
fileSystemWatcher = new FileSystemWatcher(context.GetValue(Path));
fileSystemWatcher.IncludeSubdirectories = context.GetValue(IncludeSubdirectories);
fileSystemWatcher.Filter = context.GetValue(Filter);
// Create a bookmark and get a link to it
bookmark = context.CreateBookmark(ResumeFileCreatedBookmark, BookmarkOptions.MultipleResume);
// Get a reference to the class extension FileSystemWatcherExtension
extension = context.GetExtension<FileSystemWatcherExtension>();
// Let's get the two links - the Watcher and the Bookmark function in Start
extension.Start(fileSystemWatcher, bookmark);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
protected override bool CanInduceIdle
{
get { return true; }
}
// Call to create/estore bookmarks
public void ResumeFileCreatedBookmark(NativeActivityContext context, Bookmark bookmark, object obj)
{
Result.Set(context, (string)obj);
}
}
}
4. Класс расширения для WatchFileActivity.
С Activity используется класс FileSystemWatcherExtension, который содержит обработчики событий:
/* 09.08.2012
Пример класса FileSystemWatcherExtension для WatchFileActivity.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
using System.Activities.Hosting;
using System.IO;
namespace ClassLibrary
{
public class FileSystemWatcherExtension : IWorkflowInstanceExtension
{
WorkflowInstanceProxy instance;
Bookmark bookmark;
public void SetInstance(WorkflowInstanceProxy instance)
{
this.instance = instance;
}
IEnumerable<object> IWorkflowInstanceExtension.GetAdditionalExtensions()
{
yield break;
}
public void Start(FileSystemWatcher fileSystemWatcher, Bookmark bookmark)
{
// Get a reference to a bookmark
this.bookmark = bookmark;
// Create a handler to create, rename, delete files
fileSystemWatcher.Created += new FileSystemEventHandler(FileCreated);
fileSystemWatcher.Renamed += new RenamedEventHandler(FileRename);
fileSystemWatcher.Deleted += new FileSystemEventHandler(FileCreated);
// Enable the reaction to changes to files and directories
fileSystemWatcher.EnableRaisingEvents = true;
Console.WriteLine("Start Watcher ...");
}
// 1. Handler when a file is created, that is, at first he was going to work!
void FileCreated(object sender, FileSystemEventArgs e)
{
instance.BeginResumeBookmark(bookmark, e.FullPath, CompleteResume, null);
Console.WriteLine("File Created: " + e.FullPath + " " + e.ChangeType);
}
// Handler when a file is renamed.
void FileRename(object sender, RenamedEventArgs e)
{
instance.BeginResumeBookmark(bookmark, e.FullPath, CompleteResume, null);
Console.WriteLine("Rename File:" + e.FullPath + " " + e.OldFullPath);
}
// Handler when a file is deleted.
void FileDeleted(object sender, FileSystemEventArgs e)
{
instance.BeginResumeBookmark(bookmark, e.FullPath, CompleteResume, null);
Console.WriteLine("Deleted File: " + e.FullPath + " " + e.ChangeType);
}
// 2. The second phase at the end of a bookmark
void CompleteResume(IAsyncResult ar)
{
var result = instance.EndResumeBookmark(ar);
}
}
}
5. Клиент для WatchFileActivity.
Ниже приведен пример клиента, который позволяет вносить изменения в файловую систему. Он используется только для отладки.
В реальной системе компьютеры сервера и клиента чаще всего различные.
/* 09.08.2012
Клиент для работы с Activity WatchFile
Выполняет действия :
1. Создание файла, если такой файл существует - сначала удаление.
2. Переименовывает файл методом копирования.
3. Вся логика по работе с изменением файлов сосредоточена здесь,
Activity выполняет функции: закладки, отлавливает все события, выводит сообщения.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ClientTestWatchActivity;
using System.IO;
namespace ClientTestWatchActivity
{
public partial class Form1 : Form
{
FileStream file;
public Form1()
{
InitializeComponent();
}
// Создание и удаление файла.
private void button1_Click(object sender, EventArgs e)
{
try
{
// Считаем имя создаваемого файла
string fileName = textBox2.Text;
// Имя не пустое?
if (String.IsNullOrEmpty(fileName)) throw new ArgumentOutOfRangeException("Name File: ", "Empty Value");
// Проверим, нет ли такого файла?
const string caption = "Delete File";
if (File.Exists(fileName))
{
var result = MessageBox.Show(fileName, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
// Если файл удалять - удалим
if (result == DialogResult.Yes) File.Delete(fileName);
}
file = File.Open(fileName, FileMode.Create);
byte[] bytes = UnicodeEncoding.Unicode.GetBytes(textBox1.Text);
file.Write(bytes, 0, bytes.Length);
file.Flush();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error ");
}
finally
{
if(!(file == null))
file.Close();
}
}
// Переименование файла
private void button2_Click(object sender, EventArgs e)
{
try
{
// Считаем имя файла который надо переименовать
string path = textBox2.Text;
// Считаем новое имя файла
string newPath = textBox3.Text;
// Певое Имя не пустое?
if (String.IsNullOrEmpty(path)) throw new ArgumentOutOfRangeException("Name File: ", "Empty Value");
// Второе имя не пустое?
if (String.IsNullOrEmpty(newPath)) throw new ArgumentOutOfRangeException("New Name File: ", "Empty Value");
// Проверим, нет ли первого файла, который надо удалить?
const string caption = "Delete File";
if (File.Exists(newPath))
{
var result = MessageBox.Show(newPath, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
// Если файл удалять - удалим
if (result == DialogResult.Yes) File.Delete(newPath);
}
File.Move(path, newPath);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error ");
}
finally
{
if (!(file == null))
file.Close();
}
}
// Включение - выключение кнопок.
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked == true)
{
textBox3.Enabled = true;
button1.Enabled = false;
button2.Enabled = true;
}
else
{
textBox3.Enabled = false;
button1.Enabled = true;
button2.Enabled = false;
}
}
}
}
Visual Studio 2010 проект содержащий: Activity, Workflow и Windows Form клиент можно загрузить.
Евгений Вересов.
09.08.2012 года.
|