2013-03-20 23 views
0

我正在寫一個Windows窗體應用程序我C#,在那裏我需要打開一個文檔/文件(.doc,.pdf,.xlsx, .tiff等)在安裝在客戶端PC上的相關程序中發送給用戶。從數據庫創建臨時文件,打開它的關聯程序,然後刪除它

用戶關閉顯示程序後應立即刪除該文件。

我已經嘗試過幾種創建和打開文件的選項,但還沒有找到金蛋。

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); 
     } 
    } 

回答

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。

+0

如果我在第一個方法中這樣做,在打開文件之前立即刪除文件,因爲'FileOption' – 2013-03-20 00:52:41

+0

在第一個方法中,在'create'後面的FileStream中放入'FileOptions.DeleteOnClose'。 Close()',從第一個FileStream中刪除DeleteOnClose。這樣當你關閉進程時,它應該刪除文件。 – uNople 2013-03-20 01:07:44

+0

'File.Open'不會將'FileOption'作爲參數,並且我看不到如何使用'new FileStream'顯示文件。 – 2013-03-20 07:11:57

0

一些事情。

首先,如果這是在winforms應用程序的主UI線程中運行,那麼您的應用程序將無法使用任一解決方案進行響應。

其次,兩種解決方案都依賴於幾種不同應用程序的優雅退出。這是有風險的。

如果外部進程無法正確清理文件句柄,那麼您的解決方案將導致無限遞歸。根據Process.HasExited,我也會感到不舒服,因爲我已經看到有關此屬性的可靠性的許多線索。

我建議使用相對於您的應用程序的臨時目錄,並在應用程序退出和啓動時清理該目錄(以防萬一您的應用程序無法正常退出)。

+0

感謝您的意見。當我打開文件時,我已經創建了一個單獨的線程。 – 2013-04-15 02:47:24

相關問題