Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > GetDiskFreeSpaceEx


Автор: rAccOOn 7.10.2009, 09:22
Здраствуйте, вот код
Код

void CUhygDlg::OnButton1() 
{
    char mas[20];
    unsigned long Available, Total, Free;
    list.ResetContent();
    char dd[4];
    DWORD dr = GetLogicalDrives();
    for( int i = 0; i < 26; i++ )
    {
        int n = ((dr>>i)&0x00000001);
        if( n == 1 ) 
        {
            dd[0] =  char(65+i); dd[1] = ':'; dd[2] = '\\'; dd[3] = 0;
            list.AddString(dd);    
        }
    }    
    list_a.ResetContent();
    int d;
    UpdateData(true);
        d = GetDriveType(ed); // ed- эдит в который вводится название раздела о котором нужна инфа
    if( d == DRIVE_UNKNOWN ) list_a.AddString(" Íåèçâåñòíûé");
    if( d == DRIVE_NO_ROOT_DIR )list_a.AddString(" Íåèçâåñòíûé");
    if( d == DRIVE_REMOVABLE )list_a.AddString( " Cìåííûé");
    if( d == DRIVE_FIXED ) list_a.AddString(" Ëîêàëüíûé");
    if( d == DRIVE_REMOTE ) list_a.AddString(" Ñåòåâîé");
    if( d == DRIVE_CDROM ) list_a.AddString(" CD-ROM");
    if( d == DRIVE_RAMDISK ) list_a.AddString(" Âèðòóàëüíûé â ÎÇÓ");
    UpdateData(false);


        if(GetDiskFreeSpaceEx("d:\\", (PULARGE_INTEGER)&Available,(PULARGE_INTEGER)&Total,(PULARGE_INTEGER)&Free))
        {
                ed1=itoa(Total, mas, 10);
                ed2=itoa(Free, mas, 10);
                ed3=itoa(Available, mas, 10);
                UpdateData(false);
        }
}


Вообщем при нажатии на кнопку, програма выводит список разделов, при попытке получить обьем памяти вообе, обьема свободной и обьема занятой выводит какие то не понятные числа.
http://www.picamatic.com/view/5431326_Безымянный/
Подскажите кто может где я ошибаюсь и как это исправить 

Автор: jonie 7.10.2009, 09:31
http://msdn.microsoft.com/en-us/library/aa383742%28VS.85%29.aspx
ULARGE_INTEGER это НЕ unsigned long тип.
sizeof(long) = 4 (на x86 , впрочем и на x64 в видении майкрософта тоже 4), у вас странно что вообще не вылетает все нафиг, т.к. вы перещаписываете буфер.

Автор: xvr 7.10.2009, 12:22
Кстати, ваш GetDiskFreeSpaceEx всегда возвращает свободное место на диске D: (см его первый параметр). Это так и было задумано?

Автор: rAccOOn 7.10.2009, 17:48
Цитата(xvr @ 7.10.2009,  12:22)
Кстати, ваш GetDiskFreeSpaceEx всегда возвращает свободное место на диске D: (см его первый параметр). Это так и было задумано?

Да, я хотел выводить пока тока диск D, п потом когда уже пойму как это делать то можна будет и поменять.

Добавлено @ 18:02
Код

void CUhygDlg::OnButton1() 
{
    char mas[10];
    __int64 Available;
    __int64 Total;
    __int64 Free;
    list.ResetContent();
    char dd[4];
    DWORD dr = GetLogicalDrives();
    for( int i = 0; i < 26; i++ )
    {
        int n = ((dr>>i)&0x00000001);
        if( n == 1 ) 
        {
            dd[0] =  char(65+i); dd[1] = ':'; dd[2] = '\\'; dd[3] = 0;
            list.AddString(dd);    
        }
    }    
    list_a.ResetContent();
    int d;
    UpdateData(true);
        d = GetDriveType(ed);
    if( d == DRIVE_UNKNOWN ) list_a.AddString("Oei: Iaecaanoiue");
    if( d == DRIVE_NO_ROOT_DIR )list_a.AddString("Oei: Iaecaanoiue");
    if( d == DRIVE_REMOVABLE )list_a.AddString( "Oei: Ciaiiue");
    if( d == DRIVE_FIXED ) list_a.AddString("Oei: Eieaeuiue");
    if( d == DRIVE_REMOTE ) list_a.AddString("Oei: Naoaaie");
    if( d == DRIVE_CDROM ) list_a.AddString("Oei: CD-ROM");
    if( d == DRIVE_RAMDISK ) list_a.AddString("Oei: Ae?ooaeuiue a ICO");
    UpdateData(false);


        if(GetDiskFreeSpaceEx("e:\\", (PULARGE_INTEGER)&Available,(PULARGE_INTEGER)&Total,(PULARGE_INTEGER)&Free))
        {
                ed1=itoa(Total, mas, 10);
                ed2=itoa(Free, mas, 10);
                ed3=itoa(Available, mas, 10);
                UpdateData(false);
        }

}



