不同的磁盘序列号来自 GetVolumeInformation()

Different disk serial number result from GetVolumeInformation()

本文关键字:GetVolumeInformation 序列号 磁盘      更新时间:2023-10-16
DWORD disk_serialINT[MAX_PATH + 1];
GetVolumeInformationA(NULL, NULL, NULL, disk_serialINT, NULL, NULL, NULL, NULL);
char* disk_serialANSI;
sprintf(disk_serialANSI, "%d", disk_serialINT);
std::string HDDserial = disk_serialANSI;

这是我的一段代码,我在其中获取hdd序列号,但问题是每次程序执行时的值都不同。有人可以解释一下吗?

解决:

DWORD disk_serialINT;
GetVolumeInformationA(NULL, NULL, NULL, &disk_serialINT, NULL, NULL, NULL, NULL);
std::string HDDserial = std::to_string(disk_serialINT);

谢谢。

这两

行将为您提供未定义的行为

char* disk_serialANSI;
sprintf(disk_serialANSI, "%d", disk_serialINT);

你声明了一个指针变量,但实际上并没有让它指向任何地方。未初始化的局部变量具有不确定的值(实际上它似乎是随机的),并且通过使用未初始化的指针,您不知道sprintf调用将写入何处


由于您正在C++编程,因此有几种解决方案。

  • 老式的方法是使disk_serialANSI成为字符数组,大到足以容纳数字(包括字符串终止符)。另一种方法是手动为指针分配内存,然后在完成该内存后再次释放该内存。

  • 使用 std::ostringstream 格式化数据并获取std::string

  • 使用 std::to_string 直接转换为字符串。

  • 使用增强词法转换。

除了约阿希姆所说的话之外,您没有正确传递序列号。您需要将指针传递给单个值。

DWORD disk_serialINT;
GetVolumeInformationA(NULL, NULL, NULL, &disk_serialINT, NULL, NULL, NULL, NULL);

在您的代码中,您在此处执行的操作使情况更加复杂:

sprintf(disk_serialANSI, "%d", disk_serialINT);

忽略 Joachim 的答案涵盖的未初始化变量 disk_serialANSI,您将传递指向"%d"格式字符串的指针。一旦你把disk_serialINT改为单一值,事情就会更好。但是,您正在将无符号值传递给单个格式字符串。

是时候放弃这些粗糙的 C 格式函数并使用 C++ 标准库在整数值和文本之间进行转换了。

最后要强调的一点是,必须检查对 Win32 API 的调用的返回值。您不知道函数调用是否成功。您一定不能假设它确实如此。文档涵盖了所有这些内容:https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993.aspx

此程序打印包含当前目录的卷的序列号:

#include <Windows.h>
#include <iostream>
int main()
{
    DWORD disk_serialINT;
    if (!GetVolumeInformationA(NULL, NULL, NULL, &disk_serialINT, NULL,
        NULL, NULL, NULL))
    {
        std::cout << "Failed: " << GetLastError() << std::endl;
        return 1;
    }
    std::cout << "Current directory volume serial numnber: " << std::hex 
        << disk_serialINT << std::endl;
    return 0;
}

如果有人来查看此代码,这里的解决方案是我对它的看法:

问题#1

DWORD disk_serialINT[MAX_PATH + 1];
  • 当您只需要一个值时,声明一个DWORD值数组。
  • 使用宏MAX_PATH(并向其添加 1),而不了解它的用途。
  • 不知道类型(当DWORD类型无符号INT命名变量)。
  • 不了解问题域(当变量实际上是序列号时disk_serial命名变量)。

问题#2

GetVolumeInformationA(NULL, NULL, NULL, disk_serialINT, NULL, NULL, NULL, NULL);
  • 无错误处理(不检查失败的函数返回值)。
  • 了解按值和按引用传递参数之间的区别(不传递变量disk_serialINT地址)。

问题 #3

char* disk_serialANSI;
  • 不了解数组和指针之间的区别。
  • 不了解静态分配和动态分配之间的区别。

问题 #4

sprintf(disk_serialANSI, "%d", disk_serialINT);
  • 使用未初始化的变量disk_serialANSI .
  • 使用
  • 错误的变量类型(要么使用char数组,要么保留指针但分配内存并稍后释放它)。
  • 不了解问题域(卷序列号使用错误的格式,应%08lX)。
  • 不使用安全版本的sprintf

问题 #5

std::string HDDserial = disk_serialANSI;
  • 在没有充分理由的情况下混合使用C和C++。

换句话说,所有典型的初学者程序员错误。希望他们在此期间学到了更多,而不仅仅是在堆栈溢出上找到问题的答案。

上面已经有一个David Heffeman提供的C++解决方案,所以为了答案的完整性,这里是等效的C解决方案:

#include <stdio.h>
#include <windows.h>
int main()
{
    const int VolumeSerialLength = 9; // 8 hex digits + zero termination
    char VolumeSerial[VolumeSerialLength] = { 0 };
    DWORD VolumeSerialNumber;
    if (GetVolumeInformationA(NULL, NULL, NULL, &VolumeSerialNumber, NULL, NULL, NULL, NULL) {
        sprintf_s(VolumeSerial, VolumeSerialLength, "%08lX", VolumeSerialNumber);
        printf("Volume serial number: %8.8s.n", VolumeSerial);
        return 0;
    } else {
        printf("GetVolumeInformationA() error: %08lXn", GetLastError());
        return 1;
    }
}
相关文章:
  • 没有找到相关文章