@@ -208,6 +208,56 @@ impl WebDriver {
208208
209209 fn spawn_process ( & self , driver_path : & Option < PathBuf > , port : u32 ) -> Result < Child > {
210210 let driver_path = driver_path. as_ref ( ) . unwrap ( ) ; // Safe unwrap since we validated above
211+
212+ let mut command = Self :: create_command ( driver_path, port) ;
213+ Self :: log_command ( & command) ;
214+
215+ match command. spawn ( ) {
216+ Ok ( child) => Ok ( child) ,
217+ Err ( e) => {
218+ #[ cfg( not( target_os = "windows" ) ) ]
219+ {
220+ Err ( self . handle_spawn_error ( e, & command, "standard method" ) )
221+ }
222+ #[ cfg( target_os = "windows" ) ]
223+ {
224+ self . spawn_with_fallback ( driver_path, port, e, & command)
225+ }
226+ }
227+ }
228+ }
229+
230+ /// Windows-specific fallback spawn method when CREATE_NO_WINDOW fails
231+ #[ cfg( target_os = "windows" ) ]
232+ fn spawn_with_fallback (
233+ & self ,
234+ driver_path : & PathBuf ,
235+ port : u32 ,
236+ original_error : std:: io:: Error ,
237+ original_command : & Command ,
238+ ) -> Result < Child > {
239+ // If CREATE_NO_WINDOW fails, try without any special flags
240+ error ! ( "Failed to spawn with CREATE_NO_WINDOW: {original_error}" ) ;
241+ error ! ( "Trying without special creation flags..." ) ;
242+
243+ let mut fallback_command = Self :: standard_command ( driver_path, port) ;
244+ Self :: log_command ( & fallback_command) ;
245+
246+ match fallback_command. spawn ( ) {
247+ Ok ( child) => {
248+ info ! ( "Successfully spawned WebDriver without special creation flags" ) ;
249+ Ok ( child)
250+ }
251+ Err ( fallback_e) => {
252+ error ! ( "Original error: {original_error}" ) ;
253+ error ! ( "Fallback error: {fallback_e}" ) ;
254+ Err ( self . handle_spawn_error ( fallback_e, & fallback_command, "fallback method" ) )
255+ }
256+ }
257+ }
258+
259+ /// Creates a command with standard configuration (no Windows flags)
260+ fn standard_command ( driver_path : & PathBuf , port : u32 ) -> Command {
211261 let mut command = Command :: new ( driver_path) ;
212262 command. arg ( format ! ( "--port={port}" ) ) ;
213263
@@ -220,81 +270,60 @@ impl WebDriver {
220270 . stdout ( Stdio :: piped ( ) )
221271 . stderr ( Stdio :: piped ( ) ) ;
222272
273+ command
274+ }
275+
276+ /// Creates a command with Windows-specific flags
277+ #[ cfg( target_os = "windows" ) ]
278+ fn create_command ( driver_path : & PathBuf , port : u32 ) -> Command {
279+ use std:: os:: windows:: process:: CommandExt ;
280+
281+ let mut command = Self :: standard_command ( driver_path, port) ;
282+ // Try with CREATE_NO_WINDOW for headless operation
283+ command. creation_flags ( 0x08000000 ) ; // CREATE_NO_WINDOW flag
284+ command
285+ }
286+
287+ #[ cfg( not( target_os = "windows" ) ) ]
288+ fn create_command ( driver_path : & PathBuf , port : u32 ) -> Command {
289+ Self :: standard_command ( driver_path, port)
290+ }
291+
292+ /// Logs command execution details
293+ fn log_command ( command : & Command ) {
223294 info ! (
224295 "Executing command: {:?} {:?}" ,
225296 command. get_program( ) ,
226297 command. get_args( )
227298 ) ;
299+ }
300+
301+ /// Handles spawn errors with appropriate logging and diagnostics
302+ fn handle_spawn_error (
303+ & self ,
304+ e : std:: io:: Error ,
305+ command : & Command ,
306+ attempt : & str ,
307+ ) -> anyhow:: Error {
308+ error ! ( "Failed to spawn '{WEBDRIVER_BIN}' with {attempt}: {e}" ) ;
309+ error ! (
310+ "Command was: {:?} {:?}" ,
311+ command. get_program( ) ,
312+ command. get_args( )
313+ ) ;
228314
229315 #[ cfg( target_os = "windows" ) ]
230- {
231- use std:: os:: windows:: process:: CommandExt ;
232- // Try with CREATE_NO_WINDOW for headless operation
233- command. creation_flags ( 0x08000000 ) ; // CREATE_NO_WINDOW flag
316+ if attempt == "CREATE_NO_WINDOW" {
317+ error ! ( "Windows: Check if antivirus is blocking the process" ) ;
318+ error ! ( "Windows: Check if the binary has proper permissions" ) ;
234319 }
235320
236- // Try to spawn the process
237- match command. spawn ( ) {
238- Ok ( child) => Ok ( child) ,
239- Err ( e) => {
240- #[ cfg( target_os = "windows" ) ]
241- {
242- // If CREATE_NO_WINDOW fails, try without any special flags
243- error ! ( "Failed to spawn with CREATE_NO_WINDOW: {e}" ) ;
244- error ! ( "Trying without special creation flags..." ) ;
245-
246- let mut fallback_command = Command :: new ( driver_path) ;
247- fallback_command. arg ( format ! ( "--port={port}" ) ) ;
248-
249- #[ cfg( feature = "chromedriver" ) ]
250- fallback_command. arg ( "--verbose" ) ;
251-
252- fallback_command
253- . stdin ( Stdio :: piped ( ) )
254- . stdout ( Stdio :: piped ( ) )
255- . stderr ( Stdio :: piped ( ) ) ;
256-
257- match fallback_command. spawn ( ) {
258- Ok ( child) => {
259- info ! ( "Successfully spawned WebDriver without special creation flags" ) ;
260- Ok ( child)
261- }
262- Err ( fallback_e) => {
263- error ! ( "Failed to spawn '{WEBDRIVER_BIN}' with fallback method: {fallback_e}" ) ;
264- error ! ( "Original error: {e}" ) ;
265- error ! ( "Fallback error: {fallback_e}" ) ;
266- error ! (
267- "Command was: {:?} {:?}" ,
268- command. get_program( ) ,
269- command. get_args( )
270- ) ;
271- error ! ( "Windows: Check if antivirus is blocking the process" ) ;
272- error ! ( "Windows: Check if the binary has proper permissions" ) ;
273- error ! (
274- "WebDriver diagnostics after spawn failure:\n {}" ,
275- self . get_diagnostics( )
276- ) ;
277- Err ( anyhow ! ( "Failed to spawn '{WEBDRIVER_BIN}': {}" , fallback_e) )
278- }
279- }
280- }
321+ error ! (
322+ "WebDriver diagnostics after spawn failure:\n {}" ,
323+ self . get_diagnostics( )
324+ ) ;
281325
282- #[ cfg( not( target_os = "windows" ) ) ]
283- {
284- error ! ( "Failed to spawn '{WEBDRIVER_BIN}': {e}" ) ;
285- error ! (
286- "Command was: {:?} {:?}" ,
287- command. get_program( ) ,
288- command. get_args( )
289- ) ;
290- error ! (
291- "WebDriver diagnostics after spawn failure:\n {}" ,
292- self . get_diagnostics( )
293- ) ;
294- Err ( anyhow ! ( "Failed to spawn '{WEBDRIVER_BIN}': {}" , e) )
295- }
296- }
297- }
326+ anyhow ! ( "Failed to spawn '{WEBDRIVER_BIN}': {}" , e)
298327 }
299328
300329 fn setup_output_monitoring ( & self , child : & mut Child , port : u32 ) {
0 commit comments