Теперь же при выводе получаються вот такие значения
http://www.picamatic.com/view/5435891_Безымянный/

Хотя у меня на диске D: 476937 метров общий обьем. Возможно я не так преобразовую полученые данные, но если убрать преобразование полностью то вылазиет 3 ошибки о том что при переводе могут потеряться данные. и у меня появилась мысль о том что может надо переводить не в char а в какой то другой тип, или сделать надо что то еще или наоборот что то другое. 

PS: спасибо за разяснение на счет типов даных

Автор: jonie 7.10.2009, 18:24
Цитата

PS: спасибо за разяснение на счет типов даных
а почему не применили? И тип __int64 это НЕ тоже самое что ULARGE_INTEGER (хотя с натягом иожно сказать что это unsigned __int64).

более того, itoa НЕ работает с __int64 данными, он преобразует ваш int64 к int и получает данные (с потерями, что немудрено)...

Автор: rAccOOn 7.10.2009, 19:56
я просто не понял как его правильно использовать, и как его можна всунуть. Еси можете и вам не сложно напишите пример на одной из трех переменых. заранее спс 

Автор: dumb 8.10.2009, 08:59
Код

  ULARGE_INTEGER Available, Total, Free;
  TCHAR ed1[32], ed2[32], ed3[32];
  if(GetDiskFreeSpaceEx(_T("e:\\"), &Available,&Total,&Free))
  {
    _stprintf_s(ed1, _T("%llu"), Total);
    _stprintf_s(ed2, _T("%llu"), Free);
    _stprintf_s(ed3, _T("%llu"), Available);
    UpdateData(false);
  }

Автор: rAccOOn 8.10.2009, 09:21
Может для этого надо еще какую то библеотеку подключить, потому что при компиленге вылазиет ошибка
Код

error C2065: '_stprintf_s' : undeclared identifier 


Или обьявить его как то надо было. 

Автор: xvr 8.10.2009, 09:23
Цитата(rAccOOn @ 8.10.2009,  09:21)
Может для этого надо еще какую то библеотеку подключить, потому что при компиленге вылазиет ошибка
Код

error C2065: '_stprintf_s' : undeclared identifier 


Или обьявить его как то надо было.

Угу, VS2005 называется  smile 

Автор: dumb 8.10.2009, 10:56
замени _stprintf_s на sprintf

Автор: rAccOOn 8.10.2009, 11:00
аа, я пишу прогу на Visual C++ 6.0

Добавлено через 4 минуты и 57 секунд
Страно, но теперь вообще ничего не выводится. 

Автор: rAccOOn 8.10.2009, 11:21
а при попытке вывести значения ed1, ed2, ed3 в лист бокс, он их выводит но тоже какие то неестественые числа
Код
            
list_a.AddString(ed1);
list_a.AddString(ed2);
list_a.AddString(ed3);


на выходе получаються числа
http://www.picamatic.com/view/5443097_Безымянный/
получаеться числа немного изменились но до правды далековато. Но оно работает просто как то некоректно, потому что при попытке вывести ту же инфу о дисководе или о несуществующем разделе ничего не выводит.

Автор: xvr 8.10.2009, 11:23
Цитата(rAccOOn @ 8.10.2009,  11:00)
аа, я пишу прогу на Visual C++ 6.0

Добавлено @ 11:05
Страно, но теперь вообще ничего не выводится.

У VS (в особенности у 6й) формат печати __int64 другой -
Код

sprintf(ed1,"%Lu",Total);
sprintf(ed2,"%Lu", Free);
sprintf(ed3,"%Lu", Available);

Автор: GremlinProg 8.10.2009, 11:39
http://msdn.microsoft.com/en-us/library/tcxf1dw6(VS.80).aspx
Цитата(Size and Distance Specification @ MSDN)

To Specify Use Prefix With Type Specifier 
long int l d, i, o, x, or X 
long unsigned int l u 
short int h d, i, o, x, or X 
short unsigned int h u 
__int64 I64 d, i, o, u, x, or X 
Single-byte character with printf functions  h c or C 
Wide character with printf functions l c or C 
Single-byte – character string with printf functions h s or S 
Wide-character string with printf functions l s or S 

для беззнакового:
Код

...
sprintf( ed1, "%I64u", Total );
...

для знакового:
Код

...
sprintf( ed1, "%I64i", Total );
...

этот формат вроде бы поддерживался везде

Автор: rAccOOn 8.10.2009, 21:15
Это конечно страно но не первый метод ни второй не дал результата
Код

