1+ using System . Collections . ObjectModel ;
2+ using System . ComponentModel ;
13using System . Data ;
4+ using System . Diagnostics ;
25using System . Runtime . InteropServices ;
6+ using CommunityToolkit . WinUI . Controls ;
37using Microsoft . Extensions . Options ;
48using Microsoft . UI . Xaml ;
59using Microsoft . UI . Xaml . Controls ;
1317using UniGetUI . PackageEngine . Serializable ;
1418using UniGetUI . Pages . SettingsPages . GeneralPages ;
1519using Windows . ApplicationModel . Activation ;
20+ using Windows . Services . Maps ;
1621using Architecture = UniGetUI . PackageEngine . Enums . Architecture ;
1722
1823// To learn more about WinUI, the WinUI project structure,
@@ -32,6 +37,10 @@ public sealed partial class InstallOptionsPage : Page
3237 private readonly string packageInstallLocation ;
3338 private bool _uiLoaded ;
3439
40+ public ObservableCollection < IOP_Proc > ProcessesToKill = new ( ) ;
41+ private readonly ObservableCollection < IOP_Proc > _runningProcesses = new ( ) ;
42+ public ObservableCollection < IOP_Proc > SuggestedProcesses = new ( ) ;
43+
3544 public InstallOptionsPage ( IPackage package , InstallOptions options ) : this ( package , OperationType . None , options ) { }
3645 public InstallOptionsPage ( IPackage package , OperationType operation , InstallOptions options )
3746 {
@@ -82,6 +91,7 @@ async Task LoadImage()
8291 _ = LoadImage ( ) ;
8392 DialogTitle . Text = CoreTools . Translate ( "{0} installation options" , package . Name ) ;
8493 PlaceholderText . Text = CoreTools . Translate ( "{0} Install options are currently locked because {0} follows the default install options." , package . Name ) ;
94+ KillProcessesBox . PlaceholderText = CoreTools . Translate ( "Write here the process names, separed by commas (,)" ) ;
8595
8696 packageInstallLocation = Package . Manager . DetailsHelper . GetInstallLocation ( package ) ?? CoreTools . Translate ( "Unset or unknown" ) ;
8797
@@ -154,20 +164,35 @@ async Task LoadImage()
154164 }
155165 }
156166
167+ foreach ( var p in Options . KillBeforeOperation )
168+ {
169+ ProcessesToKill . Add ( new ( p ) ) ;
170+ }
157171
158172 if ( Options . CustomInstallLocation == "" ) CustomInstallLocation . Text = packageInstallLocation ;
159173 else CustomInstallLocation . Text = Options . CustomInstallLocation ;
160174
161-
162175 CustomParameters1 . Text = string . Join ( ' ' , Options . CustomParameters_Install ) ;
163176 CustomParameters2 . Text = string . Join ( ' ' , Options . CustomParameters_Update ) ;
164177 CustomParameters3 . Text = string . Join ( ' ' , Options . CustomParameters_Uninstall ) ;
165178
166179 _uiLoaded = true ;
167180 EnableDisableControls ( operation ) ;
168181 LoadIgnoredUpdates ( ) ;
182+ _ = _loadProcesses ( ) ;
169183 }
170184
185+ private async Task _loadProcesses ( )
186+ {
187+ var processNames = await Task . Run ( ( ) =>
188+ Process . GetProcesses ( ) . Select ( p => p . ProcessName ) . Distinct ( ) . ToList ( ) ) ;
189+
190+ _runningProcesses . Clear ( ) ;
191+ foreach ( var name in processNames )
192+ {
193+ if ( name . Any ( ) ) _runningProcesses . Add ( new ( name + ".exe" ) ) ;
194+ }
195+ }
171196 private void EnableDisableControls ( OperationType operation )
172197 {
173198 if ( FollowGlobalOptionsSwitch . IsOn )
@@ -188,13 +213,17 @@ private void EnableDisableControls(OperationType operation)
188213
189214 AdminCheckBox . IsEnabled = Package . Manager . Capabilities . CanRunAsAdmin ;
190215 InteractiveCheckBox . IsEnabled = Package . Manager . Capabilities . CanRunInteractively ;
191- HashCheckbox . IsEnabled = operation != OperationType . Uninstall && Package . Manager . Capabilities . CanSkipIntegrityChecks ;
192- ArchitectureComboBox . IsEnabled = operation != OperationType . Uninstall && Package . Manager . Capabilities . SupportsCustomArchitectures ;
216+ HashCheckbox . IsEnabled =
217+ operation is not OperationType . Uninstall
218+ && Package . Manager . Capabilities . CanSkipIntegrityChecks ;
219+
220+ ArchitectureComboBox . IsEnabled =
221+ operation is not OperationType . Uninstall
222+ && Package . Manager . Capabilities . SupportsCustomArchitectures ;
223+
193224 VersionComboBox . IsEnabled =
194- ( operation == OperationType . Install
195- || operation == OperationType . None )
196- && ( Package . Manager . Capabilities . SupportsCustomVersions
197- || Package . Manager . Capabilities . SupportsPreRelease ) ;
225+ operation is OperationType . Install or OperationType . None
226+ && ( Package . Manager . Capabilities . SupportsCustomVersions || Package . Manager . Capabilities . SupportsPreRelease ) ;
198227 ScopeCombo . IsEnabled = Package . Manager . Capabilities . SupportsCustomScopes ;
199228 ResetDir . IsEnabled = Package . Manager . Capabilities . SupportsCustomLocations ;
200229 SelectDir . IsEnabled = Package . Manager . Capabilities . SupportsCustomLocations ;
@@ -269,6 +298,9 @@ public async Task<InstallOptions> GetUpdatedOptions(bool updateIgnoredUpdates =
269298 Options . CustomParameters_Uninstall = CustomParameters3 . Text . Split ( ' ' ) . ToList ( ) ;
270299 Options . PreRelease = VersionComboBox . SelectedValue . ToString ( ) == CoreTools . Translate ( "PreRelease" ) ;
271300
301+ Options . KillBeforeOperation . Clear ( ) ;
302+ foreach ( var p in ProcessesToKill ) Options . KillBeforeOperation . Add ( p . Name ) ;
303+
272304 if ( VersionComboBox . SelectedValue . ToString ( ) != CoreTools . Translate ( "PreRelease" ) && VersionComboBox . SelectedValue . ToString ( ) != CoreTools . Translate ( "Latest" ) )
273305 {
274306 Options . Version = VersionComboBox . SelectedValue . ToString ( ) ?? "" ;
@@ -363,5 +395,50 @@ private void GoToSecureSettings_Click(object sender, RoutedEventArgs e)
363395 Close ? . Invoke ( this , EventArgs . Empty ) ;
364396 MainApp . Instance . MainWindow . NavigationPage . OpenSettingsPage ( typeof ( Administrator ) ) ;
365397 }
398+
399+ private void KillProcessesBox_TokenItemAdding ( TokenizingTextBox sender , TokenItemAddingEventArgs args )
400+ {
401+ args . Item = _runningProcesses . FirstOrDefault ( ( item ) => item . Name . Contains ( args . TokenText ) ) ;
402+ if ( args . Item is null )
403+ {
404+ string text = args . TokenText ;
405+ if ( ! text . EndsWith ( ".exe" ) ) text += ".exe" ;
406+ args . Item = new IOP_Proc ( text ) ;
407+ }
408+ }
409+
410+ private async void KillProcessesBox_TextChanged ( AutoSuggestBox sender , AutoSuggestBoxTextChangedEventArgs args )
411+ {
412+ var text = KillProcessesBox . Text ;
413+ await Task . Delay ( 100 ) ;
414+ if ( text != KillProcessesBox . Text )
415+ return ;
416+
417+ SuggestedProcesses . Clear ( ) ;
418+ if ( text . Trim ( ) != "" )
419+ {
420+ if ( ! text . EndsWith ( ".exe" ) )
421+ text = text . Trim ( ) + ".exe" ;
422+ SuggestedProcesses . Add ( new ( text ) ) ;
423+ foreach ( var item in _runningProcesses . Where ( x => x . Name . Contains ( KillProcessesBox . Text ) ) )
424+ {
425+ SuggestedProcesses . Add ( item ) ;
426+ }
427+ }
428+ }
429+
430+ private void KillProcessesBox_Loaded ( object sender , RoutedEventArgs e )
431+ {
432+
433+ }
434+ }
435+
436+ public class IOP_Proc
437+ {
438+ public readonly string Name ;
439+ public IOP_Proc ( string name )
440+ {
441+ Name = name ;
442+ }
366443 }
367444}
0 commit comments