【问题标题】:c++ windows pass the result from GetLogicalDrives to GetVolumeInformationc++ windows将GetLogicalDrives的结果传递给GetVolumeInformation
【发布时间】:2017-07-08 10:09:42
【问题描述】:

直升机,

我正在使用 GetLogicalDrives 获取所有驱动器,我想进一步使用它来检测驱动器类型,然后使用 GetVolumeInformation 检查特定驱动器的状态。但是,我无法在 GetVolumeInformation 和 GetDriveTypes 中使用 GetLogicalDrives(DWORD) 的结果,因为它们不支持 LPCWSTR。如何转换 GetLogicalDrives 的结果并将其传递给 GetVolumeInformation 和 GetDriveTypes?

        TCHAR myDrives[] = L" A";
        DWORD myDrivesBitMask = GetLogicalDrives();
        WCHAR szTest[10];



      if (myDrivesBitMask == 0)
wprintf(L"GetLogicalDrives() failed with error code: %d\n", GetLastError());
        else {
            wprintf(L"This machine has the following logical drives:\n");
            while (myDrivesBitMask) {
                // Use the bitwise AND with 1 to identify 
                // whether there is a drive present or not. 
                if (myDrivesBitMask & 1) {
                    // Printing out the available drives                
                    wprintf(L"drive %s\n", myDrives);
                }
                // increment counter for the next available drive.   
                myDrives[1]++;
                // shift the bitmask binary right    
                myDrivesBitMask >>= 1;
            }
            wprintf(L"\n");
        }
UINT test;
for (i = 0; i<12; i++)
    {
        test = GetDriveType(myDrives[i]);
        switch (test)
        {
        case 0: printf("Drive %S is type %d - Cannot be determined.\n", myDrives[i], test);
            break;
        case 1: printf("Drive %S is type %d - Invalid root path/Not available.\n", myDrives[i], test);
            break;
        case 2: printf("Drive %S is type %d - Removable.\n", myDrives[i], test);
            break;
        case 3: printf("Drive %S is type %d - Fixed.\n", myDrives[i], test);
            break;
        case 4: printf("Drive %S is type %d - Network.\n", myDrives[i], test);
            break;
        case 5: printf("Drive %S is type %d - CD-ROM.\n", myDrives[i], test);

            break;
        case 6: printf("Drive %S is type %d - RAMDISK.\n", myDrives[i], test);
            break;
        default: "Unknown value!\n";
        }
    }



    (GetVolumeInformation(myDrives, volumeName, ARRAYSIZE(volumeName), &serialNumber, &maxComponentLen, &fileSystemFlags, fileSystemName, ARRAYSIZE(fileSystemName)))
            {
                _tprintf(_T("There is a CD/DVD in the CD/DVD rom"));
                _tprintf(_T("Volume Name: %s\n"), volumeName);
                _tprintf(_T("Serial Number: %lu\n"), serialNumber);
                _tprintf(_T("File System Name: %s\n"), fileSystemName);
                _tprintf(_T("Max Component Length: %lu\n"), maxComponentLen);

            }
            else
                _tprintf(_T("There is NO CD/DVD in the CD/DVD rom"));

【问题讨论】:

  • 使用GetLogicalDriveStrings 而不是GetLogicalDrives
  • 或者,只需将驱动器号 0 映射到 `A:`,依此类推(按字母顺序)。
  • 对于现代 Windows,只需使用 Unicode(wchar_t 类型)就可以大大简化事情,而不是像 TCHAR 这样的 Windows 9x 兼容性宏。毕竟,您的工具链可能甚至无法生成 Windows 9x 可执行文件。因此,除了使事情复杂化之外,这些东西都是徒劳的。

标签: c++ windows winapi


【解决方案1】:

由于调用GetDriveType()GetVolumeInformation()需要驱动器号,所以使用GetLogicalDriveStrings()而不是GetLogicalDrives()会更容易,例如:

WCHAR myDrives[105];
WCHAR volumeName[MAX_PATH];
WCHAR fileSystemName[MAX_PATH];
DWORD serialNumber, maxComponentLen, fileSystemFlags;
UINT driveType;

