2011-12-04 25 views
-1

我正在使用FileRead API。 我使用了Windows 7 x64,並且我的代碼工作正常。 現在我安裝了一個新的Windows 7 x86和VS2008 teamsuit以及.NET 2,3 + SP1 + SP2,3.5,3.5.1。 我跑我的代碼作爲管理員,但仍然遇到follwoing錯誤:使用FileRead API時出現AccessViolationException

AccessViolationException(Attempted to read or write protected memory. This is often an indication that other memory is corrupt.)

int nread = 0; 
uint handle; 
byte[] buff = new byte[1024]; 
string driveRoot = string.Concat("\\\\.\\", driveLetter); 
uint hRoot = CreateFile(driveRoot, 
       GENERIC_READ | GENERIC_WRITE, 
       FILE_SHARE_READ | FILE_SHARE_WRITE, 
       IntPtr.Zero, 
       OPEN_EXISTING, 
       FILE_ATTRIBUTE_NORMAL, 
       IntPtr.Zero); 
if (hRoot != -1) 
     handle = ReadFile(hRoot, buff, 1024, nread, new System.Threading.NativeOverlapped()); 
+1

你的句柄應該是IntPtr,但是在x86上不會有問題。儘管如此,x64應該是個問題。而且nread也作爲指針傳遞,你傳遞一個uint。還應該是一個IntPtr。 –

回答

1

雖然我沒有C#大師,在我看來,你是在調用ReadFile()有錯誤的參數。

第4個參數必須是一個指向一個整數的指針,該整數將接收讀取的字節數。您自己提供整數(nread),而不是其地址(&nread)。

除非你想異步文件I/O,否則ReadFile()的最後一個參數必須是NULL指針(或者只是0)。

請參閱this example on MSDN

+0

但它在Windows7 x64上正常工作! 爲什麼相同的代碼無法在Windows7 x86上正常工作? 有什麼問題? –

+0

nread可能會解決,因爲win32需要一個指針,並傳遞零int等同於NULL指針。 –

+0

我認爲重疊閱讀可能是一個問題。你絕對不想在這裏重疊。這可能導致緩衝區在釋放後很長時間內寫入緩衝區。 –

0

我懷疑你的代碼的主要問題是你要求重疊的I/O,但是提供一個當ReadFile返回時不再存在的緩衝區。它在一些系統上工作,而不是在其他系統上工作,因爲系統決定是否異步執行操作,並且可以選擇不在一個系統上執行異步並在另一個系統上選擇不同的方式。

我確定你不想重疊I/O,所以你應該簡單地通過NULL到最終參數ReadFile

另一方面,也許你的代碼在x64系統上根本沒有任何作用,並且從來沒有像AV那麼遠。您的句柄類型被錯誤地聲明爲32位整數。

您的代碼還有許多其他小問題。以下是糾正這些錯誤的代碼的編輯版本。 P/invoke簽名來自pinvoke.net。

[DllImport("kernel32.dll", SetLastError = true)] 
public static extern IntPtr CreateFile(
    string lpFileName, 
    uint dwDesiredAccess, 
    uint dwShareMode, 
    IntPtr SecurityAttributes, 
    uint dwCreationDisposition, 
    uint dwFlagsAndAttributes, 
    IntPtr hTemplateFile 
); 

[DllImport("kernel32.dll", SetLastError = true)] 
static extern bool ReadFile(
    IntPtr hFile, 
    [Out] byte[] lpBuffer, 
    uint nNumberOfBytesToRead, 
    out uint lpNumberOfBytesRead, 
    IntPtr lpOverlapped 
); 

static void Main(string[] args) 
{ 
    string physicalDrive = @"\\.\PhysicalDrive0"; 
    IntPtr hFile = CreateFile(
     physicalDrive, 
     GENERIC_READ | GENERIC_WRITE, 
     FILE_SHARE_READ | FILE_SHARE_WRITE, 
     IntPtr.Zero, 
     OPEN_EXISTING, 
     FILE_ATTRIBUTE_NORMAL, 
     IntPtr.Zero 
    ); 
    if (hFile.ToInt64() != INVALID_HANDLE_VALUE) 
    { 
     byte[] buff = new byte[1024]; 
     uint nread; 
     if (ReadFile(hFile, buff, (uint)buff.Length, out nread, IntPtr.Zero)) 
      Console.WriteLine("Read successful"); 
    } 
} 

總結錯誤,在你的代碼:

  • 不正確使用的32位整數來存儲手柄。
  • 您的P/invoke聲明ReadFile聲明lpNumberOfBytesRead不正確。
  • ReadFile不返回句柄,它返回一個表示函數調用成功的布爾值。
  • 使用您不想使用的重疊I/O,以及哪些無法與編組的byte[]緩衝區一起使用。
  • 您絕不能從託管代碼中調用GetLastError(您在代碼中顯示的代碼中是這樣做的)。請撥打Marshal.GetLastWin32Error。原因在該方法的documentation中解釋。
+0

tnx for edit.now我用SetFilePointerEx.i移動了hfile的偏移量,但它不正確地工作==> SetFilePointerEx(hRoot,MFTAddress,ref newaddress,0); int error = GetLastError();如果(hRoot!= IntPtr.Zero) handle = ReadFile(hRoot,buff,1024,ref nread,new System.Threading.NativeOverlapped());

+0

@Saeed我想我回答了你原來的問題。現在,您似乎在評論中提出了另一個問題。你沒有說它以什麼方式失敗。 「它不能正常工作」是我們無法幫助你的足夠信息。更重要的是,在註釋中提供代碼並不會有幫助,因爲它從來不會以可讀的方式進行格式化。問題可以編輯,新的問題可以被問到。爲了記錄,我的答案是否解決了您的原始問題? –

+0

現在,看看評論中的代碼,我可以看到兩個問題。永遠不要從託管代碼調用GetLastError。調用['Marshal.GetLastWin32Error'](http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.getlastwin32error.aspx)該文檔解釋了爲什麼這很重要。其次,請停止詢問重疊的I/O。你不需要它,它不能和P/invoke byte []緩衝區一起工作。第三,'ReadFile'不返回句柄,它返回一個'bool'。我已經在我的答案中向你展示了這一切。 –

相關問題