系列文章目录

文章目录
  • 系列文章目录
  • 前言
  • 一、中文乱码原因
  • 二、解决方法
  • 1.如果是windos11下,使用英文语言,需要加以下代码
  • 2.如果是中文语言只需要一行关键代码
  • 3.如果在异常处理中显示宽字符中文
  • 4.完整代码如下:
  • 实现文件
  • 测试代码
  • 输出打印

前言

我们在win32编程中使用宽字符,std::wstring经常会遇到中文乱码的情况,比方说在调试时,查看std::string类型的字符串是显示字符串的字符无效,其实这时候已经中文乱码了,还有就是在控制台输出时也会出现中文乱码。

std::wcout,std::cout控制台输出中文乱码,std::cerr字符串的字符无效_#include

std::wcout,std::cout控制台输出中文乱码,std::cerr字符串的字符无效_std wstring中文乱码_02

一、中文乱码原因

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"));
  • 1.
  • 2.
2.如果是中文语言只需要一行关键代码
std::wcout.imbue(std::locale("chs"));
  • 1.
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;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
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);
	};
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
实现文件
#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);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
测试代码
#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;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
输出打印

std::wcout,std::cout控制台输出中文乱码,std::cerr字符串的字符无效_std wstring中文乱码_03