Skip to content

Commit baaa655

Browse files
committed
win_package improvements
- add download and download-path args - add cert key usage check
1 parent a57c55c commit baaa655

6 files changed

Lines changed: 99 additions & 40 deletions

File tree

src/lib/core/performance/performance_service.dart

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,11 @@ class PerformanceService {
124124
}
125125

126126
Future<void> enableMemoryCompression() async {
127-
await _shell.run(
128-
'PowerShell -NonInteractive -NoLogo -NoProfile -Command "Enable-MMAgent -mc"',
129-
);
127+
await runPSCommand('Enable-MMAgent -mc');
130128
}
131129

132130
Future<void> disableMemoryCompression() async {
133-
await _shell.run(
134-
'PowerShell -NonInteractive -NoLogo -NoProfile -Command "Disable-MMAgent -mc"',
135-
);
131+
await runPSCommand('Disable-MMAgent -mc');
136132
}
137133

138134
bool get statusIntelTSX {

src/lib/core/security/security_command.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ import 'dart:io';
33

44
import 'package:args/command_runner.dart';
55

6-
import 'package:process_run/shell_run.dart';
76
import 'package:revitool/core/security/security_service.dart';
87
import 'package:revitool/utils.dart';
98

109
class SecurityCommand extends Command<String> {
1110
static final _securityService = SecurityService();
12-
static final _shell = Shell();
1311
String get tag => "[Security - Defender]";
1412

1513
@override
@@ -71,8 +69,8 @@ Virus and Threat Protections Status: ${_securityService.statusDefenderProtection
7169
}
7270

7371
if (!_securityService.statusDefenderProtectionTamper) {
74-
await _shell.run(
75-
'PowerShell -EP Unrestricted -NonInteractive -NoLogo -NoP Set-MpPreference -DisableRealtimeMonitoring \$true',
72+
await runPSCommand(
73+
'Set-MpPreference -DisableRealtimeMonitoring \$true',
7674
);
7775
break;
7876
}

src/lib/core/security/security_service.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,8 @@ class SecurityService {
324324
);
325325

326326
if (File(_mpCmdRunString).existsSync()) {
327-
await _shell.run(
328-
"PowerShell -EP Unrestricted -NonInteractive -NoLogo -NoP -C 'Start-Process -FilePath \"$_mpCmdRunString\" -ArgumentList \"-RemoveDefinitions -All\" -NoNewWindow -Wait'",
327+
await runPSCommand(
328+
'Start-Process -FilePath "$_mpCmdRunString" -ArgumentList "-RemoveDefinitions -All" -NoNewWindow -Wait',
329329
);
330330
}
331331

src/lib/core/winsxs/win_package_command.dart

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,16 @@ import 'dart:async';
22
import 'dart:io';
33

44
import 'package:args/command_runner.dart';
5-
import 'package:process_run/shell_run.dart';
65
import 'package:revitool/core/ms_store/ms_store_command.dart';
76
import 'package:revitool/core/security/security_service.dart';
87
import 'package:revitool/core/winsxs/win_package_service.dart';
98
import 'package:revitool/shared/win_registry_service.dart';
9+
import 'package:revitool/utils.dart';
1010

1111
class WindowsPackageCommand extends Command<String> {
1212
static final _winPackageService = WinPackageService();
1313
static final _msStoreCommand = MSStoreCommand();
1414
static final _securityService = SecurityService();
15-
static final _shell = Shell();
1615

1716
static const tag = "[Windows Package]";
1817

@@ -23,6 +22,21 @@ class WindowsPackageCommand extends Command<String> {
2322
String get name => 'winpackage';
2423

2524
WindowsPackageCommand() {
25+
argParser.addOption(
26+
'download',
27+
help: 'Downloads a package',
28+
29+
allowed: const [
30+
'system-components-removal',
31+
'defender-removal',
32+
'ai-removal',
33+
],
34+
);
35+
argParser.addOption(
36+
'download-path',
37+
help: 'Custom download path for packages',
38+
defaultsTo: WinPackageService.cabPath,
39+
);
2640
argParser.addOption(
2741
'install',
2842
help: 'Install a package',
@@ -48,7 +62,12 @@ class WindowsPackageCommand extends Command<String> {
4862
final installOption = argResults?.option('install');
4963
final uninstallOption = argResults?.option('uninstall');
5064

51-
if (installOption != null) {
65+
final downloadOption = argResults?.option('download');
66+
final downloadPath = argResults?.option('download-path');
67+
68+
if (downloadOption != null) {
69+
await _downloadPackage(downloadOption, downloadPath);
70+
} else if (installOption != null) {
5271
await _installPackage(installOption);
5372
} else if (uninstallOption != null) {
5473
await _uninstallPackage(getPackageType(uninstallOption));
@@ -71,6 +90,23 @@ class WindowsPackageCommand extends Command<String> {
7190
}
7291
}
7392

93+
Future<void> _downloadPackage(
94+
final String parameter,
95+
final String? path,
96+
) async {
97+
try {
98+
final mode = getPackageType(parameter);
99+
stdout.writeln('$tag Downloading package: ${mode.packageName}');
100+
final packagePath = await _winPackageService.downloadPackage(
101+
mode,
102+
path: path,
103+
);
104+
stdout.writeln(packagePath);
105+
} catch (e) {
106+
stderr.writeln('$tag $e');
107+
}
108+
}
109+
74110
Future<void> _installPackage(final String parameter) async {
75111
try {
76112
final mode = getPackageType(parameter);
@@ -89,11 +125,11 @@ class WindowsPackageCommand extends Command<String> {
89125
if (mode == WinPackageType.aiRemoval) {
90126
WinRegistryService.hidePageVisibilitySettings("aicomponents");
91127
WinRegistryService.hidePageVisibilitySettings("privacy-systemaimodels");
92-
await _shell.run(
93-
'PowerShell -EP Unrestricted -NonInteractive -NoLogo -NoP -C "Disable-WindowsOptionalFeature -Online -FeatureName Recall -NoRestart"',
128+
await runPSCommand(
129+
'Disable-WindowsOptionalFeature -Online -FeatureName Recall -NoRestart',
94130
);
95-
await _shell.run(
96-
'PowerShell -EP Unrestricted -NonInteractive -NoLogo -NoP -C "Get-AppxPackage -AllUsers Microsoft.Copilot* | Remove-AppxPackage"',
131+
await runPSCommand(
132+
'Get-AppxPackage -AllUsers Microsoft.Copilot* | Remove-AppxPackage',
97133
);
98134
}
99135
} catch (e) {
@@ -111,8 +147,8 @@ class WindowsPackageCommand extends Command<String> {
111147
if (packageType == WinPackageType.aiRemoval) {
112148
WinRegistryService.unhidePageVisibilitySettings("aicomponents");
113149
WinRegistryService.unhidePageVisibilitySettings("privacy-systemaimodels");
114-
await _shell.run(
115-
'PowerShell -EP Unrestricted -NonInteractive -NoLogo -NoP -C "Enable-WindowsOptionalFeature -Online -FeatureName Recall -NoRestart"',
150+
await runPSCommand(
151+
'Enable-WindowsOptionalFeature -Online -FeatureName Recall -NoRestart',
116152
);
117153
await _msStoreCommand.installPackage(
118154
id: "9nht9rb2f4hd",

src/lib/core/winsxs/win_package_service.dart

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import 'dart:io';
22
import 'package:collection/collection.dart';
33
import 'package:path/path.dart' as p;
4-
import 'package:process_run/shell.dart';
54
import 'package:revitool/shared/network_service.dart';
65
import 'package:revitool/shared/win_registry_service.dart';
6+
import 'package:revitool/utils.dart';
77

88
import 'package:win32_registry/win32_registry.dart';
99

@@ -25,7 +25,6 @@ class WinPackageService {
2525
const WinPackageService._private();
2626

2727
static final _networkService = NetworkService();
28-
static final _shell = Shell();
2928

3029
static final cabPath = p.join(
3130
Directory.systemTemp.path,
@@ -65,15 +64,13 @@ class WinPackageService {
6564
lastError == null;
6665
}
6766

68-
Future<String> downloadPackage(final WinPackageType packageType) async {
69-
final cabPath = p.join(Directory.systemTemp.path, 'Revision-Tool', 'CAB');
70-
if (await Directory(cabPath).exists()) {
71-
try {
72-
await Directory(cabPath).delete(recursive: true);
73-
} catch (e) {
74-
stderr.writeln('Failed to delete CAB directory: $e');
75-
}
76-
}
67+
Future<String> downloadPackage(
68+
final WinPackageType packageType, {
69+
String? path,
70+
}) async {
71+
final downloadPath = path ?? cabPath;
72+
73+
Directory(downloadPath).createSync(recursive: true);
7774

7875
final List<dynamic> assests = (await _networkService.getGHLatestRelease(
7976
ApiEndpoints.cabPackages,
@@ -90,30 +87,44 @@ class WinPackageService {
9087
throw 'No matching package found for ${packageType.packageName} with architecture ${WinRegistryService.cpuArch}';
9188
}
9289

93-
final downloadPath = "$cabPath\\$name";
94-
await _networkService.downloadFile(downloadUrl, downloadPath);
95-
if (!File(downloadPath).existsSync()) {
90+
final filePath = p.join(downloadPath, name);
91+
92+
await _networkService.downloadFile(downloadUrl, filePath);
93+
if (!File(filePath).existsSync()) {
9694
throw 'Failed to download package: $name';
9795
}
9896

99-
return downloadPath;
97+
return filePath;
10098
}
10199

102100
Future<void> installPackage(final String packagePath) async {
101+
if (!File(packagePath).existsSync()) {
102+
throw 'Package file does not exist: $packagePath';
103+
}
104+
105+
String certValue = await runPSCommand(
106+
'(Get-AuthenticodeSignature -FilePath "$packagePath").SignerCertificate.Extensions.EnhancedKeyUsages.Value',
107+
);
108+
109+
if (certValue.isEmpty || certValue != '1.3.6.1.4.1.311.10.3.6') {
110+
throw '[win_package] invalid signature: $packagePath';
111+
}
112+
103113
WinRegistryService.createKey(
104114
Registry.localMachine,
105115
r'Software\Microsoft\SystemCertificates\ROOT\Certificates\8A334AA8052DD244A647306A76B8178FA215F344',
106116
);
107117

108118
// running it via TrustedInstaller causes 'Win32 internal error "Access is denied" 0x5 occurred while reading the console output buffer'
109-
await _shell.run(
110-
"powershell -EP Unrestricted -NoLogo -NonInteractive -NoP -C \"Add-WindowsPackage -Online -NoRestart -IgnoreCheck -PackagePath '$packagePath'\"",
119+
await runPSCommand(
120+
'Add-WindowsPackage -Online -NoRestart -IgnoreCheck -PackagePath "$packagePath"',
111121
);
122+
await File(packagePath).delete();
112123
}
113124

114125
Future<void> uninstallPackage(final WinPackageType packageType) async {
115-
await _shell.run(
116-
'PowerShell -EP Unrestricted -NonInteractive -NoLogo -NoP -C "Get-WindowsPackage -Online -PackageName \'${packageType.packageName}*\' | Remove-WindowsPackage -Online -NoRestart"',
126+
await runPSCommand(
127+
'Get-WindowsPackage -Online -PackageName "${packageType.packageName}*" | Remove-WindowsPackage -Online -NoRestart',
117128
);
118129
}
119130
}

src/lib/utils.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,21 @@ bool isProcessRunning(String name) {
8282

8383
return result == 1;
8484
}
85+
86+
/// PowerShell helper for executing commands with faster startup time
87+
Future<String> runPSCommand(String command) async {
88+
final result = await Process.run('powershell', [
89+
'-EP Unrestricted',
90+
'-NoProfile',
91+
'-NonInteractive',
92+
'-NoLogo',
93+
'-Command',
94+
command,
95+
], runInShell: true);
96+
97+
if (result.exitCode != 0) {
98+
throw Exception('PowerShell command failed: ${result.stderr}');
99+
}
100+
101+
return result.stdout.toString();
102+
}

0 commit comments

Comments
 (0)