Defrag API C # Wrappers

xiaoxiao2021-04-09  448

For My OWN AMUSEMENT, I DECIDED TO Wrap The Nt Defrag Apis in C #.

IT isn't Great, But ... I'll Give It The Classic Dev Guarantee of "It Works on My Machine". Http://www.thenetworkadministrator.com/top20.htm

The MSDN Documentation Uses Lots of Very Scary Words Like "IOCTL" and "Deviceiocontrol" and the such. Hopefully, I've Abstract Some of That Away ...

First, you can get a bitmap of the cluster usage on the device ...

Static Public BitArray GetVoluMemap (String DeviceName)

The you can get a map of a file - Virtual Clusters and Logical Clusters

static public Array GetFileMap (string path) Finally, you can move sections of a file around on a volume ... static public void MoveFile (string deviceName, string path, Int64 VCN, Int64 LCN, Int32 count) Here's the whole thing, nearly Guaranteed to Break your file system if used. :-) /// A set of simple c # wrappers over the nt defragmenter apis //////////////www.sysinternals.com/NTW2K/ Info / defrag.shtml // // msdn how-to // ms-help: //ms.msdnqtr.2004jul.1033/fileio/base/defragmenting_files.htm/ http://msdn.microsoft.com/library/ Default.asp? URL = / library / en-us / fileio / base / defragmenting_files.asp //// fsctl_get_volume_bitmap // http://msdn.microsoft.com/library/default.asp?url=/library/en- us / fileio / base / fsctl_get_volume_bitmap.asp //// interesting structures ... // FSCTL_MOVE_FILE // FSCTL_GET_RETRIEVAL_POINTERS // RETRIEVAL_POINTERS_BUFFER // FSCTL_GET_RETRIEVAL_POINTERS //// DeviceIoControl // http://msdn.microsoft.com/library/default .asp? url = / library / en-us / devio / base / deviceiocontr ol.asp // using System; using System.Diagnostics; using System.Collections; using System.Runtime.InteropServices; namespace defraglib {public class IOWrapper {// // CreateFile constants // const uint FILE_SHARE_READ = 0x00000001; const uint FILE_SHARE_WRITE = 0x00000002; const uint FILE_SHARE_DELETE = 0x00000004; const uint OPEN_EXISTING = 3; const uint GENERIC_READ = (0x80000000); const uint GENERIC_WRITE = (0x40000000); const uint FILE_FLAG_NO_BUFFERING = 0x20000000; const uint FILE_READ_ATTRIBUTES = (0x0080); const uint FILE_WRITE_ATTRIBUTES = 0x0100;

const uint ERROR_INSUFFICIENT_BUFFER = 122; [DllImport ( "kernel32.dll", SetLastError = true)] static extern IntPtr CreateFile (string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); [DllImport ( "kernel32.dll", SetLastError = true)] static extern int CloseHandle (IntPtr hObject); [DllImport ( "kernel32.dll", SetLastError = true)] static extern bool DeviceIoControl (IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize , [Out] IntPtr lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, IntPtr lpOverlapped); static private IntPtr OpenVolume (string DeviceName) {IntPtr hDevice; hDevice = CreateFile (@ "//./" DeviceName, Generic_Read | generic_write, file_share_write, intptr.zero, open_existing, 0, intptr.zero; if ((int) hdevice == -1) {throw new exception (Marshal.getlastwin32error (). TString ());} return hdevice;} static private intptr openfile (string path) {INTPTR HFILE; HFILE =

CreateFile (path, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);. If ((int) hFile == -1) {throw new Exception (Marshal.GetLastWin32Error () ToString () );} Return Hfile;} ///

/// Get Cluster Usage for a device /// /// USE "C: / // a bitarray for each cluster static public BitArray GetVolumeMap (string DeviceName) {IntPtr pAlloc = IntPtr.Zero; IntPtr hDevice = IntPtr.Zero; try {hDevice = OpenVolume (DeviceName); Int64 i64 = 0 Gchandle Handle = Gchaldle.alloc (i64, gchandletype. Pinned); IntPtr p = handle.AddrOfPinnedObject (); // alloc off more than enough for my machine // 64 megs == 67108864 bytes == 536870912 bits == cluster count // NTFS 4k clusters == 2147483648 k of storage = = 2097152 megs == 2048 gig disk storage uint q = 1024 * 1024 * 64; // 1024 BYTES == 1k * 1024 == 1 meg * 64 == 64 megs uint size = 0; Palloc = Marshal.allochglobal ((int) q); intptr pdest = pAlloc; bool fast =

DeviceIoControl (hDevice, FSConstants.FSCTL_GET_VOLUME_BITMAP, p, (uint) Marshal.SizeOf (i64), pDest, q, ref size, IntPtr.Zero); if (fResult!) {Throw new Exception (Marshal.GetLastWin32Error () ToString (. ));} handle.Free (); / * object returned was ... typedef struct {LARGE_INTEGER StartingLcn; LARGE_INTEGER BitmapSize; BYTE Buffer [1];} VOLUME_BITMAP_BUFFER, * PVOLUME_BITMAP_BUFFER; * / Int64 StartingLcn = (Int64) Marshal.PtrToStructure (PDEST, TYPEOF (INT64)); debug.assert (startinglcn == 0); pdest = (int 64) PDEST 8); int64 Bitmapsize = (int64) Marshal.PTRTRUCTURE (PDEST, TYPEOF (int64)) ; INT32 BYTESIZE = (INT); BYTESIZE ; // Round Up - Even with no remainder INTPTR BitMapbegin = (int 64) PDEST 8); Byte [] Bytearr = New Byte [bytesize]; Marshal .Copy (BitmapBegin, byteArr, 0, (Int32) byteSize); BitArray retVal = new BitArray (byteArr); retVal.Length = (int) BitmapSize; // truncate to exact cluster count return retVal;} finally {CloseHandle (hDevice) HDevice = INTPTR.ZERO; MARSHAL.FREEHGLOBAL (Palloc); Palloc = INTPTR.ZERO;

}}} ///

