Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从数据库创建临时文件,用相关程序打开它,然后删除它_C#_Database_Blob_Filestream - Fatal编程技术网

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

C# 从数据库创建临时文件,用相关程序打开它,然后删除它,c#,database,blob,filestream,C#,Database,Blob,Filestream,我正在编写一个windows窗体应用程序I C#,其中需要在客户端pc上安装的关联程序中向用户打开一个文档/文件(.doc、.pdf、.xlsx、.tiff等) 用户关闭显示程序后,应立即删除该文件 我尝试了几个创建和打开文件的选项,但还没有找到金蛋 public static void databaseFileRead(string file_name, byte[] file) { path = file_name; int file_size_int = file.Leng

我正在编写一个windows窗体应用程序I C#,其中需要在客户端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);
}
在上面的方法中,我在最后一行(
FileStream open=…
)得到一个IOException,指出“进程无法访问文件‘xxx’,因为它正被另一个进程使用”

在这个方法中,我还得到一个IOException,在最后一行(
file.Delete(@path);
)上指出“进程无法访问文件'xxx',因为它正被另一个进程使用”,这意味着该文件仍在使用中,这是正确的。似乎
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.Delete,我只需要在我的调试中使用它——也许把它放在那里是个好主意,因为如果有人在文件被删除之前退出应用程序,它会再次尝试创建它

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


是我用来解决你的p.WaitForExit问题的参考资料。我建议您在应用程序中的另一个线程上启动此操作,因为否则您的应用程序将在检查线程已退出时挂起(在windows中变为白色/灰色,并告诉您它没有响应)。如果您正在使用wpf,您可以做一些事情,例如使视觉效果无效,或者重新绘制GUI以便您仍然可以使用它,但这些都是有问题的,并且会消耗大量CPU。

好的,在评论之后,这里有一个可行的第二种方法:

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资源管理器中,如果您有admin,它不关心这个问题,这就是为什么您可以从那里删除它,但C#关心文件属性。我将该行更改为
File.SetAttributes(@path,attributes | FileAttributes.Temporary)现在可以工作了

是我用来解决你的p.WaitForExit问题的参考资料。我建议您在应用程序中的另一个线程上启动此操作,因为否则您的应用程序将在检查线程已退出时挂起(在windows中变为白色/灰色,并告诉您它没有响应)。如果你使用wpf,你可以做一些事情,比如使视觉效果无效,或者重新绘制GUI,这样你仍然可以使用它,但这些都是有问题的,并且会消耗大量CPU。

有几件事

首先,如果这是在winforms应用程序的主UI线程中运行的,则使用任一解决方案,您的应用程序都将变得无响应

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

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

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

有几件事

首先,如果这是在winforms应用程序的主UI线程中运行的,则使用任一解决方案,您的应用程序都将变得无响应

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

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


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

如果我在第一个方法中这样做,文件在打开之前会立即被删除,因为第一个方法中有
FileOption
,那么,在
create.Close()
之后的文件流中放入
FileOptions.DeleteOnClose
,从第一个文件中删除DeleteOnClose