2011-11-21 9 views
5

自動的に削除される一時ファイルを作成しようとしています。私は、フラグのすべての可能な組み合わせを試してみたが、私はいつも「プロセスを取得すると思います同じプロセス内の同じファイルに2つのFileStreamを作成します

stream = new FileStream(
      tmpFilePath, 
      FileMode.Open, 
      FileAccess.Read, 
      FileShare.Read); 

stream = new FileStream(
      tmpFilePath, 
      FileMode.OpenOrCreate, 
      FileAccess.ReadWrite, 
      FileShare.ReadWrite, 
      4096, 
      FileOptions.DeleteOnClose|FileOptions.RandomAccess 
      ); 

このファイルには、FileStreamをを作成するサードパーティのAPIで使用されます他のプロセスで使用されているため、ファイル 'XXX'にアクセスできません... "

何か間違っていますか?周りに道がありますか?

+0

サードパーティのライブラリにファイルストリームを共有できませんか? –

+0

最初に一時ファイルを作成し、ストリームを閉じます。その後、サードパーティのAPIがアクセスできるようになります。作業が終了したら、一時ファイルを削除します。必要に応じて、同期を使用してください。 – kol

+0

他のプロセスで 'FileAccess.Read、FileShare.Read'を使うことはできません。' FileAccess.ReadWrite、FileShare.ReadWrite'を試してみてください。 – Cipi

答えて

0

問題は、あなたがまだあなたが開いて作成した最初のストリームを持っているということです。あなたはファイルを作成し、それを解放して(ストリームを閉じて)、サードパーティのAPIに作業をさせてからファイルを削除する必要があります。 IDispoableであるクラスにこれをすべてラップすることは素晴らしい解決策かもしれません。コンストラクタでファイルを作成して解放し、メソッドを第三者の作業をラップし、disposeメソッドで削除します。

+0

ストリームに問題があり、それに気づいていません。 – Cipi

+0

@Cipi ???私は知っている、私はファイルの内容について何も言わなかった。 –

+0

** FileOptions.DeleteOnClose **フラグでストリームを作成したため、ストリームを閉じることができません。このフラグを使用すると、プロセスがクラッシュしてもファイルが削除されます。ストリームを閉じると、ファイルが削除されます。それで、APIが仕事をしてからストリームを閉じるまで、それを開いたままにしておきたいのです。 –

2

ドキュメントによれば、はい。

http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx

抜粋:

読むには:読書のためのファイルのその後の開放を可能にします。このフラグが指定されていない場合、ファイルを閉じるまで、読み取りのためにファイルを開く要求(このプロセスでまたはまたは他のプロセス)が失敗します。ただし、このフラグを指定しても、ファイルにアクセスするにはさらに権限が必要な場合があります。

0

あなたは3サードパーティのAPIに既存のストリームを渡すか、あなただけしたい場合は3-サードパーティAPI用の専用モードを読み取ることができますがStreamReaderインスタンスを渡す

using (var stream = new FileStream("trace.txt", FileMode.OpenOrCreate,FileAccess.ReadWrite)) 
    { 
     using (var anotherStream = new StreamReader(stream)) 
     { 
      //magic here 
     } 
    } 
2

私はまったく同じユースケースを持っていると遭遇同じ問題。私がしようとしているのは、両方のストリームに対して(FileShare.ReadWrite | FileShare.Delete)を使用することです。

+0

ケンは正しい道にあります。 1つのFileStreamが書き込み用に開かれ、FileShare.Readが指定されている場合は、2番目のFileStreamが読み込み用に開かれ、FileShare.ReadWriteを指定してファイルストリーム(「FileStream」など)と共有できるようにする必要があります。 –

0

この呼び出しシーケンスは、サードパーティのAPIがFileShare.ReadWriteを使用している場合、または使用している場合にFileAccess.Readを使用している場合にのみ機能します。

他の人も読み書きを開くことができるように、読み書きを開いています。 サードパーティのコードは、他のユーザーが読み取り専用で開くことを許可しながら、読み取り専用でオープンしようとしています。あなたはまだそれを読み書き可能に開いているので、これは失敗します。

あなたの代わりに次のパターンを採用する必要があります、あなたは、サードパーティのコードを変更することはできませんと仮定すると:あなたが現在いるよう

  1. はなく、DeleteOnCloseフラグなしで、ファイルを開きます。
  2. 他のコードを読む必要があるコンテンツを書く。
  3. ファイルを閉じます。
  4. オプションで、FileAccess.Read(場合によってはDeleteOnClose)で再度開きます。
  5. サードパーティのコードを呼び出します。
  6. 他の読書をしていますが、書いていません。私の経験で
