@@ -2,6 +2,8 @@ use schemars::JsonSchema;
22use serde:: { Deserialize , Serialize } ;
33use std:: { borrow:: Cow , fmt, path:: Path , sync:: LazyLock } ;
44
5+ use crate :: command:: new_std_command;
6+
57/// Shell configuration to open the terminal with.
68#[ derive( Clone , Debug , Default , Serialize , Deserialize , PartialEq , Eq , JsonSchema , Hash ) ]
79#[ serde( rename_all = "snake_case" ) ]
@@ -108,16 +110,12 @@ pub fn get_windows_system_shell() -> String {
108110 use std:: path:: PathBuf ;
109111
110112 fn find_pwsh_in_programfiles ( find_alternate : bool , find_preview : bool ) -> Option < PathBuf > {
111- #[ cfg( target_pointer_width = "64" ) ]
112- let env_var = if find_alternate {
113- "ProgramFiles(x86)"
114- } else {
115- "ProgramFiles"
116- } ;
117-
118- #[ cfg( target_pointer_width = "32" ) ]
119113 let env_var = if find_alternate {
120- "ProgramW6432"
114+ if cfg ! ( target_pointer_width = "64" ) {
115+ "ProgramFiles(x86)"
116+ } else {
117+ "ProgramW6432"
118+ }
121119 } else {
122120 "ProgramFiles"
123121 } ;
@@ -165,23 +163,19 @@ pub fn get_windows_system_shell() -> String {
165163 } else {
166164 "Microsoft.PowerShell_"
167165 } ;
168- msix_app_dir
169- . read_dir ( )
170- . ok ( ) ?
171- . filter_map ( |entry| {
172- let entry = entry. ok ( ) ?;
173- if !matches ! ( entry. file_type( ) , Ok ( ft) if ft. is_dir( ) ) {
174- return None ;
175- }
166+ msix_app_dir. read_dir ( ) . ok ( ) ?. find_map ( |entry| {
167+ let entry = entry. ok ( ) ?;
168+ if !matches ! ( entry. file_type( ) , Ok ( ft) if ft. is_dir( ) ) {
169+ return None ;
170+ }
176171
177- if !entry. file_name ( ) . to_string_lossy ( ) . starts_with ( prefix) {
178- return None ;
179- }
172+ if !entry. file_name ( ) . to_string_lossy ( ) . starts_with ( prefix) {
173+ return None ;
174+ }
180175
181- let exe_path = entry. path ( ) . join ( "pwsh.exe" ) ;
182- exe_path. exists ( ) . then_some ( exe_path)
183- } )
184- . next ( )
176+ let exe_path = entry. path ( ) . join ( "pwsh.exe" ) ;
177+ exe_path. exists ( ) . then_some ( exe_path)
178+ } )
185179 }
186180
187181 fn find_pwsh_in_scoop ( ) -> Option < PathBuf > {
@@ -190,15 +184,37 @@ pub fn get_windows_system_shell() -> String {
190184 pwsh_exe. exists ( ) . then_some ( pwsh_exe)
191185 }
192186
187+ // check whether the found powershell is executable for us
193188 static SYSTEM_SHELL : LazyLock < String > = LazyLock :: new ( || {
194- find_pwsh_in_programfiles ( false , false )
195- . or_else ( || find_pwsh_in_programfiles ( true , false ) )
196- . or_else ( || find_pwsh_in_msix ( false ) )
197- . or_else ( || find_pwsh_in_programfiles ( false , true ) )
198- . or_else ( || find_pwsh_in_msix ( true ) )
199- . or_else ( || find_pwsh_in_programfiles ( true , true ) )
200- . or_else ( find_pwsh_in_scoop)
201- . map ( |p| p. to_string_lossy ( ) . into_owned ( ) )
189+ let can_execute_pwsh = |p : & PathBuf | {
190+ #[ allow( clippy:: disallowed_methods) ]
191+ let status = new_std_command ( p) . arg ( "-NoProfile" ) . arg ( "-Help" ) . status ( ) ;
192+ let success = status. as_ref ( ) . is_ok_and ( |status| status. success ( ) ) ;
193+ if !success {
194+ log:: warn!(
195+ "Powershell found at `{}` is not executable: {status:?}" ,
196+ p. display( )
197+ ) ;
198+ }
199+ success
200+ } ;
201+
202+ let locations = [
203+ || find_pwsh_in_programfiles ( false , false ) ,
204+ || find_pwsh_in_programfiles ( true , false ) ,
205+ || find_pwsh_in_msix ( false ) ,
206+ || find_pwsh_in_programfiles ( false , true ) ,
207+ || find_pwsh_in_msix ( true ) ,
208+ || find_pwsh_in_programfiles ( true , true ) ,
209+ || find_pwsh_in_scoop ( ) ,
210+ || which:: which_global ( "pwsh.exe" ) . ok ( ) ,
211+ || which:: which_global ( "powershell.exe" ) . ok ( ) ,
212+ ] ;
213+ locations
214+ . into_iter ( )
215+ . filter_map ( |f| f ( ) )
216+ . find ( |p| can_execute_pwsh ( & p) )
217+ . map ( |p| p. to_string_lossy ( ) . trim ( ) . to_owned ( ) )
202218 . inspect ( |shell| log:: info!( "Found powershell in: {}" , shell) )
203219 . unwrap_or_else ( || {
204220 log:: warn!( "Powershell not found, falling back to `cmd`" ) ;
0 commit comments