我的应用程序存储所有类型的文件,并允许用户打开这些文件。我们只使用Process.Start
使用默认应用程序打开文件。我们还允许用户拖放从多个位置(包括Outlook)将文件拖放到我们的应用程序中
此功能通常可以正常工作,但是有一种情况会导致问题:当用户打开存储在我们的应用程序中的Outlook电子邮件时,该电子邮件具有附件,然后尝试拖动&将附加文件放入我们的应用程序,Outlook锁定电子邮件文件,并且永远不会释放锁定,直到我们的应用程序或Outlook关闭。
我在WPF和Winforms的简单测试应用程序以及3.0到4.5.1的所有.Net版本中都重现了这个问题。
XAML:
<Window x:Class="DragDropBug.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="250" Width="300">
<Grid AllowDrop="True" Drop="HandleDrop">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.ColumnSpan="2" Text="DROP THE FILE HERE!"/>
<Button Grid.Row="1" Grid.Column="0" Content="Open File" Click="OpenTheFile"/>
<Button Grid.Row="1" Grid.Column="1" Content="Try to Delete File" Click="DeleteTheFile"/>
</Grid>
</Window>
代码隐藏文件:
using System;
using System.Diagnostics;
using System.IO;
using System.Windows;
namespace DragDropBug
{
public partial class MainWindow : Window
{
private const string ORIGINAL_FILENAME = "Testing.msg";
private const string WORKING_FILENAME = "Testing-copy.msg";
public MainWindow()
{
InitializeComponent();
if (File.Exists(WORKING_FILENAME))
{
File.Delete(WORKING_FILENAME);
}
}
private void HandleDrop(object sender, DragEventArgs e)
{
MessageBox.Show("Drop completed");
}
private void OpenTheFile(object sender, RoutedEventArgs e)
{
if (!File.Exists(ORIGINAL_FILENAME))
{
MessageBox.Show("File does not exist.");
}
else
{
// Make a copy so we can repeat the test multiple times
File.Copy(ORIGINAL_FILENAME, WORKING_FILENAME);
// Launch the default program for the email file
// (this should be Outlook -- haven't tested with other email clients)
Process myprocess = new Process();
myprocess.StartInfo.FileName = WORKING_FILENAME;
myprocess.Start();
}
}
private void DeleteTheFile(object sender, RoutedEventArgs e)
{
if (!File.Exists(WORKING_FILENAME))
{
MessageBox.Show("File does not exist.");
}
else
{
try
{
File.Delete(WORKING_FILENAME);
MessageBox.Show("File deleted successfully!");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
}
此示例取决于是否有一封名为Testing.msg
的电子邮件,其中包含附件。
重现问题的步骤是:
此时,由于电子邮件已关闭,我希望能够删除我的文件,因为它不应该被使用,但Outlook会为该文件保持句柄打开,并且不允许我删除它。我必须关闭Outlook或我的应用程序以释放该句柄。
如果我跳过第3步,那么拖动&amp;删除操作,我可以删除该文件。
我的问题是,是否有某种方法可以阻止此文件锁定或强制Outlook放弃锁定,以便我可以在拖动后与文件进行交互?
答案 0 :(得分:0)
您可以使用System.Diagnostics查看正在运行的进程并获取进程ID(pids)列表。调用process.start时,将正在运行的pid存储为类级变量。完成后,在与该pid相关的进程上调用kill()。
using System.Diagnostics
public static ProcessThread [] GetProcessThreads (int procID)
{
try
{
Process proc = Process.GetProcessById (procID);
ProcessThread [] threads = proc.Threads;
return threads;
}
catch ( Exception e)
{
Console.WriteLine (e.Message);
return null;
}
}
然后获取ID:
threadIDs[i] = threads[i].Id;
诀窍是确定你需要杀死哪个pid,因为会有很多Outlook运行实例。执行此操作的最佳方法是运行一个监视线程,该线程将调用该进程上的Kill()方法。