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 êëèåíò ìîæíî çàãðóçèòü.
Ìû îòâåòèì íà Âàøè âîïðîñû. C óâàæåíèåì, Åâãåíèé Âåðåñîâ.
09.08.2012 ãîäà.