我的应用程序存储所有类型的文件,并允许用户打开这些文件。我们只使用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为该文件保持一个打开的句柄,不允许我删除它。我必须关闭Outlook或我的应用程序来释放该句柄。
如果我跳过步骤3,拖动&删除操作,我可以删除文件。
我的问题是,如果有一些方法来防止这个文件锁定或强制Outlook放弃锁定,以便我可以与拖拽后的文件进行交互?
您可以使用System。用于查看正在运行的进程并获得进程ID (pid)列表的诊断。当你调用process。首先,将正在运行的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()方法。