从我的应用程序打开的Outlook电子邮件中拖动附件时,如何防止文件锁定?

时间:2014-08-07 16:50:14

标签: .net outlook

我的应用程序存储所有类型的文件,并允许用户打开这些文件。我们只使用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的电子邮件,其中包含附件。

重现问题的步骤是:

  1. 确保Outlook已在运行
  2. 运行测试应用,然后点击&#34;打开文件&#34;按钮 - 这将打开电子邮件文件
  3. 将附件从电子邮件拖到标有&#34;此处删除文件的空间!&#34;
  4. 关闭电子邮件窗口
  5. 点击&#34;尝试删除文件&#34;按钮
  6. 此时,由于电子邮件已关闭,我希望能够删除我的文件,因为它不应该被使用,但Outlook会为该文件保持句柄打开,并且不允许我删除它。我必须关闭Outlook或我的应用程序以释放该句柄。

    如果我跳过第3步,那么拖动&amp;删除操作,我可以删除该文件。

    我的问题是,是否有某种方法可以阻止此文件锁定或强制Outlook放弃锁定,以便我可以在拖动后与文件进行交互?

1 个答案:

答案 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()方法。