diff --git a/includes/install.core.inc b/includes/install.core.inc
index 38ad724..794b15b 100644
--- a/includes/install.core.inc
+++ b/includes/install.core.inc
@@ -1585,19 +1585,6 @@
 }
 
 /**
- * Batch callback for batch installation of modules.
- */
-function _install_module_batch($module, $module_name, &$context) {
-  // Install and enable the module right away, so that the module will be
-  // loaded by drupal_bootstrap in subsequent batch requests, and other
-  // modules possibly depending on it can safely perform their installation
-  // steps.
-  module_enable(array($module), FALSE);
-  $context['results'][] = $module;
-  $context['message'] = st('Installed %module module.', array('%module' => $module_name));
-}
-
-/**
  * 'Finished' callback for module installation batch.
  */
 function _install_profile_modules_finished($success, $results, $operations) {
diff --git a/includes/install.inc b/includes/install.inc
index 71de3e6..5b0a056 100644
--- a/includes/install.inc
+++ b/includes/install.inc
@@ -1330,3 +1330,38 @@
   $task_class = 'DatabaseTasks_' . $driver;
   return new $task_class();
 }
+
+/**
+ * Batch callback for batch installation of modules.
+ */
+function _install_module_batch($module, $module_name, &$context) {
+  // Install and enable the module right away, so that the module will be
+  // loaded by drupal_bootstrap in subsequent batch requests, and other
+  // modules possibly depending on it can safely perform their installation
+  // steps.
+  module_enable(array($module), FALSE);
+  $context['results'][] = $module;
+  $context['message'] = st('Installed %module module.', array('%module' => $module_name));
+}
+
+/**
+ * Batch callback for batch uninstallation of modules.
+ */
+function _uninstall_module_batch($module, $module_name, &$context) {
+  module_disable(array($module), FALSE);
+  $context['results'][] = $module;
+  $context['message'] = st('Uninstalled %module module.', array('%module' => $module_name));
+}
+
+/**
+ * Batch finish callback for bath installation / uninstallation of modules.
+ */
+function _install_modules_batch_finished($success, $results, $operations) {
+  if ($success && count($results)) {
+    drupal_flush_all_caches();
+    drupal_set_message(st('The configuration options have been saved.'));
+  }
+  else if(!$success) {
+    drupal_set_message(st('An error occured while trying to save onfiguration options.'));
+  }
+}
diff --git a/modules/simpletest/tests/module_test.module b/modules/simpletest/tests/module_test.module
index d781350..164388b 100644
--- a/modules/simpletest/tests/module_test.module
+++ b/modules/simpletest/tests/module_test.module
@@ -104,12 +104,25 @@
 }
 
 /**
- * Implements hook_modules_enabled().
+ * Implements hook_batch_alter().
  */
-function module_test_modules_enabled($modules) {
-  // Record the ordered list of modules that were passed in to this hook so we
-  // can check that the modules were enabled in the correct sequence.
-  variable_set('test_module_enable_order', $modules);
+function module_test_batch_alter(&$batch) {
+  // Check if we've got a module form submit batch by verifying it's
+  // finished callback.
+  $set = $batch['sets'][$batch['current_set']];
+  if (isset($set['finished']) &&
+  $set['finished'] == '_install_modules_batch_finished') {
+    $modules = array();
+    foreach ($set['operations'] as $weight => $operation) {
+      list($callback, $info) = $operation;
+      list($module, $name) = $info;
+      $modules[$weight] = $module;
+    }
+    // Get the ordered list of modules that were passed in to the batch so we
+    // can check that the modules would have been enabled in the correct
+    // sequence.
+    variable_set('test_module_enable_order', $modules);
+  }
 }
 
 /**
diff --git a/modules/system/system.admin.inc b/modules/system/system.admin.inc
index b6f6789..ad1d8a2 100644
--- a/modules/system/system.admin.inc
+++ b/modules/system/system.admin.inc
@@ -1221,19 +1221,29 @@
   // Reverse the 'enable' list, to order dependencies before dependents.
   krsort($actions['enable']);
 
-  // Installs, enables, and disables modules.
-  module_enable($actions['enable'], FALSE);
-  module_disable($actions['disable'], FALSE);
+  // Make sure we redirect to modules page after batch process.
+  $form_state['redirect'] = 'admin/modules';
 
-  // Gets module list after install process, flushes caches and displays a
-  // message if there are changes.
-  $post_install_list = module_list(TRUE);
-  if ($pre_install_list != $post_install_list) {
-    drupal_flush_all_caches();
-    drupal_set_message(t('The configuration options have been saved.'));
+  // Prepare the batch operations and set the batch.
+  $operations = array();
+  foreach ($actions['enable'] as $weight => $module) {
+    $operations[] = array('_install_module_batch', array($module, $files[$module]->info['name']));
+  }
+  foreach ($actions['disable'] as $weight => $module) {
+    $operations[] = array('_uninstall_module_batch', array($module, $files[$module]->info['name']));
   }
 
-  $form_state['redirect'] = 'admin/modules';
+  // Prevent starting a batch with no operation.
+  if (count($operations)) {
+    $batch = array(
+      'operations' => $operations,
+      'title' => t('Updating modules.'),
+      'error_message' => t('The installation has encountered an error.'),
+      'finished' => '_install_modules_batch_finished',
+      'file' => 'includes/install.inc',
+    );
+    batch_set($batch);
+  }
 }
 
 /**
diff --git a/modules/system/system.test b/modules/system/system.test
index cae5cc7..a7b6ff4 100644
--- a/modules/system/system.test
+++ b/modules/system/system.test
@@ -517,7 +517,6 @@
     $edit['modules[Core][poll][enable]'] = 'poll';
     $edit['modules[Core][php][enable]'] = 'php';
     $this->drupalPost('admin/modules', $edit, t('Save configuration'));
-    $this->assertModules(array('forum', 'poll', 'php'), TRUE);
 
     // Check the actual order which is saved by module_test_modules_enabled().
     $this->assertIdentical(variable_get('test_module_enable_order', FALSE), $expected_order, t('Modules enabled in the correct order.'));
