从数据库创建临时文件,用相关程序打开,然后删除

本文关键字:程序 删除 然后 数据库 创建 临时文件 | 更新日期: 2023-09-27 18:05:02

我正在用c#编写一个windows窗体应用程序,我需要在客户端pc上安装的相关程序中向用户打开文档/文件(.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',因为它正在被另一个进程使用"在最后一行(File.Delete(@path);)意味着该文件仍在使用中,这是正确的。p.WaitForExit();似乎没有等待所有程序,例如:OpenOffice…

是否可以在外部程序中打开/显示FileOptions.DeleteOnClose创建的文件?如果有,怎么做?

我确实喜欢这个想法,当文件不再使用时,Windows就会删除文件。

文件自动从用户硬盘中消失是很重要的,最好的选择是从流或相等的流中读取和打开文件。但据我所知,这是不可能的……

解决:

然而,我不确定这是否是一个探测器的方式来捕捉异常,并再次调用closeIfReady方法,直到文件被释放…

   public static void databaseFileRead(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);
        create.Write(file, 0, file_size_int);
        var attributes = File.GetAttributes(path);
        File.SetAttributes(path, attributes | FileAttributes.Temporary);
        create.Close();
        Process p = Process.Start(path);
        while (!p.HasExited)
        {
            Thread.Sleep(500);
        }
        closeIfReady(path);
    }
    static void closeIfReady(string path)
    {
        try
        { File.Delete(@path); }
        catch
        {
            Thread.Sleep(1000);
            closeIfReady(path);
        }
    }

从数据库创建临时文件,用相关程序打开,然后删除

好的,在注释之后,这是第二个有效的方法:

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。在开始时删除,我只是需要它在我的调试-可能是一个好主意,把它留在那里,但是,因为如果有人退出应用程序之前,文件被删除,它会尝试重新创建它。

然而,这个方法中的问题行是:File.SetAttributes(@path, attributes | FileAttributes.ReadOnly|FileAttributes.Temporary);因为文件是以只读方式创建的,所以不能用file . delete删除它。在windows资源管理器中,它不关心这个,如果你有admin,这就是为什么你可以从那里删除它,但c#关心文件属性。我把这行改为File.SetAttributes(@path, attributes | FileAttributes.Temporary);,现在它工作了。

这个问题是我用来解决你的p.w itforexit问题的参考。我建议在你的应用程序的不同线程上开始这个,否则你的应用程序会挂起,而它正在检查线程已经退出(在窗口变成白色/灰色,并告诉你它没有响应)。如果你正在使用wpf,你可以做一些事情,比如无效的视觉效果,或者重画你的GUI,这样你仍然可以使用它,但这些都是hack,可以消耗大量的CPU。

几件事

首先,如果这是在winforms应用程序的主UI线程中运行,那么无论使用哪种解决方案,你的应用程序都会变得无响应。

第二,两种解决方案都依赖于几个不同应用程序的优雅退出。这很冒险。

如果外部进程不能正确地清理文件句柄,您的解决方案将导致无限递归。我也会对依赖Process感到不舒服。我已经看到了很多关于这个属性的可靠性的线程。

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