C# 从数据库创建临时文件,用相关程序打开它,然后删除它
我正在编写一个windows窗体应用程序I C#,其中需要在客户端pc上安装的关联程序中向用户打开一个文档/文件(.doc、.pdf、.xlsx、.tiff等) 用户关闭显示程序后,应立即删除该文件 我尝试了几个创建和打开文件的选项,但还没有找到金蛋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
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