@@ -241,72 +241,94 @@ def _aks_bastion_get_current_shell_cmd():
241241 ppid = os .getppid ()
242242 parent = psutil .Process (ppid )
243243 parent_name = parent .name ()
244- logger .debug (f "Immediate parent process: { parent_name } (PID: { ppid } )" )
244+ logger .debug ("Immediate parent process: %s (PID: %s)" , parent_name , ppid )
245245
246246 # On Windows, Azure CLI is often invoked as az.cmd, which means the immediate parent
247247 # is cmd.exe but the actual user shell (PowerShell) is the grandparent process
248- if sys .platform .startswith ("win" ):
249- try :
250- parent_exe = parent .exe ()
251- logger .debug (f"Parent executable path: { parent_exe } " )
252-
253- # If the immediate parent is cmd.exe, check if it's wrapping az.cmd for PowerShell
254- if "cmd" in parent_name .lower ():
255- try :
256- # Get the grandparent process (parent of cmd.exe)
257- grandparent = parent .parent ()
258- if grandparent :
259- grandparent_name = grandparent .name ()
260- logger .debug (f"Detected grandparent process: { grandparent_name } (PID: { grandparent .pid } )" )
261-
262- # If grandparent is PowerShell, that's the actual user shell
263- if "pwsh" in grandparent_name .lower () or "powershell" in grandparent_name .lower ():
264- logger .debug ("Grandparent is PowerShell - using PowerShell as target shell" )
265- # Try to find pwsh first, fall back to powershell
266- pwsh_path = shutil .which ("pwsh" )
267- if pwsh_path :
268- logger .debug (f"Found pwsh at: { pwsh_path } " )
269- return "pwsh"
270- powershell_path = shutil .which ("powershell" )
271- if powershell_path :
272- logger .debug (f"Found powershell at: { powershell_path } " )
273- return "powershell"
274- # If we can't find pwsh/powershell in PATH, use the detected grandparent
275- logger .debug ("PowerShell not found in PATH, using detected grandparent executable" )
276- return grandparent .exe () if grandparent .exe () else grandparent_name
277- # If grandparent is not PowerShell, stick with cmd
278- else :
279- logger .debug ("Grandparent is not PowerShell - using cmd as target shell" )
280- return "cmd"
281- except (psutil .NoSuchProcess , psutil .AccessDenied ) as e :
282- # If we can't access grandparent, assume cmd is the actual shell
283- logger .debug (f"Cannot access grandparent process: { e } - using cmd as target shell" )
284- return "cmd"
285-
286- # For direct PowerShell processes (not wrapped by cmd), prefer pwsh over powershell.exe
287- elif "pwsh" in parent_name .lower () or "powershell" in parent_name .lower ():
288- logger .debug ("Direct PowerShell parent detected" )
289- # Try to find pwsh first, fall back to powershell
290- pwsh_path = shutil .which ("pwsh" )
291- if pwsh_path :
292- logger .debug (f"Found pwsh at: { pwsh_path } " )
293- return "pwsh"
294- powershell_path = shutil .which ("powershell" )
295- if powershell_path :
296- logger .debug (f"Found powershell at: { powershell_path } " )
297- return "powershell"
298- # If we can't find pwsh/powershell in PATH, use the detected parent
299- logger .debug ("PowerShell not found in PATH, using detected parent executable" )
300- return parent_exe if parent_exe else parent_name
301- else :
302- logger .debug (f"Other Windows shell detected: { parent_name } " )
303- return parent_exe if parent_exe else parent_name
304- except (psutil .NoSuchProcess , psutil .AccessDenied ) as e :
305- logger .debug (f"Cannot access parent process details: { e } " )
306- pass
307-
308- logger .debug (f"Using parent process name as shell: { parent_name } " )
309- return parent_name
248+ if not sys .platform .startswith ("win" ):
249+ logger .debug ("Using parent process name as shell: %s" , parent_name )
250+ return parent_name
251+
252+ return _get_windows_shell_cmd (parent , parent_name )
253+
254+
255+ def _get_windows_shell_cmd (parent , parent_name ):
256+ """Get the shell command on Windows, handling az.cmd wrapper scenarios."""
257+ try :
258+ parent_exe = parent .exe ()
259+ logger .debug ("Parent executable path: %s" , parent_exe )
260+
261+ # If the immediate parent is cmd.exe, check if it's wrapping az.cmd for PowerShell
262+ if "cmd" in parent_name .lower ():
263+ return _handle_cmd_parent (parent )
264+
265+ # For direct PowerShell processes (not wrapped by cmd)
266+ if "pwsh" in parent_name .lower () or "powershell" in parent_name .lower ():
267+ return _handle_powershell_parent (parent_exe , parent_name )
268+
269+ logger .debug ("Other Windows shell detected: %s" , parent_name )
270+ return parent_exe if parent_exe else parent_name
271+
272+ except (psutil .NoSuchProcess , psutil .AccessDenied ) as e :
273+ logger .debug ("Cannot access parent process details: %s" , e )
274+ return parent_name
275+
276+
277+ def _handle_cmd_parent (parent ):
278+ """Handle case where immediate parent is cmd.exe - check for PowerShell grandparent."""
279+ try :
280+ # Get the grandparent process (parent of cmd.exe)
281+ grandparent = parent .parent ()
282+ if not grandparent :
283+ return "cmd"
284+
285+ grandparent_name = grandparent .name ()
286+ logger .debug ("Detected grandparent process: %s (PID: %s)" , grandparent_name , grandparent .pid )
287+
288+ # If grandparent is PowerShell, that's the actual user shell
289+ if "pwsh" in grandparent_name .lower () or "powershell" in grandparent_name .lower ():
290+ return _get_powershell_executable (grandparent )
291+
292+ logger .debug ("Grandparent is not PowerShell - using cmd as target shell" )
293+ return "cmd"
294+
295+ except (psutil .NoSuchProcess , psutil .AccessDenied ) as e :
296+ # If we can't access grandparent, assume cmd is the actual shell
297+ logger .debug ("Cannot access grandparent process: %s - using cmd as target shell" , e )
298+ return "cmd"
299+
300+
301+ def _handle_powershell_parent (parent_exe , parent_name ):
302+ """Handle direct PowerShell parent process."""
303+ logger .debug ("Direct PowerShell parent detected" )
304+ return _get_powershell_executable_from_path () or parent_exe or parent_name
305+
306+
307+ def _get_powershell_executable (grandparent ):
308+ """Get PowerShell executable, preferring pwsh over powershell."""
309+ logger .debug ("Grandparent is PowerShell - using PowerShell as target shell" )
310+ powershell_cmd = _get_powershell_executable_from_path ()
311+ if powershell_cmd :
312+ return powershell_cmd
313+
314+ # If we can't find pwsh/powershell in PATH, use the detected grandparent
315+ logger .debug ("PowerShell not found in PATH, using detected grandparent executable" )
316+ return grandparent .exe () if grandparent .exe () else grandparent .name ()
317+
318+
319+ def _get_powershell_executable_from_path ():
320+ """Try to find PowerShell executable in PATH, preferring pwsh over powershell."""
321+ pwsh_path = shutil .which ("pwsh" )
322+ if pwsh_path :
323+ logger .debug ("Found pwsh at: %s" , pwsh_path )
324+ return "pwsh"
325+
326+ powershell_path = shutil .which ("powershell" )
327+ if powershell_path :
328+ logger .debug ("Found powershell at: %s" , powershell_path )
329+ return "powershell"
330+
331+ return None
310332
311333
312334def _aks_bastion_prepare_shell_cmd (kubeconfig_path ):
0 commit comments