0

FileOptions.DeleteOnCloseで開かFileStreamFileShare値にかかわらず、別のFileStreamへのファイルパスを渡すことで開くことができません。

DuplicateHandleすべてのコードを所有している場合は、異なるプロセスからでもDeleteOnCloseファイルを複数回開くことができます。

.NET 4.5.1のコード例です。

using System; 
using System.Diagnostics; 
using System.IO; 
using System.Runtime.InteropServices; 
using System.Text; 
using System.Windows.Forms; 
using Microsoft.Win32.SafeHandles; 

namespace Example 
{ 
    public static class DuplicatedHandleExample 
    { 
    [DllImport("kernel32.dll")] 
    private static extern bool DuplicateHandle(
     SafeFileHandle hSourceProcessHandle, 
     IntPtr hSourceHandle, 
     SafeFileHandle hTargetProcessHandle, 
     out SafeFileHandle lpTargetHandle, 
     UInt32 dwDesiredAccess, 
     bool bInheritHandle, 
     UInt32 dwOptions); 

    [DllImport("kernel32.dll")] 
    private static extern SafeFileHandle OpenProcess(
     UInt32 dwDesiredAccess, 
     bool bInheritHandle, 
     int dwProcessId); 

    private const UInt32 PROCESS_DUP_HANDLE = 0x0040; 

    private const UInt32 DUPLICATE_SAME_ACCESS = 0x0002; 

    public static void CreateFileInProcessA() 
    { 
     try 
     { 
     // open new temp file with FileOptions.DeleteOnClose 
     string tempFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("D")); 
     using (FileStream fs = new FileStream(tempFilePath, FileMode.CreateNew, 
      FileAccess.ReadWrite, FileShare.Read | FileShare.Write | FileShare.Delete, 
      4096, FileOptions.DeleteOnClose)) 
     { 
      // put a message in the temp file 
      fs.Write(new[] { (byte)'h', (byte)'i', (byte)'!' }, 0, 3); 
      fs.Flush(); 

      // put our process ID and file handle on clipboard 
      string data = string.Join(",", 
      Process.GetCurrentProcess().Id.ToString(), 
      fs.SafeFileHandle.DangerousGetHandle().ToString()); 

      Clipboard.SetData(DataFormats.UnicodeText, data); 

      // show messagebox (while holding file open!) and wait for user to click OK 
      MessageBox.Show("Temp File opened. Process ID and File Handle copied to clipboard. Click OK to close temp file."); 
     } 
     } 
     catch (Exception ex) 
     { 
     MessageBox.Show(ex.ToString()); 
     } 
    } 

    public static void OpenFileInProcessB() 
    { 
     try 
     { 
     // get process ID and file handle from clipboard 
     string data = (string)Clipboard.GetData(DataFormats.UnicodeText); 
     string[] dataParts = data.Split(','); 
     int sourceProcessId = int.Parse(dataParts[0]); 
     IntPtr sourceFileHandle = new IntPtr(Int64.Parse(dataParts[1])); 

     // get handle to target process 
     using (SafeFileHandle sourceProcessHandle = 
      OpenProcess(PROCESS_DUP_HANDLE, false, sourceProcessId)) 
     { 
      // get handle to our process 
      using (SafeFileHandle destinationProcessHandle = 
      OpenProcess(PROCESS_DUP_HANDLE, false, Process.GetCurrentProcess().Id)) 
      { 
      // duplicate handle into our process 
      SafeFileHandle destinationFileHandle; 
      DuplicateHandle(sourceProcessHandle, sourceFileHandle, 
       destinationProcessHandle, out destinationFileHandle, 
       0, false, DUPLICATE_SAME_ACCESS); 

      // get a FileStream wrapper around it 
      using (FileStream fs = new FileStream(destinationFileHandle, FileAccess.ReadWrite, 4096)) 
      { 
       // read file contents 
       fs.Position = 0; 
       byte[] buffer = new byte[100]; 
       int numBytes = fs.Read(buffer, 0, 100); 
       string message = Encoding.ASCII.GetString(buffer, 0, numBytes); 

       // show messagebox (while holding file open!) and wait for user to click OK 
       MessageBox.Show("Found this message in file: " + message + Environment.NewLine + 
       "Click OK to close temp file"); 
      } 
      } 
     } 
     } 
     catch (Exception ex) 
     { 
     MessageBox.Show(ex.ToString()); 
     } 
    } 
    } 
} 
関連する問題