2023-10-09 09:32:07 +08:00
|
|
|
import 'dart:io';
|
|
|
|
|
2023-11-21 23:36:26 +08:00
|
|
|
import 'package:hive/hive.dart';
|
2024-03-01 20:59:43 +08:00
|
|
|
import 'package:starcitizen_doctor/common/utils/log.dart';
|
2023-10-09 09:32:07 +08:00
|
|
|
|
|
|
|
class SystemHelper {
|
2023-11-07 22:35:25 +08:00
|
|
|
static String powershellPath = "powershell.exe";
|
|
|
|
|
2023-11-10 21:58:29 +08:00
|
|
|
static initPowershellPath() async {
|
2024-03-23 17:53:42 +08:00
|
|
|
try {
|
|
|
|
var result = await Process.run(powershellPath, ["echo", "ping"]);
|
|
|
|
if (!result.stdout.toString().startsWith("ping") &&
|
|
|
|
powershellPath == "powershell.exe") {
|
|
|
|
throw "powershell check failed";
|
|
|
|
}
|
|
|
|
} catch (e) {
|
2023-11-07 22:35:25 +08:00
|
|
|
Map<String, String> envVars = Platform.environment;
|
|
|
|
final systemRoot = envVars["SYSTEMROOT"];
|
|
|
|
if (systemRoot != null) {
|
|
|
|
final autoSearchPath =
|
|
|
|
"$systemRoot\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
|
|
|
|
dPrint("auto search powershell path === $autoSearchPath");
|
|
|
|
powershellPath = autoSearchPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-09 09:32:07 +08:00
|
|
|
static Future<bool> checkNvmePatchStatus() async {
|
|
|
|
try {
|
2023-11-07 22:35:25 +08:00
|
|
|
var result = await Process.run(SystemHelper.powershellPath, [
|
2023-10-09 09:32:07 +08:00
|
|
|
"Get-ItemProperty",
|
|
|
|
"-Path",
|
|
|
|
"\"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\stornvme\\Parameters\\Device\"",
|
|
|
|
"-Name",
|
|
|
|
"\"ForcedPhysicalSectorSizeInBytes\""
|
|
|
|
]);
|
|
|
|
dPrint("checkNvmePatchStatus result ==== ${result.stdout}");
|
|
|
|
if (result.stderr == "" &&
|
|
|
|
result.stdout.toString().contains("{* 4095}")) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Future<String> addNvmePatch() async {
|
2023-11-13 22:52:40 +08:00
|
|
|
var result = await Process.run(powershellPath, [
|
2023-10-09 09:32:07 +08:00
|
|
|
'New-ItemProperty',
|
|
|
|
"-Path",
|
|
|
|
"\"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\stornvme\\Parameters\\Device\"",
|
|
|
|
"-Name",
|
|
|
|
"ForcedPhysicalSectorSizeInBytes",
|
|
|
|
"-PropertyType MultiString",
|
|
|
|
"-Force -Value",
|
|
|
|
"\"* 4095\""
|
|
|
|
]);
|
|
|
|
dPrint("nvme_PhysicalBytes result == ${result.stdout}");
|
|
|
|
return result.stderr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static doRemoveNvmePath() async {
|
|
|
|
try {
|
2023-11-13 22:52:40 +08:00
|
|
|
var result = await Process.run(powershellPath, [
|
2023-10-09 09:32:07 +08:00
|
|
|
"Clear-ItemProperty",
|
|
|
|
"-Path",
|
|
|
|
"\"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\stornvme\\Parameters\\Device\"",
|
|
|
|
"-Name",
|
|
|
|
"\"ForcedPhysicalSectorSizeInBytes\""
|
|
|
|
]);
|
|
|
|
dPrint("doRemoveNvmePath result ==== ${result.stdout}");
|
|
|
|
if (result.stderr == "") {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 获取 RSI 启动器 目录
|
|
|
|
static Future<String> getRSILauncherPath() async {
|
2023-11-21 23:36:26 +08:00
|
|
|
final confBox = await Hive.openBox("app_conf");
|
|
|
|
final path = confBox.get("custom_launcher_path");
|
|
|
|
if (path != null && path != "") {
|
|
|
|
if (await File(path).exists()) {
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-09 09:32:07 +08:00
|
|
|
Map<String, String> envVars = Platform.environment;
|
|
|
|
final programDataPath = envVars["programdata"];
|
|
|
|
final rsiFilePath =
|
|
|
|
"$programDataPath\\Microsoft\\Windows\\Start Menu\\Programs\\Roberts Space Industries\\RSI Launcher.lnk";
|
|
|
|
final rsiLinkFile = File(rsiFilePath);
|
|
|
|
if (await rsiLinkFile.exists()) {
|
2023-11-07 22:35:25 +08:00
|
|
|
final r = await Process.run(SystemHelper.powershellPath, [
|
2023-10-09 09:32:07 +08:00
|
|
|
"(New-Object -ComObject WScript.Shell).CreateShortcut(\"$rsiFilePath\").targetpath"
|
|
|
|
]);
|
|
|
|
if (r.stdout.toString().contains("RSI Launcher.exe")) {
|
|
|
|
final start = r.stdout.toString().split("RSI Launcher.exe");
|
|
|
|
return "${start[0]}RSI Launcher.exe";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
static killRSILauncher() async {
|
|
|
|
var psr = await Process.run(
|
2023-11-10 21:58:29 +08:00
|
|
|
powershellPath, ["ps", "\"RSI Launcher\"", "|select -expand id"]);
|
2023-10-09 09:32:07 +08:00
|
|
|
if (psr.stderr == "") {
|
|
|
|
for (var value in (psr.stdout ?? "").toString().split("\n")) {
|
|
|
|
dPrint(value);
|
|
|
|
if (value != "") {
|
|
|
|
Process.killPid(int.parse(value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Future<List<String>> getPID(String name) async {
|
2023-11-10 21:58:29 +08:00
|
|
|
final r = await Process.run(powershellPath, ["(ps $name).Id"]);
|
2023-10-13 21:58:25 +08:00
|
|
|
final str = r.stdout.toString().trim();
|
|
|
|
dPrint(str);
|
|
|
|
if (str.isEmpty) return [];
|
|
|
|
return str.split("\n");
|
2023-10-09 09:32:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static checkAndLaunchRSILauncher(String path) async {
|
|
|
|
// check running and kill
|
|
|
|
await killRSILauncher();
|
|
|
|
// launch
|
2023-11-28 20:04:15 +08:00
|
|
|
final processorAffinity = await SystemHelper.getCpuAffinity();
|
|
|
|
if (processorAffinity == null) {
|
|
|
|
Process.run(path, []);
|
|
|
|
} else {
|
|
|
|
Process.run("cmd.exe", [
|
|
|
|
'/C',
|
|
|
|
'Start',
|
|
|
|
'""',
|
|
|
|
'/High',
|
|
|
|
'/Affinity',
|
|
|
|
processorAffinity,
|
|
|
|
path,
|
|
|
|
]);
|
|
|
|
}
|
2023-10-09 09:32:07 +08:00
|
|
|
dPrint(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Future<int> getSystemMemorySizeGB() async {
|
2023-11-10 21:58:29 +08:00
|
|
|
final r = await Process.run(powershellPath, [
|
2023-10-09 09:32:07 +08:00
|
|
|
"(Get-CimInstance Win32_PhysicalMemory | Measure-Object -Property capacity -Sum).sum /1gb"
|
|
|
|
]);
|
|
|
|
return int.tryParse(r.stdout.toString().trim()) ?? 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Future<String> getSystemCimInstance(String win32InstanceName,
|
|
|
|
{pathName = "Name"}) async {
|
|
|
|
final r = await Process.run(
|
2023-11-10 21:58:29 +08:00
|
|
|
powershellPath, ["(Get-CimInstance $win32InstanceName).$pathName"]);
|
2023-10-09 09:32:07 +08:00
|
|
|
return r.stdout.toString().trim();
|
|
|
|
}
|
|
|
|
|
|
|
|
static Future<String> getSystemName() async {
|
|
|
|
final r = await Process.run(
|
2023-11-10 21:58:29 +08:00
|
|
|
powershellPath, ["(Get-ComputerInfo | Select-Object -expand OsName)"]);
|
2023-10-09 09:32:07 +08:00
|
|
|
return r.stdout.toString().trim();
|
|
|
|
}
|
|
|
|
|
2023-10-29 17:10:39 +08:00
|
|
|
static Future<String> getCpuName() async {
|
|
|
|
final r = await Process.run(
|
2023-11-10 21:58:29 +08:00
|
|
|
powershellPath, ["(Get-WmiObject -Class Win32_Processor).Name"]);
|
2023-10-29 17:10:39 +08:00
|
|
|
return r.stdout.toString().trim();
|
|
|
|
}
|
|
|
|
|
2023-10-09 09:32:07 +08:00
|
|
|
static Future<String> getGpuInfo() async {
|
|
|
|
const cmd = r"""
|
|
|
|
$adapterMemory = (Get-ItemProperty -Path "HKLM:\SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0*" -Name "HardwareInformation.AdapterString", "HardwareInformation.qwMemorySize" -Exclude PSPath -ErrorAction SilentlyContinue)
|
|
|
|
foreach ($adapter in $adapterMemory) {
|
|
|
|
[PSCustomObject] @{
|
|
|
|
Model=$adapter."HardwareInformation.AdapterString"
|
|
|
|
"VRAM (GB)"=[math]::round($adapter."HardwareInformation.qwMemorySize"/1GB)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
""";
|
2023-11-10 21:58:29 +08:00
|
|
|
final r = await Process.run(powershellPath, [cmd]);
|
2023-10-09 09:32:07 +08:00
|
|
|
return r.stdout.toString().trim();
|
|
|
|
}
|
|
|
|
|
|
|
|
static Future<String> getDiskInfo() async {
|
2023-11-10 21:58:29 +08:00
|
|
|
return (await Process.run(powershellPath,
|
2023-10-09 09:32:07 +08:00
|
|
|
["Get-PhysicalDisk | format-table BusType,FriendlyName,Size"]))
|
|
|
|
.stdout
|
|
|
|
.toString()
|
|
|
|
.trim();
|
|
|
|
}
|
|
|
|
|
|
|
|
static Future<int> getDirLen(String path, {List<String>? skipPath}) async {
|
|
|
|
if (path == "") return 0;
|
|
|
|
int totalSize = 0;
|
|
|
|
try {
|
|
|
|
final l = await Directory(path).list(recursive: true).toList();
|
|
|
|
for (var element in l) {
|
|
|
|
if (element is File) {
|
|
|
|
bool skip = false;
|
|
|
|
if (skipPath != null) {
|
|
|
|
for (var value in skipPath) {
|
|
|
|
if (element.absolute.path.startsWith(value)) {
|
|
|
|
skip = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!skip) totalSize += await element.length();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (_) {}
|
|
|
|
return totalSize;
|
|
|
|
}
|
2023-11-21 01:05:20 +08:00
|
|
|
|
|
|
|
static Future<int> getNumberOfLogicalProcessors() async {
|
|
|
|
final cpuNumberResult = await Process.run(powershellPath,
|
|
|
|
["(Get-WmiObject -Class Win32_Processor).NumberOfLogicalProcessors"]);
|
|
|
|
if (cpuNumberResult.exitCode != 0) return 0;
|
|
|
|
return int.tryParse(cpuNumberResult.stdout.toString().trim()) ?? 0;
|
|
|
|
}
|
|
|
|
|
2023-11-28 20:04:15 +08:00
|
|
|
static Future<String?> getCpuAffinity() async {
|
|
|
|
final confBox = await Hive.openBox("app_conf");
|
|
|
|
final eCoreCount = int.tryParse(
|
|
|
|
confBox.get("gameLaunch_eCore_count", defaultValue: "0")) ??
|
|
|
|
0;
|
2023-11-21 01:05:20 +08:00
|
|
|
final cpuNumber = await getNumberOfLogicalProcessors();
|
2023-11-23 22:30:00 +08:00
|
|
|
if (cpuNumber == 0 || eCoreCount == 0 || eCoreCount > cpuNumber) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuffer sb = StringBuffer();
|
|
|
|
for (var i = 0; i < cpuNumber; i++) {
|
|
|
|
if (i < eCoreCount) {
|
|
|
|
sb.write("0");
|
|
|
|
} else {
|
|
|
|
sb.write("1");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
final binaryString = sb.toString();
|
|
|
|
int hexDigits = (binaryString.length / 4).ceil();
|
|
|
|
dPrint("Affinity sb ==== $sb");
|
|
|
|
return int.parse(binaryString, radix: 2)
|
|
|
|
.toRadixString(16)
|
|
|
|
.padLeft(hexDigits, '0')
|
|
|
|
.toUpperCase();
|
2023-11-21 01:05:20 +08:00
|
|
|
}
|
2024-02-24 14:42:33 +08:00
|
|
|
|
2024-03-31 15:53:56 +08:00
|
|
|
static Future openDir(path, {bool isFile = false}) async {
|
2024-02-24 14:42:33 +08:00
|
|
|
dPrint("SystemHelper.openDir path === $path");
|
|
|
|
await Process.run(
|
2024-04-12 20:02:00 +08:00
|
|
|
SystemHelper.powershellPath, ["explorer.exe", isFile ? "/select,$path" : "\"/select,\"$path\"\""]);
|
2024-02-24 14:42:33 +08:00
|
|
|
}
|
2024-03-12 22:08:46 +08:00
|
|
|
|
|
|
|
static String getHostsFilePath() {
|
|
|
|
final envVars = Platform.environment;
|
|
|
|
final systemRoot = envVars["SYSTEMROOT"];
|
|
|
|
return "$systemRoot\\System32\\drivers\\etc\\hosts";
|
|
|
|
}
|
2023-10-09 09:32:07 +08:00
|
|
|
}
|