shell.dart 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import 'dart:ffi';
  2. import 'dart:io';
  3. import 'package:flutter/services.dart';
  4. import 'package:process_run/shell.dart';
  5. import 'package:path/path.dart' as path;
  6. import 'package:naiyouwl/app/const/const.dart';
  7. import 'package:naiyouwl/app/utils/logger.dart';
  8. import 'package:wl_base_help/wl_base_help.dart';
  9. Future<void> killProcess(String name) async {
  10. log.debug("kill: ", name);
  11. if (Platform.isWindows) {
  12. await Process.run('taskkill', ["/F", "/FI", "IMAGENAME eq $name"]);
  13. } else {
  14. await Process.run('bash', ["-c", "ps -ef | grep $name | grep -v grep | awk '{print \$2}' | xargs kill -9"]);
  15. }
  16. }
  17. Future<bool> isRunningAsAdmin() async {
  18. final Shell shell = Shell();
  19. try {
  20. if (Platform.isWindows) {
  21. // Windows: 使用 "net session" 检查管理员权限
  22. final List<ProcessResult> results = await shell.run('net session');
  23. if (results.isNotEmpty && results[0].exitCode == 0) {
  24. return true;
  25. }
  26. } else if (Platform.isMacOS || Platform.isLinux) {
  27. // macOS / Linux: 使用 "id -u" 检查管理员权限
  28. final List<ProcessResult> results = await shell.run('id -u');
  29. if (results.isNotEmpty && results[0].stdout.trim() == '0') {
  30. return true;
  31. }
  32. }
  33. } catch (e) {
  34. // 如果出现异常 (如 ShellException),默认认为没有管理员权限
  35. return false;
  36. }
  37. return false;
  38. }
  39. Future<bool> killCCoreProcess(int pid) async {
  40. return Process.killPid(pid);
  41. }
  42. Future<ProcessResult> runCCore(String executable, List<String> arguments) async {
  43. String executablePath = shellArgument(executable).replaceAll(' ', r'\\ ');
  44. if (Platform.isMacOS) {
  45. return await Process.run(
  46. path.join(Paths.assetsBin.path, executablePath),
  47. [executable, ...arguments],
  48. );
  49. } else if (Platform.isWindows) {
  50. return await Process.run(
  51. path.join(Paths.assetsBin.path, executablePath),
  52. [executable, ...arguments],
  53. );
  54. } else {
  55. // https://blog.csdn.net/weixin_49867936/article/details/109612918
  56. // https://askubuntu.com/questions/287845/how-to-configure-pkexec
  57. return await Process.run("pkexec", [executable, ...arguments]);
  58. }
  59. }
  60. Future<ProcessResult> runCCoreAsAdmin(String executable, List<String> arguments) async {
  61. // String executablePath = shellArgument(executable).replaceAll(' ', r'\\ ');
  62. return await Process.run(
  63. path.join(Paths.assetsBin.path, "run-as-admin.bat"),
  64. [executable, ...arguments],
  65. );
  66. }
  67. Future<String?> getKeychainPassword() async {
  68. final result = await Process.run('security', [
  69. 'find-generic-password',
  70. '-a', 'naiyout',
  71. '-s', 'sudo_password',
  72. '-w'
  73. ]);
  74. return result.exitCode == 0 ? result.stdout.trim() : null;
  75. }
  76. Future<bool> hasSavedPassword() async {
  77. final password = await getKeychainPassword();
  78. return password != null;
  79. }
  80. Future<bool> testSudoPassword(String password) async {
  81. final result = await Process.run('bash', [
  82. '-c',
  83. 'echo "$password" | sudo -S echo "test"'
  84. ]);
  85. return result.exitCode == 0;
  86. }
  87. Future<void> saveKeychainPassword(String password) async {
  88. // 先测试密码是否正确
  89. if (!await testSudoPassword(password)) {
  90. throw Exception("密码不正确");
  91. }
  92. // 删除旧密码(如果存在)
  93. await Process.run('security', [
  94. 'delete-generic-password',
  95. '-a', 'naiyout',
  96. '-s', 'sudo_password'
  97. ]);
  98. // 保存新密码
  99. await Process.run('security', [
  100. 'add-generic-password',
  101. '-a', 'naiyout',
  102. '-s', 'sudo_password',
  103. '-w', password
  104. ]);
  105. }
  106. Future<ProcessResult> runAsAdmin(String executable, List<String> arguments) async {
  107. String executablePath = shellArgument(executable).replaceAll(' ', r'\\ ');
  108. //executablePath = executablePath.substring(1, executablePath.length - 1);
  109. if (Platform.isMacOS) {
  110. return await Process.run(
  111. 'osascript',
  112. [
  113. '-e',
  114. shellArguments(['do', 'shell', 'script', '$executablePath ${shellArguments(arguments)}', 'with', 'administrator', 'privileges']),
  115. ],
  116. );
  117. } else if (Platform.isWindows) {
  118. return await Process.run(
  119. path.join(Paths.assetsBin.path, "run-as-admin.bat"),
  120. [executable, ...arguments],
  121. );
  122. } else {
  123. // https://blog.csdn.net/weixin_49867936/article/details/109612918
  124. // https://askubuntu.com/questions/287845/how-to-configure-pkexec
  125. return await Process.run("pkexec", [executable, ...arguments]);
  126. }
  127. }
  128. // Platform messages are asynchronous, so we initialize in an async method.
  129. Future<String> platformState() async {
  130. String platformVersion;
  131. if(Platform.isWindows){
  132. try {
  133. final _wlBaseHelpPlugin = WlBaseHelp();
  134. platformVersion =
  135. await _wlBaseHelpPlugin.getPlatformVersion() ?? 'Unknown platform version';
  136. platformVersion = platformVersion + ClashName.architecture.name;
  137. } on PlatformException {
  138. platformVersion = 'Failed to get platform version.';
  139. }
  140. return platformVersion;
  141. }
  142. else {
  143. return ClashName.os.name + "-" + ClashName.architecture.name;
  144. }
  145. }
  146. Future<void> onRunAdmin() async {
  147. if(Platform.isWindows){
  148. try {
  149. final _wlBaseHelpPlugin = WlBaseHelp();
  150. await _wlBaseHelpPlugin.runAsAdministrator();
  151. } on PlatformException {
  152. }
  153. }
  154. }
  155. Future<bool> onIsRunAdmin() async {
  156. bool isAdmin;
  157. try {
  158. final _wlBaseHelpPlugin = WlBaseHelp();
  159. isAdmin = await _wlBaseHelpPlugin.isRunningAsAdmin() ?? false;
  160. } on PlatformException {
  161. isAdmin = false;
  162. }
  163. return isAdmin;
  164. }
  165. Future<bool> onIsProcessRunning(String passName) async {
  166. bool isRun = false;
  167. if(Platform.isWindows){
  168. try {
  169. final _wlBaseHelpPlugin = WlBaseHelp();
  170. isRun = await _wlBaseHelpPlugin.isProcessRunning(passName) ?? false;
  171. if (isRun){
  172. await onKillProcess(passName);
  173. }
  174. } on PlatformException {
  175. isRun = false;
  176. }
  177. }
  178. return isRun;
  179. }
  180. Future<void> onKillProcess(String passName) async {
  181. try {
  182. final _wlBaseHelpPlugin = WlBaseHelp();
  183. await _wlBaseHelpPlugin.killProcess(passName);
  184. } on PlatformException {
  185. }
  186. }