55using System . IO ;
66using System . Linq ;
77using System . Text ;
8+ using System . Threading ;
89using System . Threading . Tasks ;
910using System . Windows . Forms ;
1011
@@ -95,8 +96,8 @@ public override void Activate(string templateName) {
9596 if ( String . IsNullOrEmpty ( executable ) ) {
9697 return ;
9798 }
98-
99- //string[] argv = CommandLineToArgv(executablePath, out int argc) ;
99+
100+ const int PROCESS_BY_NAME_STRICT_WAIT_FOR_EXIT_MILLISECONDS = 1000 ;
100101
101102 Process [ ] processesByName = null ;
102103 Stack < Process > processesByNameStrict = null ;
@@ -107,40 +108,54 @@ public override void Activate(string templateName) {
107108
108109 do {
109110 if ( processesByNameStrict != null ) {
110- // don't allow preceding further until
111- // all processes with the same name have been killed
112- DialogResult ? dialogResult = ShowClosableMessageBox (
113- Task . Run ( delegate ( ) {
114- // copy this, so it doesn't get set to null upon hitting OK
115- Stack < Process > _processesByNameStrict = new Stack < Process > ( processesByNameStrict ) ;
116-
117- while ( _processesByNameStrict . Any ( ) ) {
118- using ( Process processByNameStrict = _processesByNameStrict . Pop ( ) ) {
119- try {
120- if ( processByNameStrict != null ) {
121- processByNameStrict . WaitForExit ( ) ;
111+ using ( CancellationTokenSource cancellationTokenSource = new CancellationTokenSource ( ) ) {
112+ CancellationToken token = cancellationTokenSource . Token ;
113+
114+ // don't allow preceding further until
115+ // all processes with the same name have been killed
116+ DialogResult ? dialogResult = ShowClosableMessageBox (
117+ Task . Run ( delegate ( ) {
118+ // copy this, so it doesn't get set to null upon hitting OK
119+ Stack < Process > _processesByNameStrict = new Stack < Process > ( processesByNameStrict ) ;
120+
121+ while ( _processesByNameStrict . Any ( ) ) {
122+ using ( Process processByNameStrict = _processesByNameStrict . Pop ( ) ) {
123+ try {
124+ if ( processByNameStrict != null ) {
125+ // test for cancellation before waiting
126+ // (so we don't wait unnecessarily for the next processes after this one)
127+ while ( ! token . IsCancellationRequested ) {
128+ if ( processByNameStrict . WaitForExit ( PROCESS_BY_NAME_STRICT_WAIT_FOR_EXIT_MILLISECONDS ) ) {
129+ break ;
130+ }
131+ }
132+ }
133+ } catch {
134+ // fail silently
135+ // (ensure we dispose every process)
122136 }
123- } catch {
124- // fail silently
125- // (ensure we dispose every process)
126137 }
127138 }
128- }
129- } ) ,
130-
131- String . Format (
132- Properties . Resources . ProcessCompatibilityConflict ,
133- activeProcessName
134- ) ,
135-
136- Properties . Resources . FlashpointSecurePlayer ,
137- MessageBoxButtons . OKCancel ,
138- MessageBoxIcon . Warning
139- ) ;
140-
141- if ( dialogResult == DialogResult . Cancel ) {
142- Application . Exit ( ) ;
143- throw new InvalidModificationException ( "The operation was aborted by the user." ) ;
139+ } ) ,
140+
141+ String . Format (
142+ Properties . Resources . ProcessCompatibilityConflict ,
143+ activeProcessName
144+ ) ,
145+
146+ Properties . Resources . FlashpointSecurePlayer ,
147+ MessageBoxButtons . OKCancel ,
148+ MessageBoxIcon . Warning
149+ ) ;
150+
151+ // end the task passed to the Closable Message Box
152+ // we'll be creating a new one on the next loop as necessary
153+ cancellationTokenSource . Cancel ( ) ;
154+
155+ if ( dialogResult == DialogResult . Cancel ) {
156+ Application . Exit ( ) ;
157+ throw new InvalidModificationException ( "The operation was aborted by the user." ) ;
158+ }
144159 }
145160
146161 processesByNameStrict = null ;
0 commit comments