系列文章目录
文章目录
- 系列文章目录
- 前言
- 一、中文乱码原因
- 二、解决方法
- 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,setting
std::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 privileges
if (!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 finish
WaitForSingleObject(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 command
if (!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 command
if (!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 stop
while (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;
}
输出打印