#! perl if ( @ARGV[0] ) { die( "\nBkAllDrv.pl, Version 2.21 for Windows 2000 / XP\n", "Backup all device drivers installed on your PC\n\n", "Usage: BKALLDRV.PL [ /A ]\n\n", "Where: /A forces ALL drivers to be backed up, including inactive ones\n\n", "Notes: [1] This script requires Microsoft's DEVCON utility, available at:\n", " http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q311272\n", " [2] A directory \"Drivers\\\" will be created in the current\n", " directory; drivers will be backed up in subdirectories.\n", " [3] In the \"Drivers\\\" directory, a log file \"bkalldrv.log\"\n", " will be created, which can aid in restoring backed up drivers.\n", " [4] If duplicate device names exist, they will be backed up in the\n", " same directory.\n", " [5] Existing files will be overwritten unless they are read-only.\n", " [6] This script will abort on directory or log file creation errors,\n", " but not on file copy errors.\n\n", "Written by Rob van der Woude\nhttp://www.robvanderwoude.com\n" ) unless uc( @ARGV[0] ) eq "/A"; } # Check command line argument if ( @ARGV[0] ) { $find = "FindAll" } else { $find = "Find" } # Reset counters $devcount = 0; $dircount = 0; $errcount = 0; $filecount = 0; # External modules use File::Copy; use Sys::Hostname; # Get host name $host = hostname(); # Create backup target directory for this particular host mkdir "Drivers"; mkdir "Drivers\\$host"; if ( $! ) { die "Error $! while creating directory Drivers\\$host: $^E\n" unless ( $! eq "File exists" ) } # Display message print "\nGathering driver information, please wait...\n\n"; # Variable used to check if DEVCON.EXE is available $missing = 1; # Create empty log files open( LOG, "> ./Drivers/$host/bkalldrv.log" ) or die( "Error creating log file.\n" ); open( ERROR, "> ./Drivers/$host/bkalldrv.err" ) or die( "Error creating error log file.\n" ); # List all hardware IDs using DEVCON.EXE, then use # DEVCON.EXE again to list the associated driver files foreach ( `devcon.exe $find * 2>nul \| find.exe \"\\\"` ) { if ( $_ =~ m/^([^:\s]+)\s*:\s*([^\s][^\n]+)$/ ) { # On match assume DEVCON.EXE is available $missing = 0; $hwid = $1; $name = $2; # $dirname is "escaped" $name $dirname = $2; $dirname =~ s/\//_/g; $dirname =~ s/,/ /g; $dirname =~ s/:/ /g; $dirname =~ s/;/ /g; $dirname =~ s/ / /g; $dirname =~ s/&/_and_/g; $dirname =~ s/\(/[/g; $dirname =~ s/\)/]/g; $dirname =~ s/^\s*([^\s].*[^\s])\s*$/$1/; if ( $name ) { # Find and copy driver files for this particular hardware # ID, and keep count of the total number of files copied foreach ( `devcon.exe DriverFiles \"\@$hwid\"` ) { SELECT: { if ( $_ =~ m/^ ([A-Z]:\\[^\n]+)$/i ) { if ( copy( $1, "Drivers\\$host\\$class\\$dirname" ) ) { $filecount = $filecount + 1; } else { $msg = "Error copying $1 to Drivers\\$host\\$class\\$dirname: $!\n $^E\n"; print $msg; print ERROR "[".( $errcount + 1 )."] $msg"; $errcount = $errcount + 1; } last SELECT; } if ( $_ =~ m/^ Driver installed from ([A-Z]:\\[^\[]+) \[[^\]]+\]\. (No|[0-9]+) file\(?s?\)? used by driver.?$/i ) { if ( copy( $1, "Drivers\\$host\\$class\\$dirname" ) ) { $filecount = $filecount + 1; } else { $msg = "Error copying $1 to Drivers\\$host\\$class\\$dirname: $!\n $^E\n"; print $msg; print ERROR "[".( $errcount + 1 )."] $msg"; $errcount = $errcount + 1; } if ( $1 =~ m/.*\\([^\\]+)$/ ) { $inf = "\\$1"; } else { $inf = ""; } # Log hardware ID and associated INF file print LOG ( $devcount + 1 )."\t$hwid\t$class\\$dirname"."$inf\n"; last SELECT; } if ( $_ =~ m/^([^\s][^\\]+)\\.+/i ) { $class = $1; mkdir "Drivers\\$host\\$class"; if ( $! ) { $descr = $!; $msg = "Error creating directory Drivers\\$host\\$class: $!\n $^E\n"; if ( $descr ne "File exists" and $descr ne "Bad file descriptor" ) { print ERROR "[".( $errcount + 1 )."] $msg"; close( ERROR ); die $msg; } } last SELECT; } if ( $_ =~ m/^ Name: ([^\$]+)$/i ) { print "Backing up driver files for $1"; mkdir "Drivers\\$host\\$class\\$dirname"; if ( $! ) { $descr = $!; $msg = "Error creating directory Drivers\\$host\\$class\\$dirname: $!\n $^E\n"; if ( $descr ne "File exists" and $descr ne "Bad file descriptor" ) { print ERROR "[".( $errcount + 1 )."] $msg"; close( ERROR ); die $msg; } } $dircount = $dircount + 1; last SELECT; } if ( $_ =~ m/^(No|[0-9]+) matching device\(?s?\)? found.?$/i ) { if ( uc( $1 ) ne "NO" ) { $devcount = $devcount + 1; } } } } } } } # Close log files close( LOG ); close( ERROR ); # Display error message if DEVCON.EXE isn't available if ( $missing ) { print( "DEVCON.EXE not found! Please download it at:\n", "http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q311272\n" ) } # Display summary print "\nBacked up $filecount driver files for $devcount devices\n"; if ( $errcount ) { print( "\n$errcount errors were encountered while copying; please check the\n", "error log \"Drivers\\$host\\bkalldrv.err\" for missed files.\n" ); } else { unlink ERROR; }