/// Returns a 2 * Number of extents array - //// /// File To Get The Map for EX: "C: / Windows/explorer.exe" /// An Array of [Virtual Cluster, Physical Cluster] static public array getfilemap (string path) {INTPTR hFile = IntPtr.Zero; IntPtr pAlloc = IntPtr.Zero; try {hFile = OpenFile (path); Int64 i64 = 0; GCHandle handle = GCHandle.Alloc (i64, GCHandleType.Pinned); IntPtr p = handle.AddrOfPinnedObject (); UINT Q = 1024 * 1024 * 64; // 1024 BYTES == 1k * 1024 == 1 meg * 64 == 64 megs uint size = 0; Palloc = Marshal.allochglobal (int) q); intPtr pdest = Palloc; Bool Fresult = Deviceiocontrol (Hfile, Fscon Stants.fsctl_get_retrieval_pointers, p, (uint) Marshal.SizeOf (i64), pdest, q, ref size, intptr.zero; if (! FRESULT) {throw new exception (). Tostring ());} Handle.Free (); / * returned back one of ... typedef struct retrieval_pointers_buffer {dWord extentcount; large_integer startingvcn; struct {large_integer nextvcn

LARGE_INTEGER Lcn;} Extents [1];} RETRIEVAL_POINTERS_BUFFER, * PRETRIEVAL_POINTERS_BUFFER; * / Int32 ExtentCount = (Int32) Marshal.PtrToStructure (pDest, typeof (Int32)); pDest = (IntPtr) ((Int64) pDest 4); Int64 Startingvcn = (int 64) Marshal.PTRTOStructure (PDEST, TYPEOF (INT64)); debug.assert (startingvcn == 0); pdest = (int 4) (INT64) PDEST 8); // NOW PDEST POINTS AT An Array of ARRAY OF Pairs of int64s. Array Retval = Array.createInstance (TypeOf (INT64), New INT [2] {EXTENTCOUNT, 2}); for (int i = 0; i /// input structure for use in movefile /// private struct movefiledata {public int 64 startingvcn; public int64 startinglcn; public int32 clustercount;} ///

///move a virtual cluster for a file to a logical cluster on disk, repeat for count clusters /// /// device to move on "C: /// File to Muck with "c: / windows/explorer.exe" /// Cluster Number in File to Move /// Cluster on disk to move to /// for how much clusters static public void file (String DeviceName, String path, Int64 VCN, Int64 LCN, Int32 count) {IntPtr hVol = IntPtr.Zero; IntPtr hFile = IntPtr.Zero; try {hVol = OpenVolume (deviceName); hFile = OpenFile (path); MoveFileData mfd = new MoveFileData (); Mfd.hfile = hfile; mfd.startingvcn = vcn; mfd.startinglcn = lcn; mfd.clustercount = count; gchandle handle = g CHandle.Alloc (mfd, GCHandleType.Pinned); IntPtr p = handle.AddrOfPinnedObject (); uint bufSize = (uint) Marshal.SizeOf (mfd); uint size = 0; bool fResult = DeviceIoControl (hVol, FSConstants.FSCTL_MOVE_FILE, p , BufSize, INTPTR.ZERO, // No Output Data from this fsctl 0, ref size, point, intel; handle.free ();

转载请注明原文地址:https://www.9cbs.com/read-133061.html

New Post(0)