title: Bitmap file Integrity/Validity checking to confirm completion of Save Progress
body: <p>Heyo,
  I'm trying to find out if the Save-Progress of a bitmap file is completed, can't use the lock state or UNC Journal for it.. And heres why:</p>
  
  <p>Running a FileSystemWatcher i detect file creations and changes (also folders.. but they are not a problem). Now if i was just expecting copy/move operations this whole thing wouldn't be a problem.. The problem arises when the DCC applications come into play (let's take PhotoShop as an example here).</p>
  
  <p>When you open a file in PS it locks it (so far so good), when you save a file it saves to a temp then does some 'magic' and you got your 'new' file (depending on PS.version and file output format it writes to the file directly without the temp).. Even when using a temp it keeps a constant lock on the file and the Close is only added to the unc journal when you close the file in the application, not after the save is finished..</p>
  
  <p>So you can see my problem here.. In order to process the file further after it has been changed(or created) i need to know if it is in fact a valid, complete bitmap file.
  I've been searching and reading for 4 days on this now and thought I'd see if anyone was willing to help me on this.</p>
  
  <p>Here's a shortened version of the Watcher class with only the create and change handlers:</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.IO;
  
  namespace spacename
  {
    public class WatchDog2
    {
      private string RootPath;
  
      private FileSystemWatcher Watcher;
  
      // something running in the background chipping away at the cue
      private System.Timers.Timer Clock = new System.Timers.Timer(5000) { AutoReset = true };
  
      private List&lt;FileSystemEventArgs&gt; FileCheckList = new List&lt;FileSystemEventArgs&gt;();
  
      private bool CheckLock = false;
  
      #region Events
  
      public delegate void OnChangeHandler(object sender, FileSystemEventArgs e);
      public delegate void OnRenameHandler(object sender, RenamedEventArgs e);
  
      public event OnChangeHandler OnFileCreate;
      public event OnChangeHandler OnFolderCreate;
  
      public event OnChangeHandler OnFileChange;
  
      #endregion
  
      /// &lt;summary&gt;
      /// ctor
      /// &lt;/summary&gt;
      public WatchDog2(string rootPath, string filter = "*.*")
      {
        RootPath = rootPath;
  
        var di = new DirectoryInfo(rootPath);
  
        if (di.Exists)
        {
          Watcher = new FileSystemWatcher(di.FullName, filter);
  
          Watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite |
                                  NotifyFilters.FileName | NotifyFilters.DirectoryName;
  
          Watcher.IncludeSubdirectories = true;
  
          Watcher.InternalBufferSize = 65536; //64kb (max)
        }
        else
        {
          Watcher = new FileSystemWatcher();
        }
  
        Watcher.Created += Watcher_Created;
        Watcher.Changed += Watcher_Changed;
  
        Clock.Elapsed += Clock_Elapsed;
      }
  
      /// &lt;summary&gt;
      /// Create Handler
      /// &lt;/summary&gt;
      void Watcher_Created(object sender, FileSystemEventArgs e)
      {
        if (Path.HasExtension(e.FullPath))
        {
          if (App.SupportedExtensions.Contains(Path.GetExtension(e.FullPath).ToLower()))
          {
            if (new FileInfo(e.FullPath).Exists)
            {
              FileCheckList.Add(e);
  
              Clock.Start();
            }
          }
        }
        else
        {
          if (OnFolderCreate != null)
            OnFolderCreate(sender, e);
        }
      }
  
      /// &lt;summary&gt;
      /// Change Handler
      /// &lt;/summary&gt;
      void Watcher_Changed(object sender, FileSystemEventArgs e)
      {
        if (Path.HasExtension(e.FullPath))
        {
          if (App.SupportedExtensions.Contains(Path.GetExtension(e.FullPath).ToLower()))
          {
            if (new FileInfo(e.FullPath).Exists)
            {
              FileCheckList.Add(e);
  
              Clock.Start();
            }
          }
        } // no folder change catching
      }
  
      /// &lt;summary&gt;
      /// Queue check
      /// &lt;/summary&gt;
      void Clock_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
      {
        if (!CheckLock)
        {
          CheckLock = true;
  
          for (int i = 0; i &lt; FileCheckList.Count; i++)
          {
            var fi = new FileInfo(FileCheckList[i].FullPath);
  
            if (fi.Exists)
            {
              if (fi.Length &gt; 0) //add propper checks for bitmap validity
              {
                switch (FileCheckList[i].ChangeType)
                {
                  case WatcherChangeTypes.Created:
                    if (OnFileCreate != null)
                      OnFileCreate(null, FileCheckList[i]);
                    break;
  
                  case WatcherChangeTypes.Changed:
                    if (OnFileChange != null)
                      OnFileChange(null, FileCheckList[i]);
                    break;
                }
              }
            }
            else // if save was aborted
            {
              FileCheckList.RemoveAt(i);
            }
          }
          CheckLock = false;
        }
      }
    }
  }
  </code></pre>
  
  <p>Almost forgot.. I'm doing this in the context of a WPF application.</p>
  
  <p>thx for taking the time :)</p>