if (!GetLogicalDriveStringsW(ARRAYSIZE(myDrives)-1, myDrives))
{
    wprintf(L"GetLogicalDrives() failed with error code: %lu\n", GetLastError());
}
else
{
    wprintf(L"This machine has the following logical drives:\n");

    for (LPWSTR drive = myDrives; *drive != 0; drive += 4)
    {
        driveType = GetDriveTypeW(drive);
        wprintf(L"Drive %s is type %d - ", drive, driveType);

        switch (driveType)
        {
            case DRIVE_UNKNOWN:
                wprintf(L"Cannot be determined!");
                break;
            case DRIVE_NO_ROOT_DIR:
                wprintf(L"Invalid root path/Not available.");
                break;
            case DRIVE_REMOVABLE:
                wprintf(L"Removable.");
                break;
            case DRIVE_FIXED:
                wprintf(L"Fixed.");
                break;
            case DRIVE_REMOTE:
                wprintf(L"Network.");
                break;
            case DRIVE_CDROM:
                 wprintf(L"CD-ROM.");
                 break;
            case DRIVE_RAMDISK:
                wprintf(L"RAMDISK.");
                break;
            default:
                wprintf(L"Unknown value!");
        }
        wprintf(L"\n");

        if (driveType == DRIVE_CDROM)
        {
            if (GetVolumeInformationW(drive, volumeName, ARRAYSIZE(volumeName), &serialNumber, &maxComponentLen, &fileSystemFlags, fileSystemName, ARRAYSIZE(fileSystemName)))
            {
                wprintf(L"  There is a CD/DVD in the drive:\n");
                wprintf(L"  Volume Name: %s\n", volumeName);
                wprintf(L"  Serial Number: %08X\n", serialNumber);
                wprintf(L"  File System Name: %s\n", fileSystemName);
                wprintf(L"  Max Component Length: %lu\n", maxComponentLen);
            }
            else
            {
                wprintf(L"  There is NO CD/DVD in the drive");
            }
        }
    }
}

【讨论】:

  • 谢谢。我非常感谢您花时间制作这个示例。这简化了代码。
【解决方案2】:

我会为 GetLogicalDrives() 创建一个包装函数,以便更容易处理驱动路径向量:

std::vector< std::wstring > GetLogicalDrivePathes()
{
    std::vector< std::wstring > result;

    DWORD mask = GetLogicalDrives();
    for( wchar_t drive = 'A'; drive <= 'Z'; ++drive )
    {
        if( mask & 1 )
        {
            std::wstring rootPath;
            rootPath += drive;
            rootPath += L":\\";
            result.push_back( rootPath );
        }
        mask >>= 1;
    }

    return result;
}

可以这样使用:

for( auto& path : GetLogicalDrivePathes() )
{   
    std::wstring test = GetDriveType( path.data() );
    std::wcout << test << L'\n';
}

【讨论】:

  • GetLogicalDriveStrings() 将大大简化 GetLogicalDrivePathes()
  • 我讨厌双零结尾的字符串,我想坚持使用 OP 使用的函数来展示它是如何工作的。如果您愿意,可以发布一个答案,展示如何使用 GetLogicalDriveStrings() 作为替代方案。
  • 谢谢这个例子真的很有帮助。
  • @zett42:“我讨厌双零结尾的字符串” - 这是解释数据类型的不幸方式。它实际上是一个字符串列表,由一个空字符串终止。无需发明特殊的语义类来描述列表终止符。
  • 没错,但我仍然尽可能避免使用这些 API。与他们合作并不难,但我经常看到其他开发人员做错了事,所以这似乎是一个难以理解的概念。
【解决方案3】:

如果您想要 Drive 字符串,这可以解决问题,我也讨厌双 NULL 术语字符串。
甚至不能在调试器中查看它们,或者我不知道如何......

此函数采用双 NULL 终止的字符串并将其拆分为 CStringArray,您可以随意使用您喜欢的内容。它只是工作。

size_t ExtractNullTermStringsFromBuffer(CStringArray &dest, const WCHAR* SourceBuffer, const size_t BufLen)
{
    if (SourceBuffer[0] == '\0')
        return 0;
    WCHAR* strtok = new WCHAR[BufLen];
    size_t tokPos = 0;
    for (size_t curPos = 0; curPos < BufLen; ) {
        if (SourceBuffer[curPos] == '\0') { // first null byte
            strtok[tokPos] = '\0';
            tokPos = 0; // set to start new string
            dest.Add(strtok); //add it
            curPos++; // increment pos
            if (SourceBuffer[curPos] == '\0') { // check for the end
                curPos = BufLen; // break the loop
            }
        } else {
            strtok[tokPos] = SourceBuffer[curPos]; // otherwise continue
            curPos++;
            tokPos++;
        }
    }
    delete strtok;
    return dest.GetCount();
}

GetLogicalDriveStrings 部分在这里然后调用上面的函数

DWORD dwSize = MAX_PATH;
    WCHAR szLogicalDrives[MAX_PATH] = { 0 };
    DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives);
    CStringArray dest;
    size_t szSize = ExtractNullTermStringsFromBuffer(dest, szLogicalDrives, MAX_PATH);
    for (size_t curPos = 0; curPos < szSize; curPos++) {
        //      dest[curPos]; do something with it here
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    相关资源
    最近更新 更多