获取可用驱动器列表及其大小

3
我知道你可以使用GetLogicalDrives()和GetDiskFreeSpaceEx()的组合来获取驱动器列表及其大小。我一直在使用GetDiskFreeSpaceEx()而没有问题,但当我尝试使用GetLogicalDrives()时遇到了一个问题:我不想在将其传递给GetDiskFreeSpaceEx()之前检查每个可能的字母是否存在。

有没有更简单的方法来获取系统上的驱动器(磁盘)列表及其大小?我正在使用C,在Windows上。

我想澄清一点,我知道使用C#和WMI可能更容易,但我对此没有兴趣,请不要将其作为可能的解决方案发布。如果您想指出如何在C和WMI中完成,请继续。谢谢,不需要C++或C#!(就像我的上一个问题中有人所做的那样)


+1,好问题,+添加winapi标签以便正确引导答案。 - user257111
“我不想要检查每个可能的字母是否存在”…好的,你不想要,但是你必须检查驱动器是否存在吗?如果是,请解释原因。 - Brian R. Bondy
因为在某些系统上,您可能会在远程驱动器上陷入循环中。 - Jessica
无论如何,我想我会坚持下去,因为GetLogicalDriveStrings最终变得很痛苦。 - Jessica
顺便说一下,这是被标记为c的第10,000个问题 :) - Daniel Vassallo
3个回答

8
你可以使用 GetLogicalDriveStrings 函数,它会返回一个包含系统上所有有效驱动器字母的缓冲区。

更新:

下面是我编写的一个示例程序,它使用 GetLogicalDriveStrings 枚举驱动器并输出一些基本信息。

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

int __cdecl main()
{
    DWORD cchBuffer;
    WCHAR* driveStrings;
    UINT driveType;
    PWSTR driveTypeString;
    ULARGE_INTEGER freeSpace;

    // Find out how big a buffer we need
    cchBuffer = GetLogicalDriveStrings(0, NULL);

    driveStrings = (WCHAR*)malloc((cchBuffer + 1) * sizeof(TCHAR));
    if (driveStrings == NULL)
    {
        return -1;
    }

    // Fetch all drive strings    
    GetLogicalDriveStrings(cchBuffer, driveStrings);

    // Loop until we find the final '\0'
    // driveStrings is a double null terminated list of null terminated strings)
    while (*driveStrings)
    {
        // Dump drive information
        driveType = GetDriveType(driveStrings);
        GetDiskFreeSpaceEx(driveStrings, &freeSpace, NULL, NULL);

        switch (driveType)
        {
        case DRIVE_FIXED:
            driveTypeString = L"Hard disk";
            break;

        case DRIVE_CDROM:
            driveTypeString = L"CD/DVD";
            break;

        case DRIVE_REMOVABLE:
            driveTypeString = L"Removable";
            break;

        case DRIVE_REMOTE:
            driveTypeString = L"Network";
            break;

        default:
            driveTypeString = L"Unknown";
            break;
        }

        printf("%S - %S - %I64u GB free\n", driveStrings, driveTypeString,
                  freeSpace.QuadPart / 1024 / 1024 / 1024);

        // Move to next drive string
        // +1 is to move past the null at the end of the string.
        driveStrings += lstrlen(driveStrings) + 1;
    }

    free(driveStrings);

    return 0;

}

在我的计算机上,这将输出:
C:\ - Hard disk - 181 GB free
D:\ - CD/DVD - 0 GB free
E:\ - Hard disk - 806 GB free

谢谢,但我无法让它工作... 当我尝试将每个字符串发送到GetDiskFreeSpaceEx时,它会崩溃。 你能发一段代码片段吗? - Jessica
看看Laurie Stern的回答,然后思考为什么driveStrings的增量会导致free(driveStrings)不再有效。 - Jesse Chisholm

5

GetLogicalDrives()是系统提供的API。一个简单的for()循环将把它的结果转换成驱动器字母,就像这样:

DWORD d = GetLogicalDrives();
int i;
TCHAR Drive[] = _T("A:\\");
for(i=0;i<26;i++)
{
    if(d & (1<<i))
    {
        Drive[0] = _T('A')+i;
        GetDiskFreeSpaceEx(Drive, .....);
    }
}

如果您对Stack Overflow提供的服务水平不满意,可以随时要求退款。


不是我不满意,而是人们没有注意问题和标签。这已经不是第一次发生了。如果我明确地问了C语言的问题,你为什么要用VB语言回答呢? 感谢您的回答。 - Jessica
2
我认为是 i < 26 => https://dev59.com/lHI-5IYBdhLWcg3wQV8Z - Christopher Oezbek
还要注意在"A:\"中缺少的反斜杠\。 - Christopher Oezbek

3
这是Michael的代码,曾经作为编辑被拒绝。在free()时会发生段错误,除非插入一个虚拟变量'singleDriveString',如下所示:
#include <windows.h>
#include <malloc.h>
#include <stdio.h>

int __cdecl main()
{
DWORD cchBuffer;
WCHAR* driveStrings;
UINT driveType;
PWSTR driveTypeString;
ULARGE_INTEGER freeSpace;

// Find out how big a buffer we need
cchBuffer = GetLogicalDriveStrings(0, NULL);

driveStrings = (WCHAR*)malloc((cchBuffer + 1) * sizeof(TCHAR));
if (driveStrings == NULL)
{
    return -1;
}

// Fetch all drive strings    
GetLogicalDriveStrings(cchBuffer, driveStrings);

// Loop until we find the final '\0'
// driveStrings is a double null terminated list of null terminated strings)
wchar_t * singleDriveString = driveStrings;
while (*singleDriveString)
{
    // Dump drive information
    driveType = GetDriveType(singleDriveString);
    GetDiskFreeSpaceEx(singleDriveString, &freeSpace, NULL, NULL);

    switch (driveType)
    {
    case DRIVE_FIXED:
        driveTypeString = L"Hard disk";
        break;

    case DRIVE_CDROM:
        driveTypeString = L"CD/DVD";
        break;

    case DRIVE_REMOVABLE:
        driveTypeString = L"Removable";
        break;

    case DRIVE_REMOTE:
        driveTypeString = L"Network";
        break;

    default:
        driveTypeString = L"Unknown";
        break;
    }

    printf("%S - %S - %I64u GB free\n", singleDriveString, driveTypeString,
              freeSpace.QuadPart / 1024 / 1024 / 1024);

    // Move to next drive string
    // +1 is to move past the null at the end of the string.
    singleDriveString += lstrlen(singleDriveString) + 1;
}

free(driveStrings);

return 0;

} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接