/**
  * Starts script execution.
  *
  * @return void
  *
  * @throws \Exception   On errors
  */
 public function run()
 {
     $this->setAsTerminator();
     $eventHandlerRegistry = Application::getInstance()->getDiContainer()->getEventHandlerRegistry();
     $eventHandlerRegistry->raise(new Event(Event::TYPE_APPLICATION_BEFORE_RUN));
     $this->prepareSwitches();
     try {
         $this->parseSwitches($this->cliHelper->getParsedArgs());
     } catch (\Exception $exception) {
         $this->cliHelper->setErrorMessage($exception->getMessage());
         // Set the exit code to invocation error if it's currently set to success.
         if ($this->getExitCode() == self::EXIT_CODE_SUCCESS) {
             $this->setExitCode(self::EXIT_CODE_INVOCATION_ERROR);
         }
         echo $this->cliHelper->getUsageOutput(false);
         // Re-throw the exception
         throw $exception;
     }
     $this->runBefore();
     try {
         if ($this->currentUsage == self::HELP_USAGE) {
             echo $this->cliHelper->getUsageOutput(true);
         } else {
             $eventHandlerRegistry->raise(new Event(Event::TYPE_CONTROLLER_BEFORE_ACTION));
             $this->execute();
             $eventHandlerRegistry->raise(new Event(Event::TYPE_CONTROLLER_AFTER_ACTION));
         }
     } catch (\Exception $exception) {
         $this->removeSignalHandler();
         if (self::EXIT_CODE_SUCCESS == $this->getExitCode()) {
             $this->setExitCode(self::EXIT_CODE_UNHANDLED_EXCEPTION);
         }
         Application::getInstance()->getDiContainer()->getErrorHandlerRegistry()->handleException($exception);
     }
     $this->removeSignalHandler();
     $this->runAfter();
     $eventHandlerRegistry->raise(new Event(Event::TYPE_APPLICATION_AFTER_RUN));
 }