luat_console_win32.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include "luat_base.h"
  2. #ifdef LUAT_USE_WINDOWS
  3. #include <windows.h>
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <TlHelp32.h>
  7. #include <Psapi.h>
  8. // Windows控制台编码自动设置
  9. void luat_console_auto_encoding(void) {
  10. // 检测是否在Windows控制台环境中
  11. HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
  12. if (hStdout == INVALID_HANDLE_VALUE) {
  13. return; // 不在控制台中运行(可能是重定向或其他)
  14. }
  15. // 检测控制台模式
  16. DWORD mode = 0;
  17. if (!GetConsoleMode(hStdout, &mode)) {
  18. return; // 不是真正的控制台
  19. }
  20. // 获取当前控制台代码页
  21. UINT currentCP = GetConsoleOutputCP();
  22. // 如果已经是UTF-8,无需设置
  23. if (currentCP == 65001) {
  24. // 启用虚拟终端序列支持
  25. mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
  26. SetConsoleMode(hStdout, mode);
  27. return;
  28. }
  29. // 尝试检测父进程类型并相应设置编码
  30. DWORD parentPid = 0;
  31. HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  32. if (hSnapshot != INVALID_HANDLE_VALUE) {
  33. PROCESSENTRY32 pe32;
  34. pe32.dwSize = sizeof(PROCESSENTRY32);
  35. DWORD currentPid = GetCurrentProcessId();
  36. if (Process32First(hSnapshot, &pe32)) {
  37. do {
  38. if (pe32.th32ProcessID == currentPid) {
  39. parentPid = pe32.th32ParentProcessID;
  40. break;
  41. }
  42. } while (Process32Next(hSnapshot, &pe32));
  43. }
  44. // 查找父进程名称
  45. if (parentPid != 0) {
  46. HANDLE hParent = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, parentPid);
  47. if (hParent) {
  48. char szProcessName[MAX_PATH];
  49. if (GetModuleFileNameExA(hParent, NULL, szProcessName, MAX_PATH)) {
  50. char* pszFileName = strrchr(szProcessName, '\\');
  51. if (pszFileName) {
  52. pszFileName++;
  53. // 转换为小写进行比较
  54. for (char* p = pszFileName; *p; p++) {
  55. if (*p >= 'A' && *p <= 'Z') *p = *p + 32;
  56. }
  57. // 检测命令行类型并设置编码
  58. if (strstr(pszFileName, "cmd.exe")) {
  59. // CMD: 使用system调用chcp命令
  60. system("chcp 65001 >nul 2>&1");
  61. }
  62. else if (strstr(pszFileName, "powershell.exe") ||
  63. strstr(pszFileName, "pwsh.exe")) {
  64. // PowerShell: 直接设置控制台代码页
  65. SetConsoleOutputCP(65001);
  66. SetConsoleCP(65001);
  67. // 设置环境变量影响PowerShell行为
  68. SetEnvironmentVariableA("PYTHONIOENCODING", "utf-8");
  69. }
  70. else {
  71. // 其他情况,直接设置为UTF-8
  72. SetConsoleOutputCP(65001);
  73. SetConsoleCP(65001);
  74. }
  75. }
  76. }
  77. CloseHandle(hParent);
  78. }
  79. }
  80. CloseHandle(hSnapshot);
  81. }
  82. else {
  83. // 如果无法检测父进程,直接设置UTF-8
  84. SetConsoleOutputCP(65001);
  85. SetConsoleCP(65001);
  86. }
  87. // 启用虚拟终端序列支持
  88. mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
  89. SetConsoleMode(hStdout, mode);
  90. }
  91. #endif