【C++】防止机械/移动硬盘休眠 - NoSleepHD
初衷
由于外置机械桌面硬盘总是在p图找素材的时候自动休眠,总是要不时的唤醒重启很麻烦,所以写了个防止机械/移动硬盘休眠软件。
原理
原理是定期向硬盘中进行文件操作从而防止硬盘休眠。这里是每60秒向硬盘创建一个文件后立刻删除,即可以唤醒硬盘又没有残留。
设置了定时退出器,程序到时间会自动退出。(由于每60秒写一次文件,这里的倒计时采用的是每次-1,而不是真的定时器。)
运行截图
代码
#include <windows.h>
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <vector>
#include <sstream>
#include <io.h>
#include <fcntl.h>
// 添加一个辅助函数来输出中文
void PrintW(const wchar_t* text) {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD written;
WriteConsoleW(hConsole, text, wcslen(text), &written, NULL);
}
// 获取可用的硬盘列表
std::vector<char> GetAvailableDrives() {
std::vector<char> drives;
DWORD driveMask = GetLogicalDrives();
for (char drive = 'A'; drive <= 'Z'; drive++) {
if (driveMask & 1) {
std::string rootPath = std::string(1, drive) + ":\\";
UINT driveType = GetDriveTypeA(rootPath.c_str());
// 只显示可移动驱动器和固定驱动器
if (driveType == DRIVE_REMOVABLE || driveType == DRIVE_FIXED) {
drives.push_back(drive);
}
}
driveMask >>= 1;
}
return drives;
}
// 写入文件到指定驱动器
void WriteToFile(char drive, int remainingMinutes) {
std::string filePath = std::string(1, drive) + ":\\temp_disk_awake";
HANDLE hFile = CreateFileA(
filePath.c_str(),
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
NULL
);
if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile); // 立即关闭文件,会自动删除
// 只在控制台显示时间信息
SYSTEMTIME st;
GetLocalTime(&st);
wchar_t timeStr[200];
if (remainingMinutes >= 0) {
swprintf_s(timeStr, L"%c: 写入成功: %04d-%02d-%02d %02d:%02d:%02d,剩余时间:%d 分钟\n",
drive, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, remainingMinutes);
} else {
swprintf_s(timeStr, L"%c: 写入成功: %04d-%02d-%02d %02d:%02d:%02d\n",
drive, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
}
PrintW(timeStr);
} else {
wchar_t errorStr[100];
swprintf_s(errorStr, L"%c: 无法访问磁盘,请确保磁盘已连接且有写入权限\n", drive);
PrintW(errorStr);
}
}
int main() {
_setmode(_fileno(stdout), _O_U16TEXT);
// 获取并显示可用驱动器
std::vector<char> drives = GetAvailableDrives();
PrintW(L"可用的驱动器:\n");
for (size_t i = 0; i < drives.size(); i++) {
wchar_t driveStr[100];
swprintf_s(driveStr, L"%zd. %c:\\\n", i + 1, drives[i]);
PrintW(driveStr);
}
PrintW(L"请输入要保持唤醒的驱动器编号(多个驱动器用空格分隔,如:1 3):");
std::string input;
std::getline(std::cin, input);
// 解析用户输入
std::vector<char> selectedDrives;
std::stringstream ss(input);
int choice;
while (ss >> choice) {
if (choice > 0 && choice <= static_cast<int>(drives.size())) {
selectedDrives.push_back(drives[choice - 1]);
}
}
if (selectedDrives.empty()) {
PrintW(L"未选择任何驱动器,程序退出\n");
return 1;
}
PrintW(L"是否需要定时退出?(y/n):");
char timerChoice;
std::cin >> timerChoice;
std::cin.ignore(1000, '\n');
int totalMinutes = -1; // -1 表示无限运行
if (timerChoice == 'y' || timerChoice == 'Y') {
PrintW(L"请输入程序运行时间(分钟):");
std::cin >> totalMinutes;
if (totalMinutes <= 0) {
PrintW(L"时间设置无效,程序退出\n");
return 1;
}
}
PrintW(L"已选择的驱动器:");
for (char drive : selectedDrives) {
wchar_t driveStr[10];
swprintf_s(driveStr, L"%c: ", drive);
PrintW(driveStr);
}
PrintW(L"\n");
wchar_t startMsg[200];
if (totalMinutes > 0) {
swprintf_s(startMsg, L"程序已启动,将运行 %d 分钟,每60秒写入一次数据来保持硬盘唤醒...\n", totalMinutes);
} else {
swprintf_s(startMsg, L"程序已启动,将持续运行,每60秒写入一次数据来保持硬盘唤醒...\n");
}
PrintW(startMsg);
PrintW(L"按Ctrl+C终止程序\n");
int remainingMinutes = totalMinutes;
while (true) {
// 写入所有选中的驱动器
for (char drive : selectedDrives) {
WriteToFile(drive, remainingMinutes);
}
// 如果是最后一次写入(remainingMinutes == 0),直接退出
if (remainingMinutes == 0) {
break;
}
// 不是最后一次,则等待并继续
std::this_thread::sleep_for(std::chrono::seconds(60));
// 更新计时器(只在有限时间模式下)
if (remainingMinutes > 0) {
remainingMinutes--;
}
// remainingMinutes == -1 时继续循环(无限运行模式)
}
if (totalMinutes > 0) {
PrintW(L"\n设定时间已到,程序退出\n");
}
return 0;
}