从DB创建临时文件,使用关联程序打开它,然后删除它

时间:2013-03-20 00:38:55

标签: c# database blob filestream

我正在编写一个Windows表单应用程序i C#,我需要在安装在其上的相关程序中向用户打开文档/文件(.doc,.pdf,.xlsx,.tiff等)。客户端电脑。

用户关闭显示程序后,应立即删除该文件。

我已经尝试了几种创建和打开文件的选项,但还没有找到金蛋。

public static void databaseFileRead(string file_name, byte[] file)
{
    path = file_name;
    int file_size_int = file.Length;
    FileStream create = new FileStream(@path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read, file_size_int, FileOptions.DeleteOnClose);
    create.Write(file, 0, file_size_int);
    FileStream open = File.Open(@path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
}

在上面的方法中,我得到一个IOException,声明“进程无法访问文件'xxx',因为它正被另一个进程使用”在最后一行(FileStream open = ... )。

public static void databaseFileRead(string file_name, byte[] file)
{
    path = file_name;
    int file_size_int = file.Length;
    FileStream create = File.OpenWrite(@path);
    var attributes = File.GetAttributes(@path);
    File.SetAttributes(@path, attributes | FileAttributes.ReadOnly|FileAttributes.Temporary);
    create.Close();
    Process p = Process.Start(@path);
    p.WaitForExit();
    File.Delete(@path);
}

在这个方法中,我还得到一个IOException,声明“进程无法访问文件'xxx',因为它正被另一个进程使用”在最后一行({{1} })意味着该文件仍在使用中,这是正确的。 File.Delete(@path);似乎没有等待所有程序,例如的OpenOffice ...

是否可以在外部程序中打开/显示使用p.WaitForExit();创建的文件? 如果是这样,怎么样?

我确实喜欢这样的想法,即Windows不再使用该文件就会删除该文件。

重要的是文件自动从用户硬盘中消失,最好的选择是从流中读取和打开文件或相等。但就我所读到的情况而言,这是不可能的......

解决:

但是我不确定是否可以采用这种方法来捕获异常并再次调用FileOptions.DeleteOnClose方法,直到文件被释放...

closeIfReady

2 个答案:

答案 0 :(得分:3)

好的,在评论之后,这是一个有效的第二种方法:

void Method2(string file_name, byte[] file)
{
    var path = file_name;
    int file_size_int = file.Length;
    if (File.Exists(path))
    {
        File.Delete(path);
    }
    FileStream create = File.OpenWrite(path);
    var attributes = File.GetAttributes(path);
    File.SetAttributes(path, attributes | FileAttributes.Temporary);
    create.Close();
    Process p = Process.Start(path);

    while (!p.HasExited)  
    {
        Thread.Sleep(100);  
    }

    File.Delete(path);
}

你一开始并不严格需要if.File.Exists / File.Delete,我只需要它在我的调试中 - 但是,如果有人在之前退出应用程序,可能是个好主意。文件被删除它将尝试再次创建它。

此方法中的问题是: File.SetAttributes(@path, attributes | FileAttributes.ReadOnly|FileAttributes.Temporary);由于文件是以只读方式创建的,因此无法使用File.Delete将其删除。在Windows资源管理器中,如果您有管理员,它不关心这个,这就是为什么你可以从那里删除它,但C#确实关心文件属性。我将该行更改为File.SetAttributes(@path, attributes | FileAttributes.Temporary);,现在可以正常工作。

This question是我用于p.WaitForExit问题的引用。我建议在你的应用程序的另一个线程上启动它,否则你的应用程序将挂起,而它检查线程已退出(在Windows中变为白色/灰色并告诉你它没有响应)。如果您正在使用wpf,或者重新绘制GUI以便仍然可以使用它,那么您可以执行诸如使视觉效果无效之类的操作,但这些操作非常糟糕并且可能占用大量CPU。

答案 1 :(得分:0)

有几件事。

首先,如果这是在winforms应用程序的主UI线程中运行,那么使用任一解决方案都会使您的应用程序无响应。

其次,两种解决方案都依赖于从多个不同应用程序的优雅退出。这是有风险的。

如果外部进程无法正确清理文件句柄,那么您的解决方案将导致无限递归。我也会感到不舒服,取决于Process.HasExit,因为我已经看到很多关于这个属性可靠性的线索。

我建议使用相对于您的应用程序的临时目录,并在应用程序出口和启动时清理该目录(以防您自己的应用程序无法正常退出)。