void CUhygDlg::OnButton1() 
{
            ULARGE_INTEGER Available, Total, Free;
    TCHAR ed1[32], ed2[32], ed3[32];
    list.ResetContent();
    char dd[4];
    DWORD dr = GetLogicalDrives();
    for( int i = 0; i < 26; i++ )
    {
        int n = ((dr>>i)&0x00000001);
        if( n == 1 ) 
        {
            dd[0] =  char(65+i); dd[1] = ':'; dd[2] = '\\'; dd[3] = 0;
            list.AddString(dd);    
        }
    }    
    list_a.ResetContent();
    int d;
    UpdateData(true);
        d = GetDriveType(ed);
    if( d == DRIVE_UNKNOWN ) list_a.AddString("Oei: Iaecaanoiue");
    if( d == DRIVE_NO_ROOT_DIR )list_a.AddString("Oei: Iaecaanoiue");
    if( d == DRIVE_REMOVABLE )list_a.AddString( "Oei: Ciaiiue");
    if( d == DRIVE_FIXED ) list_a.AddString("Oei: Eieaeuiue");
    if( d == DRIVE_REMOTE ) list_a.AddString("Oei: Naoaaie");
    if( d == DRIVE_CDROM ) list_a.AddString("Oei: CD-ROM");
    if( d == DRIVE_RAMDISK ) list_a.AddString("Oei: Ae?ooaeuiue a ICO");
    UpdateData(false);


        if(GetDiskFreeSpaceEx("e:\\", &Available,&Total,&Free))    
        {
                sprintf(ed1,"%Lu",Total);
                sprintf(ed2,"%Lu", Free);
                sprintf(ed3,"%Lu", Available);
             UpdateData(false);
        }

}



Посмотрите пожалуйста, вот это полный код програмы, возможно что то мишает выводу. Или может дето чего то не хватает поэтому ничего и не выводится. 

Автор: GremlinProg 8.10.2009, 23:43
а что ты ожидаешь от этого кода?

ed1, ed2, ed3 тут вроде бы вообще не используются,
ведь в них ты и сохраняешь результаты работы функции GetDiskFreeSpaceEx
выведи их в memo или список или уж на худой конец - через _RPT, в консоль отладчика, чтобы увидеть их воочию
или я что-то пропустил?

Автор: rAccOOn 9.10.2009, 06:34
Ну к примеру вот так я выводил 
Код

            list_a.AddString(ed1);
            list_a.AddString(ed2);
            list_a.AddString(ed3);

и получал
http://www.picamatic.com/view/5462320_Безымянный/

А вот Everest да и так еси посмотреть получаеться должно быть всего  50 006 мб, и свободно 14 с хвостом гиг.
Но все равно в паредке вывода идет сначала общий обьем памяти потом свободный и доступный, а получаеться что общий меньше свободного и доступного а такого быть не может быть да и числа не те. 

А я ожидал что этот код мне выведет правильные значения, ну или хотя бы очень приближеное.

Автор: smoke_man 9.10.2009, 08:18
Посмотри небольшой пример:
Код

#include <windows.h>
#include <stdio.h>

int main ()
{
    BOOL  fResult;

    char  *pszDrive  = "D:\\";

    unsigned __int64 i64FreeBytesToCaller,
        i64TotalBytes,
        i64FreeBytes; 
    
    fResult = GetDiskFreeSpaceExA (pszDrive,
            (PULARGE_INTEGER)&i64FreeBytesToCaller,
            (PULARGE_INTEGER)&i64TotalBytes,
            (PULARGE_INTEGER)&i64FreeBytes);
        if (fResult)
        {
            printf ("\n\nGetDiskFreeSpaceEx reports\n\n");
            printf ("Available space to caller = %I64u KB\n",
                i64FreeBytesToCaller / 1024);
            printf ("Total space               = %I64u KB\n",
                i64TotalBytes / 1024);
            printf ("Free space on drive       = %I64u KB\n",
                i64FreeBytes / 1024);
        }
    

    if (!fResult)
        printf ("error: %lu:  could not get free space for \"%s\"\n",
        GetLastError(), pszDrive);
    system("PAUSE");

    return EXIT_SUCCESS;
}


Автор: rAccOOn 9.10.2009, 13:21
спс, помогло. 

Автор: GremlinProg 9.10.2009, 13:36
Цитата(rAccOOn @  9.10.2009,  15:21 Найти цитируемый пост)
помогло

серьезно?
т.е. проблема заключалась только в передаче в sprintf структуры ULARGE_INTEGER?
тогда ULARGE_INTEGER использовать предпочтительнее, а в sprintf нужно передавать Total.QuadPart

Добавлено через 2 минуты и 4 секунды
хотя щас только сообразил: в килобайтах размер может корректно вписываться в 32 бита, не затрагивая старшее двойное слово

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)