Avatar billede schubert1 Nybegynder
11. juni 2009 - 18:46 Der er 18 kommentarer og
1 løsning

Find clustre på harddisken i C#

Hej eksperter!

Jeg vil gerne lave et program der kan fortælle mig hvor store og hvor mange, clustre der er på mine harrdiske.
Hvordan gør man det?
På forhånd tak :)
Avatar billede Spotgun Seniormester
11. juni 2009 - 21:22 #1
Du burde kunne finde det hele via WMI. Her er et eksempel på clusterstørrelsen:

using System.Management

            ObjectQuery query = new ObjectQuery("SELECT BlockSize, DriveLetter FROM Win32_Volume");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
            ManagementObjectCollection collection = searcher.Get();
            foreach (ManagementObject obj in collection)
            {
                Console.WriteLine("BlockSize of {0} is: {1}", obj["DriveLetter"], obj["BlockSize"]);
            }

Det skulle nok være muligt at finde noget brugbart information om harddisken under Win32_DiskPartition, Win32_LogicalDisk, Win32_DiskDrive, Win32_Volume og lignende.

Du kan se mere om de forskellige Win32 klasser her:
http://msdn.microsoft.com/en-us/library/aa394084(VS.85).aspx
Avatar billede Spotgun Seniormester
11. juni 2009 - 21:48 #2
Hvis du holder dig til Win32_Volume klassen, så kan du regne det hele ud ved lidt simpel matematik:

BlockSize = Cluster størrelse
Capacity = Total plads på disk
FreeSpace = Ledig plads på disk
Alle tre angivelser er i bytes.

Capacity / BlockSize = Total antal clusters
FreeSpace / BlockSize = Antal ledige clusters

Det er i øvrigt også cluster størrelsen der spiller ind, hvis du vælger egenskaber for en fil på din harddisk, og ser to forskellige størrelsesangivelser i "størrelse" og "diskforbrug".
Den første er filens reelle størrelse, og den anden er hvor meget plads den egentligt optager på din disk. Hvis du dividerer begge tal med cluster størrelsen, kan du se at "størrelse" ofte ikke går op i clusterstørrelsen, mens "diskforbrug" gør.
Avatar billede schubert1 Nybegynder
11. juni 2009 - 21:47 #3
Ah jeg kan se fremgangs måden :D Super tak!
Dog får jeg en exception når jeg prøver at køre ovenstående. Når den når ned til foreach smider den en "Invalid class" exception?
Kan du afmystificere det? :P
Avatar billede Spotgun Seniormester
11. juni 2009 - 21:50 #4
Mit eksempel kører fint her. Har du huske at inkludere en reference til System.Management?
Avatar billede schubert1 Nybegynder
11. juni 2009 - 21:53 #5
Ja jeg bruer resharper, så den husker det meste for mig :)... Men jeg har smidt det hele ind i en try-catch, det er det eneste der er til forskel fra dit til mit?
Avatar billede Spotgun Seniormester
11. juni 2009 - 21:56 #6
Check for tastefejl i din query så, det kan ofte give forkerte en Invalid Class fejl.
Avatar billede Spotgun Seniormester
11. juni 2009 - 21:58 #7
Det gik vist lidt for stærkt :)
Men check for tastefejl i din WMI query - det fanger resharper nok ikke!
Avatar billede schubert1 Nybegynder
11. juni 2009 - 21:58 #8
Det er copy/pastet ind fra din post, så jeg ved ikke om det her er forkert?
"SELECT BlockSize, DriveLetter FROM Win32_Volume"
Avatar billede Spotgun Seniormester
11. juni 2009 - 22:01 #9
hmm... mystisk. Hvilket OS kører du?
Avatar billede schubert1 Nybegynder
11. juni 2009 - 22:02 #10
Windows XP SP3 og med 3 NTFS drev i, har godt nok Daemon tools kørende, men det tæller ved ikke med som et drev i den her sammenhæng?
Avatar billede schubert1 Nybegynder
11. juni 2009 - 22:04 #11
det her er hvad der står i min kode:

using System;
using System.Management;

