DeviceIoControl与FSCTL_SET_ZERO_DATA返回ERROR_INVALID_PARAMETER

我想用C#中的FSCTL_SET_ZERO_DATA控制代码使用DeviceIoControl

我创build了文件C:\tmp\test.txt并在里面放置了文本“aaaa”。

我跑的代码,我收到错误号码:87
根据MSDN :“参数不正确。”

在这里输入图像描述

我认为这个问题是因为我没有任何数据发送input缓冲区( DeviceIoControl参数编号3)。

DeviceIoControl返回false
我怎么能插入有效的参数到DeviceIoControl FSCTL_SET_ZERO_DATA这将使其返回true

 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { class Program2 { [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)] static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned, IntPtr lpOverlapped); [Flags] public enum EMethod : uint { Buffered = 0, InDirect = 1, OutDirect = 2, Neither = 3 } [Flags] public enum EFileDevice : uint { FileSystem = 0x00000009 } [Flags] public enum EIOControlCode : uint { FsctlSetZeroData = (EFileDevice.FileSystem << 16) | (50 << 2) | EMethod.Buffered | (FileAccess.Write << 14), } [StructLayout(LayoutKind.Sequential)] struct FILE_ZERO_DATA_INFORMATION { public FILE_ZERO_DATA_INFORMATION(long offset, long count) { FileOffset = offset; BeyondFinalZero = offset + count; } public long FileOffset; public long BeyondFinalZero; } [DllImport("kernel32.dll")] public static extern uint GetLastError(); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CreateFile( [MarshalAs(UnmanagedType.LPTStr)] string filename, [MarshalAs(UnmanagedType.U4)] FileAccess access, [MarshalAs(UnmanagedType.U4)] FileShare share, IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, uint flagsAndAttributes, IntPtr templateFile); static void Main(string[] args) { IntPtr handle = CreateFile(@"C:\tmp\test.txt", FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, (int)FileAttributes.Normal, IntPtr.Zero); long length = 2; FILE_ZERO_DATA_INFORMATION data = new FILE_ZERO_DATA_INFORMATION(0, length); uint structSize = (uint)Marshal.SizeOf(data); IntPtr pBuffer = Marshal.AllocHGlobal((int)structSize); uint bytesReturned = 0; bool succeed = DeviceIoControl(handle, (uint)EIOControlCode.FsctlSetZeroData, pBuffer, 5, IntPtr.Zero, 5, out bytesReturned, IntPtr.Zero); // bool succeed = DeviceIoControl(handle, (uint)EIOControlCode.FsctlSetZeroData, IntPtr.Zero, 0, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); if (succeed) { Console.WriteLine("Works fine"); } else { uint err = GetLastError(); Console.WriteLine("Error number: {0}", err); } } } } 

感谢@Aybe。

解决方法是:

 uint pBufferSize = 16; Marshal.StructureToPtr(data, pBuffer, false); bool succeed = DeviceIoControl(handle, (uint)EIOControlCode.FsctlSetZeroData, pBuffer, pBufferSize, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero); 
  • 添加Marshal.StructureToPtr(data, pBuffer, false);非常重要Marshal.StructureToPtr(data, pBuffer, false);

如果你不添加它,有时函数会返回true,有时会返回false。

这是一个对C#也使用FSCTL的代码的引用。