我想用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的代码的引用。