系列文章目录
文章目录
- 系列文章目录
- 前言
- 一、中文乱码原因
- 二、解决方法
- 1.如果是windos11下,使用英文语言,需要加以下代码
- 2.如果是中文语言只需要一行关键代码
- 3.如果在异常处理中显示宽字符中文
- 4.完整代码如下:
- 实现文件
- 测试代码
- 输出打印
前言
我们在win32编程中使用宽字符,std::wstring经常会遇到中文乱码的情况,比方说在调试时,查看std::string类型的字符串是显示字符串的字符无效,其实这时候已经中文乱码了,还有就是在控制台输出时也会出现中文乱码。
一、中文乱码原因
1.编码不匹配:
宽字符编码与输出流编码不匹配:std::wstring 存储的是宽字符(wchar_t),通常使用 UTF-16 或者其他宽字符编码(如 UCS-2)。当你尝试将 std::wstring 输出到 std::cout 或 std::cerr 时,这些流默认使用的是 char 类型,因此需要将宽字符转换为相应的 char 类型编码(例如 UTF-8 或 GBK)。
控制台编码设置不正确:Windows 控制台默认使用的是 CP850 或 CP437 编码。如果你的程序输出的是 UTF-8 或者其他编码的字符串,那么在默认编码下可能会导致乱码。
2.输出流设置不正确:
如果你使用 std::wcout 或 std::wcerr 输出宽字符串,那么你需要确保你的控制台支持宽字符输出,并且设置了正确的编码。
如果你使用 std::cout 或 std::cerr 输出宽字符串,你需要先将宽字符串转换为对应的窄字符串(std::string),并确保转换编码正确。
二、解决方法
1.如果是windos11下,使用英文语言,需要加以下代码
system("chcp 936");
std::wcout.imbue(std::locale("chs"));
2.如果是中文语言只需要一行关键代码
std::wcout.imbue(std::locale("chs"));
3.如果在异常处理中显示宽字符中文
std::string utf8ToGbk(const std::string& utf8Str)
{int size_needed = MultiByteToWideChar(CP_UTF8, 0, &utf8Str[0], (int)utf8Str.size(), NULL, 0);std::wstring wstrTo(size_needed, 0);MultiByteToWideChar(CP_UTF8, 0, &utf8Str[0], (int)utf8Str.size(), &wstrTo[0], size_needed);int size_needed_gbk = WideCharToMultiByte(CP_ACP, 0, &wstrTo[0], -1, NULL, 0, NULL, NULL);std::string strTo(size_needed_gbk, 0);WideCharToMultiByte(CP_ACP, 0, &wstrTo[0], -1, &strTo[0], size_needed_gbk, NULL, NULL);return strTo;
}
int main()
{try {system("chcp 936");std::wcout.imbue(std::locale("chs"));std::wcout << "控制台输出中文" << std::endl;//setConsoleEncodingUTF8(); // 设置控制台编码为 UTF-8// 创建 ServicesControl 实例//ServicesControl svcCtrl(L"Delivery Optimization");auto svcCtrl = std::make_shared<WindowsServiceControl::ServicesControl>(L"Delivery Optimization");// 检查是否已具有管理员权限if (svcCtrl->isAdmin()) {std::cout << "Running with administrator permissions.\n";// 启动服务svcCtrl->startService(L"Delivery Optimization");std::cout << "Service started successfully.\n";// 停止服务svcCtrl->stopService(L"Delivery Optimization");std::cout << "Service stopped successfully.\n";}else {// 如果没有管理员权限,尝试提升权限svcCtrl->elevatePermissionsAndRun();}}catch (const std::runtime_error& e) {std::string str(e.what());std::string gbkStr = utf8ToGbk(str);std::cerr << "An error occurred: " << str << std::endl;return 1;}return 0;
}
4.完整代码如下:
头文件:
#pragma once#include <windows.h>
#include <iostream>
#include <string>namespace WindowsServiceControl {class IServicesControl {public:virtual bool isAdmin() = 0;virtual bool elevatePermissionsAndRun() = 0;virtual bool startService(const std::wstring& serviceName) = 0;virtual bool stopService(const std::wstring& serviceName) = 0;};
}#pragma once
#include "IServicesControl.h"using namespace WindowsServiceControl;namespace WindowsServiceControl {class ServicesControl : public IServicesControl {public:explicit ServicesControl(const std::wstring& serviceName);bool isAdmin() override;bool elevatePermissionsAndRun() override;bool startService(const std::wstring& serviceName) override;bool stopService(const std::wstring& serviceName) override;//getting,settingstd::wstring getServiceName() { return _errorMessage; }void setServiceName(std::wstring& serviceName) { _serviceName = serviceName; }private:std::wstring _serviceName;std::wstring _errorMessage;private:std::wstring formatErrorMessage();std::string wstringToUtf8String(const std::wstring& wstr);void throwRuntimeErrorWithWstring(const std::wstring& wstr);};
}
实现文件
#include "ServicesControl.h"
#include <tchar.h>
#include <vector>
#include <stdexcept>
#include <sstream>ServicesControl::ServicesControl(const std::wstring& serviceName) : _serviceName(serviceName)
{}bool ServicesControl::isAdmin()
{HANDLE hToken = nullptr;if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {DWORD lastError = GetLastError();formatErrorMessage();throw std::runtime_error("Failed to open process token. Error code: " + std::to_string(lastError));}TOKEN_ELEVATION elevation;DWORD cbSize = sizeof(TOKEN_ELEVATION);if (!GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &cbSize)) {CloseHandle(hToken);DWORD lastError = GetLastError();formatErrorMessage();throw std::runtime_error("Failed to get token information. Error code: " + std::to_string(lastError));}CloseHandle(hToken);if (elevation.TokenIsElevated == 0) {formatErrorMessage();throw std::runtime_error("The process is not running with administrator permissions.");}return true;
}bool ServicesControl::elevatePermissionsAndRun()
{STARTUPINFO si;PROCESS_INFORMATION pi;ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);ZeroMemory(&pi, sizeof(pi));TCHAR szCmdLine[MAX_PATH];_sntprintf_s(szCmdLine, MAX_PATH, _T("%s"), GetCommandLine());TCHAR szAppPath[MAX_PATH];GetModuleFileName(nullptr, szAppPath, MAX_PATH);// Attempt to launch the application with elevated privilegesif (!CreateProcessAsUser(nullptr, szAppPath, szCmdLine, nullptr, nullptr, FALSE,CREATE_NEW_CONSOLE | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT,nullptr, nullptr, &si, &pi)) {DWORD lastError = GetLastError();formatErrorMessage();throw std::runtime_error("Failed to create process with elevated privileges. Error code: " + std::to_string(lastError));}// Wait for the process to finishWaitForSingleObject(pi.hProcess, INFINITE);CloseHandle(pi.hProcess);CloseHandle(pi.hThread);return true;
}bool ServicesControl::startService(const std::wstring& serviceName)
{SC_HANDLE hSCManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);if (hSCManager == nullptr) {DWORD lastError = GetLastError();formatErrorMessage();throw std::runtime_error("OpenSCManager failed. Error code: " + std::to_string(lastError));}SC_HANDLE hService = OpenService(hSCManager, serviceName.c_str(), SERVICE_START | SERVICE_QUERY_STATUS);if (hService == nullptr) {CloseServiceHandle(hSCManager);DWORD lastError = GetLastError();formatErrorMessage();throw std::runtime_error("OpenService failed. Error code: " + std::to_string(lastError));}// Send start commandif (!StartService(hService, 0, nullptr)) {CloseServiceHandle(hService);CloseServiceHandle(hSCManager);DWORD lastError = GetLastError();formatErrorMessage();throw std::runtime_error("StartService failed. Error code: " + std::to_string(lastError));}CloseServiceHandle(hService);CloseServiceHandle(hSCManager);return true;
}bool ServicesControl::stopService(const std::wstring& serviceName)
{SC_HANDLE hSCManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE);if (hSCManager == nullptr) {DWORD lastError = GetLastError();throw std::runtime_error("OpenSCManager failed. Error code: " + std::to_string(lastError));}SC_HANDLE hService = OpenService(hSCManager, serviceName.c_str(), SERVICE_STOP | SERVICE_QUERY_STATUS);if (hService == nullptr) {CloseServiceHandle(hSCManager);DWORD lastError = GetLastError();formatErrorMessage();throw std::runtime_error("OpenService failed. Error code: " + std::to_string(lastError));}SERVICE_STATUS_PROCESS ssStatus;DWORD dwBytesNeeded;// Send stop commandif (!ControlService(hService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssStatus)) {CloseServiceHandle(hService);CloseServiceHandle(hSCManager);DWORD lastError = GetLastError();formatErrorMessage();throw std::runtime_error("ControlService failed. Error code: " + std::to_string(lastError));}// Wait for the service to stopwhile (QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssStatus, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded)) {if (ssStatus.dwCurrentState == SERVICE_STOPPED)break;Sleep(ssStatus.dwWaitHint);}CloseServiceHandle(hService);CloseServiceHandle(hSCManager);return true;
}// Helper function to convert wide string to UTF-8 string
std::string ServicesControl::wstringToUtf8String(const std::wstring& wstr)
{if (wstr.empty()) return std::string();int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);std::string strTo(size_needed, '\0');WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);return strTo;
}void ServicesControl::throwRuntimeErrorWithWstring(const std::wstring& wstr) {std::string utf8Str = wstringToUtf8String(wstr);throw std::runtime_error(utf8Str);
}std::wstring ServicesControl::formatErrorMessage()
{std::wstring errorMessage;wchar_t buffer[1024] = L"";DWORD lastError = GetLastError();FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,nullptr, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),buffer, 1024, nullptr);errorMessage = L"OpenService failed. Error code: " + std::to_wstring(lastError) + L". " + buffer;//std::string utf8Str = wideToUtf8(errorMessage);std::wcout << errorMessage << std::endl;throw std::runtime_error(wstringToUtf8String(errorMessage));//throw std::runtime_error(errorMessage);
}
测试代码
#include "ServicesControl.h" // 包含 ServicesControl 类的定义
#include <memory>
#include <io.h>
#include <fcntl.h>using namespace WindowsServiceControl;std::string utf8ToGbk(const std::string& utf8Str)
{int size_needed = MultiByteToWideChar(CP_UTF8, 0, &utf8Str[0], (int)utf8Str.size(), NULL, 0);std::wstring wstrTo(size_needed, 0);MultiByteToWideChar(CP_UTF8, 0, &utf8Str[0], (int)utf8Str.size(), &wstrTo[0], size_needed);int size_needed_gbk = WideCharToMultiByte(CP_ACP, 0, &wstrTo[0], -1, NULL, 0, NULL, NULL);std::string strTo(size_needed_gbk, 0);WideCharToMultiByte(CP_ACP, 0, &wstrTo[0], -1, &strTo[0], size_needed_gbk, NULL, NULL);return strTo;
}int main()
{try {system("chcp 936");std::wcout.imbue(std::locale("chs"));std::wcout << "控制台输出中文" << std::endl;//setConsoleEncodingUTF8(); // 设置控制台编码为 UTF-8// 创建 ServicesControl 实例//ServicesControl svcCtrl(L"Delivery Optimization");auto svcCtrl = std::make_shared<WindowsServiceControl::ServicesControl>(L"Delivery Optimization");// 检查是否已具有管理员权限if (svcCtrl->isAdmin()) {std::cout << "Running with administrator permissions.\n";// 启动服务svcCtrl->startService(L"Delivery Optimization");std::cout << "Service started successfully.\n";// 停止服务svcCtrl->stopService(L"Delivery Optimization");std::cout << "Service stopped successfully.\n";}else {// 如果没有管理员权限,尝试提升权限svcCtrl->elevatePermissionsAndRun();}}catch (const std::runtime_error& e) {std::string str(e.what());std::string gbkStr = utf8ToGbk(str);std::cerr << "An error occurred: " << str << std::endl;return 1;}return 0;
}