2010-12-16 58 views
0

我想寫一個屏幕截圖的應用程序,抓取屏幕快照,保存到一個文件,打開Paint.NET與該文件,然後上傳當用戶完成編輯在Paint.NET該文件的編輯文件的服務。如何知道用戶何時在Paint.NET中完成編輯文件?

我有其他的東西排序覆蓋。如何檢測圖像在Paint.NET中完成編輯的時間?

我正在使用.NET 3.5,C#。

我可以用一個FileSystemWatcher來檢測特定文件的變化。但是第一次文件改變並不一定表明Paint.NET已經完成。我可以等待Paint.NET退出 - 我想通過檢查Windows中的進程列表並檢測Paint.NET何時不在那裏。但是用戶可以在不實際關閉Paint.NET的情況下完成編輯文件。

如果我必須告訴用戶關閉Paint.NET,以表示該文件就可以上傳,我想我能做到這一點。但我希望避免這種額外的要求。

如果Paint.NET保存一個文件在編輯時打開進行讀取,那麼我想我可以試着看看。但是如何?也許通過輪詢,試圖用FileShare.None打開文件。

有沒有更好的方法?


編輯 - 不,Paint.NET不保留文件打開,甚至不讀。我可以打開一個圖像文件FileShare.None沒有問題,即使它正在被Paint.NET顯示/編輯。所以這個想法是行不通的。


Paint.NET是否有一個Remoting接口,在那裏我可以詢問它打開了哪些文件?這將適合我的目的。

回答

0

與此擺弄一點點之後,我覺得UI自動化將滿足。使用.NET 3.0中新增的System.Windows.Automation類,我可以查詢計算機上其他Windows的內容,並且可以找到給定進程ID的窗口。所以這是一個問題

  • 找到PaintDotNet。通過在System.Diagnostics.Process.GetProcesses
  • 爲PaintDotNet應用
  • 檢查窗口的"name" property的主窗口獲得所述AutomationElement搜索EXE過程。
  • 當它從「myfile.jpg」變成別的東西時,我知道Paint.NET有 停止編輯該文件。
  • 如果我得到一個ElementNotAvailableException,那意味着Paint.NET已經退出。

我沒有測試這個非常多,但是,這個代碼似乎爲我的目的工作:

public void Run() 
{ 
    var shortFileName = Path.GetFileName(_filename); 
    System.Console.WriteLine("Waiting for PDN to finish with {0}", shortFileName); 

    var s= from p in Process.GetProcesses() 
     where p.ProcessName.Contains("PaintDotNet.exe") 
     select p; 

    if (s.Count()==0) 
    { 
     System.Console.WriteLine("PDN is not running."); 
     return; 
    } 

    var process = s.First(); 
    var window = AutomationElement.RootElement.FindChildByProcessId(process.Id); 

    string name = 
     window.GetCurrentPropertyValue(AutomationElement.NameProperty) as string; 

    if (!name.StartsWith(shortFileName)) 
    { 
     System.Console.WriteLine("PDN appears to NOT be editing the file."); 
    } 
    else 
    { 
     try 
     { 
      int cycles = 0; 
      do 
      { 
       System.Threading.Thread.Sleep(800); 
       name = window.GetCurrentPropertyValue(AutomationElement.NameProperty) as string; 
       if (!name.StartsWith(shortFileName)) break; 
       cycles++; 
       System.Console.Write("."); 
      } while (cycles < 24); 

      if (!name.StartsWith(shortFileName)) 
       System.Console.WriteLine("PDN is done."); 
      else 
       System.Console.WriteLine("Timeout."); 
     } 
     catch (ElementNotAvailableException) 
     { 
      System.Console.WriteLine("PDN has exited."); 
     } 
    } 
} 

FindChildByProcessId方法是this blog post擴展方法。它看起來像這樣:

public static class AutomationExtensions 
{ 
    public static AutomationElement FindChildByProcessId(this AutomationElement element, int pid) 
    { 
     var cond = new PropertyCondition(AutomationElement.ProcessIdProperty, pid); 
     var result = element.FindChildByCondition(cond); 
     return result; 
    } 

    public static AutomationElement FindChildByCondition(this AutomationElement element, Condition cond) 
    { 
     var result = element.FindFirst(TreeScope.Children, cond); 
     return result; 
    } 
} 

這似乎有點非正統,但它,它只是工作。最棘手的部分是時間 - 你需要等待足夠長的時間讓應用程序啓動,可以是1秒,也可以是7秒。然後嘗試使用UIAutomation類附加到它。

0

不幸的是,沒有更好的辦法。像Microsoft Outlook這樣的應用程序在編輯附件時遇到同樣的問題。你可以嘗試採取全面的方法做出最好的猜測。

例如,當您的應用程序脫殼而出,以Paint.NET(或不管他們有關聯的編輯器),你可以檢查,看看是否該文件已經改變,如果他們這樣做,也許提示後再次變得活躍。如果流程關閉,您可以將其作爲一個非常確定的標誌,表明他們已經完成並跳過提示。如果文件系統觀察檢測的變化,你可以排隊的,直到Paint.NET不再活動等

但在編輯它的許多應用程序將不會舉行任何類型的鎖在文件上。我很確定Paint.NET不會。 Office等應用程序可能會這樣做,這可能是爲什麼從Outlook編輯Word/Excel附件比純文本文件更可靠的原因。

相關問題