namespace HDTests
{
    class HDTests
    {
        static void Main()
        {
            try
            {
                ObjectQuery query = new ObjectQuery("SELECT BlockSize, DriveLetter FROM Win32_Volume");
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
                ManagementObjectCollection collection = searcher.Get();
                foreach (ManagementObject obj in collection)
                {
                    Console.WriteLine("BlockSize of {0} is: {1}", obj["DriveLetter"], obj["BlockSize"]);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message); 
            }
        }
    }
}
Avatar billede Spotgun Seniormester
11. juni 2009 - 22:09 #12
Beats me, din kodestump virker fint her.

Daemon tools er underordnet - jeg har det også her, uden problemer. Har prøvet at target både .Net 3.5 og 2.0 - det gør heller ingen forskel. Alt virker her. Kører selv Vista SP1 x64, men det burde være underordnet...
Avatar billede schubert1 Nybegynder
11. juni 2009 - 22:13 #13
Hehe det ser ud til at microsoft heller ikke helt selv er med på hvad der sker med denne fejl.
http://social.microsoft.com/Forums/en-US/whssoftware/thread/ef9c7227-022f-4a4d-b6be-c8f1cc0042d5
Avatar billede Spotgun Seniormester
11. juni 2009 - 22:17 #14
Heheh, du har i hvert fald metoderne til at finde de informationer du skal bruge, så håber jeg du får løst dit problem på anden vis. Det er jeg vist ikke meget behjælpelig med, hvis selv Microsoft giver op :D
Avatar billede schubert1 Nybegynder
11. juni 2009 - 22:22 #15
Haha nej det bliver lidt svært :P nå men så må jeg prøve det på min bærbar istedet. Tak for hjælpen :)
Avatar billede arne_v Ekspert
12. juni 2009 - 01:01 #16
Docs for Win32_Volume http://msdn.microsoft.com/en-us/library/aa394515.aspx siger klart og tydeligt:

Windows XP and earlier:  This class is not available.
Avatar billede Spotgun Seniormester
12. juni 2009 - 08:43 #17
Ah, makes sense then. Den havde jeg lige misset :(
Avatar billede schubert1 Nybegynder
12. juni 2009 - 11:23 #18
Så kan jeg vel benytte mig af Win32_DiskDrive? Eller Win32_DiskPartition?
Avatar billede arne_v Ekspert
12. juni 2009 - 20:20 #19
Prøv den her kode:

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace E
{
   
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct NTFS_VOLUME_DATA_BUFFER
    {
        public long VolumeSerialNumber;
        public long NumberSectors;
        public long TotalClusters;
        public long FreeClusters;
        public long TotalReserved;
        public uint BytesPerSector;
        public uint BytesPerCluster;
        public uint BytesPerFileRecordSegment;
        public uint ClustersPerFileRecordSegment;
        public long MftValidDataLength;
        public long MftStartLcn;
        public long Mft2StartLcn;
        public long MftZoneStart;
        public long MftZoneEnd;
    }
    public class Program
    {
        public const int FSCTL_GET_NTFS_VOLUME_DATA = 589924;
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr CreateFile(
            string fileName,
            [MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
            [MarshalAs(UnmanagedType.U4)] FileShare fileShare,
            IntPtr securityAttributes,
            [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
            int flags,
            IntPtr template);
        [DllImport("kernel32.dll", SetLastError=true)]
        static extern bool CloseHandle(IntPtr hHandle);
        [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
        public static extern bool DeviceIoControl(
            IntPtr hDevice,
            uint dwIoControlCode,
            IntPtr lpInBuffer,
            int nInBufferSize,
            out NTFS_VOLUME_DATA_BUFFER lpOutBuffer,
            int nOutBufferSize,
            out int pBytesReturned,
            IntPtr lpOverlapped);
        public static void Main(string[] args)
        {
            NTFS_VOLUME_DATA_BUFFER data = new NTFS_VOLUME_DATA_BUFFER();
            int datalen;
            IntPtr h = CreateFile(@"\\.\C:", FileAccess.Read, FileShare.Write, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
            if(!DeviceIoControl(h, FSCTL_GET_NTFS_VOLUME_DATA, IntPtr.Zero, 0, out data, Marshal.SizeOf(data), out datalen, IntPtr.Zero))
            {
                throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
            }
            CloseHandle(h);
            Console.WriteLine(data.BytesPerCluster);
            Console.ReadKey();
        }
    }
}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester