我想编写一个截图应用程序,它可以抓取屏幕截图,保存到文件中,用该文件打开Paint.NET,然后在用户完成在Paint.NET中编辑文件时将编辑的文件上传到服务中。
我还有其他的事情要处理。如何检测在Paint.NET中编辑完图像的时间?
我使用的是.NET 3.5,C#。
我可以使用FileSystemWatcher来检测特定文件中的更改。但是,当文件第一次更改时,并不一定表示Paint.NET已经完成。我可以等待Paint.NET退出-我想通过检查Paint.NET中的进程列表并检测Paint.NET何时不再存在。但是,用户可以在不实际关闭Paint.NET的情况下完成文件的编辑。
如果我必须告诉用户关闭Paint.NET,以表明文件已准备好上载,我想我可以这样做。但我希望避免这种额外的要求。
如果Paint.NET在编辑时保存了一个打开的文件供读取,那么我想我可以试着观察它。但是怎么做呢?也许是通过轮询,尝试用FileShare.None打开文件。
有更好的办法吗?
编辑-不,Paint.NET不打开文件,甚至不用于读取。我可以在FileShare.None上打开一个没有问题的图像文件,即使它是由Paint.NET显示/编辑的,所以这个想法行不通。
Paint.NET有远程处理接口吗?在那里,我可以询问它打开了哪些文件?这符合我的目的。
发布于 2010-12-16 04:10:42
经过一点修改后,我认为UI自动化将满足。使用Windows3.0中新的System.Windows.Automation类,我可以查询机器上其他.NET的内容,并且可以为给定的进程ID找到一个窗口。
我还没有对此进行过很多测试,但是,这段代码似乎符合我的目的:
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方法是这篇博客文章的扩展方法。看起来是这样的:
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类附加到它。
发布于 2010-12-16 02:43:36
不幸的是,没有更好的方法了。像Microsoft这样的应用程序在编辑附件时也有同样的问题。你可以试着做一个最好的猜测努力,采取上述所有的方法。
例如,当您的应用程序在向Paint.NET (或与其关联的任何编辑器)脱壳后再次激活时,您可以检查文件是否已更改,如果已完成,则可能会提示。如果进程关闭,您可以使用它作为一个非常确定的标志,它们已经完成,并跳过提示符。如果文件系统监视程序检测到更改,则可以将这些更改排队,直到Paint.NET不再处于活动状态,等等。
但是,许多应用程序在编辑文件时不会对文件持有任何类型的锁。我很确定Paint.NET没有。像Office这样的应用程序--这可能就是为什么编辑Outlook中的Word/Excel附件比纯文本文件更可靠的原因。
https://stackoverflow.com/questions/4456977
复制相似问题