@@ -208,95 +208,116 @@ 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- let mut command = Command :: new ( driver_path) ;
212- command. arg ( format ! ( "--port={port}" ) ) ;
213-
214- // Add verbose flag only for chromedriver
215- #[ cfg( feature = "chromedriver" ) ]
216- command. arg ( "--verbose" ) ;
217-
218- command
219- . stdin ( Stdio :: piped ( ) )
220- . stdout ( Stdio :: piped ( ) )
221- . stderr ( Stdio :: piped ( ) ) ;
222-
223- info ! (
224- "Executing command: {:?} {:?}" ,
225- command. get_program( ) ,
226- command. get_args( )
227- ) ;
228211
229- #[ 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
234- }
212+ let mut command = Self :: create_command ( driver_path, port) ;
213+ Self :: log_command ( & command) ;
235214
236- // Try to spawn the process
237215 match command. spawn ( ) {
238216 Ok ( child) => Ok ( child) ,
239217 Err ( e) => {
218+ #[ cfg( not( target_os = "windows" ) ) ]
219+ {
220+ Err ( self . handle_spawn_error ( e, & command, "standard method" ) )
221+ }
240222 #[ cfg( target_os = "windows" ) ]
241223 {
242224 // If CREATE_NO_WINDOW fails, try without any special flags
243225 error ! ( "Failed to spawn with CREATE_NO_WINDOW: {e}" ) ;
244226 error ! ( "Trying without special creation flags..." ) ;
245227
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 ( ) ) ;
228+ let mut fallback_command = Self :: standard_command ( driver_path, port) ;
229+ Self :: log_command ( & fallback_command) ;
256230
257231 match fallback_command. spawn ( ) {
258232 Ok ( child) => {
259233 info ! ( "Successfully spawned WebDriver without special creation flags" ) ;
260234 Ok ( child)
261235 }
262236 Err ( fallback_e) => {
263- error ! ( "Failed to spawn '{WEBDRIVER_BIN}' with fallback method: {fallback_e}" ) ;
264237 error ! ( "Original error: {e}" ) ;
265238 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) )
239+ Err ( self . handle_spawn_error (
240+ fallback_e,
241+ & fallback_command,
242+ "fallback method" ,
243+ ) )
278244 }
279245 }
280246 }
281-
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- }
296247 }
297248 }
298249 }
299250
251+ /// Creates a command with standard configuration (no Windows flags)
252+ fn standard_command ( driver_path : & PathBuf , port : u32 ) -> Command {
253+ let mut command = Command :: new ( driver_path) ;
254+ command. arg ( format ! ( "--port={port}" ) ) ;
255+
256+ // Add verbose flag only for chromedriver
257+ #[ cfg( feature = "chromedriver" ) ]
258+ command. arg ( "--verbose" ) ;
259+
260+ command
261+ . stdin ( Stdio :: piped ( ) )
262+ . stdout ( Stdio :: piped ( ) )
263+ . stderr ( Stdio :: piped ( ) ) ;
264+
265+ command
266+ }
267+
268+ /// Creates a command with Windows-specific flags
269+ #[ cfg( target_os = "windows" ) ]
270+ fn create_command ( driver_path : & PathBuf , port : u32 ) -> Command {
271+ use std:: os:: windows:: process:: CommandExt ;
272+
273+ let mut command = Self :: standard_command ( driver_path, port) ;
274+ // Try with CREATE_NO_WINDOW for headless operation
275+ command. creation_flags ( 0x08000000 ) ; // CREATE_NO_WINDOW flag
276+ command
277+ }
278+
279+ #[ cfg( not( target_os = "windows" ) ) ]
280+ fn create_command ( driver_path : & PathBuf , port : u32 ) -> Command {
281+ Self :: standard_command ( driver_path, port)
282+ }
283+
284+ /// Logs command execution details
285+ fn log_command ( command : & Command ) {
286+ info ! (
287+ "Executing command: {:?} {:?}" ,
288+ command. get_program( ) ,
289+ command. get_args( )
290+ ) ;
291+ }
292+
293+ /// Handles spawn errors with appropriate logging and diagnostics
294+ fn handle_spawn_error (
295+ & self ,
296+ e : std:: io:: Error ,
297+ command : & Command ,
298+ attempt : & str ,
299+ ) -> anyhow:: Error {
300+ error ! ( "Failed to spawn '{WEBDRIVER_BIN}' with {attempt}: {e}" ) ;
301+ error ! (
302+ "Command was: {:?} {:?}" ,
303+ command. get_program( ) ,
304+ command. get_args( )
305+ ) ;
306+
307+ #[ cfg( target_os = "windows" ) ]
308+ if attempt == "CREATE_NO_WINDOW" {
309+ error ! ( "Windows: Check if antivirus is blocking the process" ) ;
310+ error ! ( "Windows: Check if the binary has proper permissions" ) ;
311+ }
312+
313+ error ! (
314+ "WebDriver diagnostics after spawn failure:\n {}" ,
315+ self . get_diagnostics( )
316+ ) ;
317+
318+ anyhow ! ( "Failed to spawn '{WEBDRIVER_BIN}': {}" , e)
319+ }
320+
300321 fn setup_output_monitoring ( & self , child : & mut Child , port : u32 ) {
301322 // Monitor stderr
302323 if let Some ( stderr) = child. stderr . take ( ) {
0 commit comments