您可以使用它wmic diskdrive get model,serialnumber
来获取当前插入的磁盘的型号和序列号,如果您同时使用它们,则它们是唯一的(如果您仅使用序列号,则可能会发生变化,其他制造商使用相同的序列号,即使实际上,它们都有不同的模式),如果您需要一种方法来唯一区分两个设备(PC、笔记本电脑...),这非常有用。现在我遇到的问题是我只想要安装操作系统的磁盘的型号和序列号。
是否有另一个命令或它们的组合(检查它们的结果,也许会看到一个共同的部分,这将导致我需要什么),它只会返回安装了操作系统的值?
我检查了选项wmic diskdrive get
,但没有看到一个可以满足我需要的选项。还有vol C
,但它提供了 Windows 为该逻辑卷(分区)提供的序列号,而不是磁盘本身的序列号。
此外,虽然用户确实可以简单地将操作系统安装在不同的磁盘上,因此型号和序列号将与上次不同(如果他们甚至意识到这是验证方法),但所需的时间这样做(无论是克隆还是全新安装,然后再次下载并安装应用程序),至少对于我的用例来说,尝试欺骗应用程序已经足够带来不便,而且它还用于其他一些小的验证,可以不必与 IP 绑定,因为可以通过路由器重新启动或网络禁用/启用(大多数情况下)轻松更改 IP,而且 IP 也适用于整个网络,而不是特定的设备。
//Edit1:我发现另一个命令在与 Windows 11 Terminal / PowerShell一起使用时有效,但不幸的是,当在 C++ 中使用时,system("Get-Disk (Get-Partition -DriveLetter 'C').DiskNumber");
它会给出错误'Get-Disk' is not recognized as an internal or external command, operable program or batch file.
因为我只需要 Windows,并且默认情况下它将使用分区 C,这本来就是这样。它提供以下信息Number / Friendly Name (is the manufacturer and model) / Serial Number / Health Status / Operational Status / Total Size / Partition Style
。
//Edit2:使用 Zac67 提供的命令,我在 C++ 中尝试了它们(std17,发布 x64,我只需要 Windows):
#include <iostream>
#include <string>
#include <array>
using namespace std;
std::string exec(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cmd, "r"), _pclose);
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}
void main() {
cout << exec("wmic bootconfig get description");
cout << exec("wmic diskdrive where DeviceID='\\\\.\\PHYSICALDRIVE3' get model,serialnumber");
}
第一个命令有我期望的返回:Description\Device\Harddisk3\Partition1
,但是当运行第二个命令时,不幸的是我得到了ERROR: Description = Invalid query
。如果我直接在 CMD 中运行它们,那么它们都运行良好,但如果我在 Windows 11 终端/PowerShell 中使用它们,则与代码相同,第一个命令很好,但第二个命令出现相同的错误。
//Edit3:根据我从 Zac67 获得的命令,这是 C++ 的最终形式:
#include <iostream>
#include <string>
#include <array>
std::string exec(const char* cmd) {
std::array<char, 128> buffer;
std::string result;
std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cmd, "r"), _pclose);
if (!pipe) {
throw std::runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
return result;
}
void replaceString(std::string& subject, const std::string& search,
const std::string& replace) {
size_t pos = 0;
while ((pos = subject.find(search, pos)) != std::string::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
}
void main() {
std::string index = exec("wmic bootconfig get description");
index = index.at(index.find_last_of("\\") - 1);
std::string modelSerialNumber = "wmic diskdrive where DeviceID='\\\\\\\\.\\\\PHYSICALDRIVE" + index + "' get model,serialnumber";
modelSerialNumber = exec(modelSerialNumber.c_str());
replaceString(modelSerialNumber, "Model", "");
replaceString(modelSerialNumber, "SerialNumber", "");
replaceString(modelSerialNumber, " ", "");
std::cout << modelSerialNumber;
}
输出将是:KINGSTONSA2000M8250GXXXX_XXXX_XXXX_XXXX_XXXX_XXXX_XXXX_XXXX.
。对于我的用例,我需要像这样联合起来的型号和序列号。
你可以运行
请注意硬盘后面的索引- 这里是3。这是下一个查询中使用的索引。
跑步
\\
对于 cmd 批处理,必须加倍才能转义每个命令\
。如果您用另一种语言运行相同的逻辑,您应该只需要\\.\PHYSICALDRIVE3
. 当然,您应该更喜欢 C++ 中的本机 WMI 查询。