2011-11-21 32 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 
      ); 

该文件将由第三方API,它还将创建一个FileStream使用不能访问文件'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,第三方阿比通过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

肯是在正确的轨道上。如果打开一个FileStream进行写入并指定FileShare.Read,则打开第二个FileStream进行读取,然后必须指定FileShare.ReadWrite以允许与“写入”文件流(如第一个FileStream)共享。 –

0

仅当第三方API使用FileShare.ReadWrite或您的公开使用FileAccess.Read时,此调用序列才可用。

您正在打开它的读/写,同时允许其他人也打开它的读/写。 第三方代码试图以只读方式打开它,同时允许其他人也打开它,但只能以只读方式打开它。由于您仍然可以读写,因此失败。

假如你不能改变的第三方代码,您将需要采取以下方式代替:

  1. 打开为您当前所在的文件,但没有DeleteOnClose标志。
  2. 编写任何需要阅读其他代码的内容。
  3. 关闭文件。(可能为DeleteOnClose)。
  4. 调用第三方代码。
  5. 做任何你想要的任何其他阅读(但不写)。
0

根据我的经验,与FileOptions.DeleteOnClose开了FileStream无法通过将文件路径到另一个FileStream无论FileShare价值被打开。

当您拥有所有代码(显然不是您的情况,对不起)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()); 
     } 
    } 
    } 
} 
相关问题