Windows中包含很多约定的路径,比如%APPDATA%
%USERPROFILE%
,或者一些库路径,文档,图片,视频。在Windows编程实践中,
应该使用knownfolderid
来固定查找位置。
import ctypes
from ctypes import wintypes
import os
# Define GUID structure
class GUID(ctypes.Structure):
_fields_ = [
("Data1", wintypes.DWORD),
("Data2", wintypes.WORD),
("Data3", wintypes.WORD),
("Data4", wintypes.BYTE * 8)
]
# KnownFolderID GUIDs
FOLDERID_RoamingAppData = GUID(0x3EB685DB, 0x65F9, 0x4CF6, (ctypes.c_ubyte * 8)(0xA0,0x3A,0xE3,0xEF,0x65,0x72,0x9F,0x3D))
FOLDERID_LocalAppData = GUID(0xF1B32785, 0x6FBA, 0x4FCF, (ctypes.c_ubyte * 8)(0x9D,0x55,0x7B,0x8E,0x7F,0x15,0x70,0x91))
FOLDERID_ProgramData = GUID(0x62AB5D82, 0xFDC1, 0x4DC3, (ctypes.c_ubyte * 8)(0xA9,0xDD,0x07,0x0D,0x1D,0x49,0x5D,0x97))
FOLDERID_Documents = GUID(0xFDD39AD0, 0x238F, 0x46AF, (ctypes.c_ubyte * 8)(0xAD,0xB4,0x6C,0x85,0x48,0x03,0x69,0xC7))
FOLDERID_ProgramFiles = GUID(0x905E63B6, 0xC1BF, 0x494E, (ctypes.c_ubyte * 8)(0xB2,0x9C,0x65,0xB7,0x32,0xD3,0xD2,0x1A))
FOLDERID_ProgramFilesX64 = GUID(0x6D809377, 0x6AF0, 0x444B, (ctypes.c_ubyte * 8)(0x89,0x57,0xA3,0x77,0x3F,0x02,0x20,0x0E))
# SHGetKnownFolderPath prototype
SHGetKnownFolderPath = ctypes.windll.shell32.SHGetKnownFolderPath
SHGetKnownFolderPath.argtypes = [ctypes.POINTER(GUID), wintypes.DWORD, wintypes.HANDLE, ctypes.POINTER(ctypes.c_wchar_p)]
SHGetKnownFolderPath.restype = wintypes.HRESULT
def get_known_folder_path(folder_id):
path_ptr = ctypes.c_wchar_p()
hr = SHGetKnownFolderPath(ctypes.byref(folder_id), 0, 0, ctypes.byref(path_ptr))
if hr != 0:
raise ctypes.WinError(hr)
path = path_ptr.value
ctypes.windll.ole32.CoTaskMemFree(path_ptr)
return path
if __name__ == "__main__":
print("FOLDERID_RoamingAppData:", get_known_folder_path(FOLDERID_RoamingAppData))
print("FOLDERID_LocalAppData:", get_known_folder_path(FOLDERID_LocalAppData))
print("FOLDERID_ProgramData:", get_known_folder_path(FOLDERID_ProgramData))
print("FOLDERID_Documents:", get_known_folder_path(FOLDERID_Documents))
print("FOLDERID_ProgramFiles:", get_known_folder_path(FOLDERID_ProgramFiles))
print("FOLDERID_ProgramFilesX64:", get_known_folder_path(FOLDERID_ProgramFilesX64))
print("TEMP:", os.environ.get("TEMP"))
#include <windows.h>
#include <shlobj.h>
#include <iostream>
#include <string>
void print_known_folder(const wchar_t* name, const KNOWNFOLDERID& folderId) {
PWSTR path = nullptr;
HRESULT hr = SHGetKnownFolderPath(folderId, 0, NULL, &path);
if (SUCCEEDED(hr)) {
std::wcout << name << L": " << path << std::endl;
CoTaskMemFree(path);
} else {
std::wcout << name << L": <Failed to get path>" << std::endl;
}
}
int main() {
print_known_folder(L"FOLDERID_RoamingAppData", FOLDERID_RoamingAppData);
print_known_folder(L"FOLDERID_LocalAppData", FOLDERID_LocalAppData);
print_known_folder(L"FOLDERID_ProgramData", FOLDERID_ProgramData);
print_known_folder(L"FOLDERID_Documents", FOLDERID_Documents);
print_known_folder(L"FOLDERID_ProgramFiles", FOLDERID_ProgramFiles);
print_known_folder(L"FOLDERID_ProgramFilesX64", FOLDERID_ProgramFilesX64);
wchar_t* temp = _wgetenv(L"TEMP");
std::wcout << L"TEMP: " << (temp ? temp : L"<not found>") << std::endl;
return 0;
}
一个应用程序通常往注册表的HKCU\Software内写数据,规范是外层为公司名,内部是产品名,然后是自组织的设置条目。
import winreg
company = "MyExampleCompany"
product = "MyExampleProduct"
settings = {
"SettingA": 123,
"SettingB": "hello",
"SettingC": 1.23
}
key_path = fr"Software\\{company}\\{product}"
with winreg.CreateKey(winreg.HKEY_CURRENT_USER, key_path) as key:
for name, value in settings.items():
if isinstance(value, int):
winreg.SetValueEx(key, name, 0, winreg.REG_DWORD, value)
elif isinstance(value, float):
# 注册表没有 float 类型,通常以字符串形式存储
winreg.SetValueEx(key, name, 0, winreg.REG_SZ, str(value))
else:
winreg.SetValueEx(key, name, 0, winreg.REG_SZ, value)
print(f"Wrote settings to HKEY_CURRENT_USER\\{key_path}")
#include <windows.h>
#include <string>
#include <iostream>
int main() {
const wchar_t* company = L"MyExampleCompany";
const wchar_t* product = L"MyExampleProduct";
std::wstring keyPath = std::wstring(L"Software\\") + company + L"\\" + product;
HKEY hKey;
LONG result = RegCreateKeyExW(
HKEY_CURRENT_USER,
keyPath.c_str(),
0, NULL, 0, KEY_WRITE, NULL, &hKey, NULL
);
if (result != ERROR_SUCCESS) {
std::wcerr << L"Failed to create/open registry key!" << std::endl;
return 1;
}
DWORD settingA = 123;
std::wstring settingB = L"hello";
std::wstring settingC = L"1.23"; // float as string
RegSetValueExW(hKey, L"SettingA", 0, REG_DWORD, reinterpret_cast<const BYTE*>(&settingA), sizeof(settingA));
RegSetValueExW(hKey, L"SettingB", 0, REG_SZ, reinterpret_cast<const BYTE*>(settingB.c_str()), (settingB.size() + 1) * sizeof(wchar_t));
RegSetValueExW(hKey, L"SettingC", 0, REG_SZ, reinterpret_cast<const BYTE*>(settingC.c_str()), (settingC.size() + 1) * sizeof(wchar_t));
RegCloseKey(hKey);
std::wcout << L"Wrote settings to HKEY_CURRENT_USER\\" << keyPath << std::endl;
return 0;
}