int __fastcall TConsoleRunner::Run(const UnicodeString Session, TOptions * Options,
  TStrings * ScriptCommands, TStrings * ScriptParameters)
{
  int ExitCode;
  try
  {
    bool AnyError = false;

    try
    {
      FScript = new TManagementScript(StoredSessions, FConsole->LimitedOutput());

      FScript->CopyParam = GUIConfiguration->DefaultCopyParam;
      FScript->SynchronizeParams = GUIConfiguration->SynchronizeParams;
      FScript->WantsProgress = FConsole->WantsProgress();
      FScript->OnPrint = ScriptPrint;
      FScript->OnPrintProgress = ScriptPrintProgress;
      FScript->OnInput = ScriptInput;
      FScript->OnTerminalPromptUser = ScriptTerminalPromptUser;
      FScript->OnShowExtendedException = ScriptShowExtendedException;
      FScript->OnTerminalQueryUser = ScriptTerminalQueryUser;
      FScript->OnQueryCancel = ScriptQueryCancel;
      FScript->OnSynchronizeStartStop = ScriptSynchronizeStartStop;
      FScript->OnProgress = ScriptProgress;
      FScript->Interactive = (ScriptCommands == NULL) && FConsole->Interactive();

      UpdateTitle();

      // everything until the first manually entered command is "batch"
      // (including opening session from command line and script file)
      FBatchScript = true;

      if (!Session.IsEmpty())
      {
        if (!FScript->Interactive)
        {
          PrintMessage(LoadStr(SCRIPT_CMDLINE_SESSION));
        }
        FCommandError = false;
        FScript->Connect(Session, Options, false);
        if (FCommandError)
        {
          Failed(AnyError);
        }
      }

      FScript->Groups = Options->SwitchValue(L"xmlgroups", true, false);

      int ScriptPos = 0;
      bool Result;
      do
      {
        UpdateTitle();

        UnicodeString Command;
        if ((ScriptCommands != NULL) && (ScriptPos < ScriptCommands->Count))
        {
          Result = true;
          Command = ScriptCommands->Strings[ScriptPos];
          ScriptPos++;
        }
        else
        {
          if (FBatchScript)
          {
            // no longer batch
            FBatchScript = false;
            FScript->StartInteractive();
          }
          Print(L"winscp> ");
          Result = DoInput(Command, true, 0, false);
        }

        if (Result)
        {
          FCommandError = false;
          FScript->Command(ExpandCommand(Command, ScriptParameters));

          if (FCommandError)
          {
            Failed(AnyError);
            if (FScript->Batch == TScript::BatchAbort)
            {
              Result = false;
            }
          }

          if (FScript->Terminal != NULL)
          {
            FScript->Terminal->Idle();
          }
        }
      }
      while (Result && FScript->Continue && !Aborted());
    }
    catch(Exception & E)
    {
      Failed(AnyError);
      ShowException(&E);
    }

    if (FLastProgressLen > 0)
    {
      FConsole->Print(L"\n");
      FLastProgressLen = 0;
    }

    ExitCode = (AnyError || FAborted) ? RESULT_ANY_ERROR : RESULT_SUCCESS;

    if (FScript != NULL)
    {
      UnicodeString ExitCodeMessage = FORMAT(L"Exit code: %d", (ExitCode));
      FScript->Log(llMessage, ExitCodeMessage);
      if (Configuration->LogProtocol >= 1)
      {
        FConsole->Print(ExitCodeMessage + L"\n");
        UnicodeString LogMessage = FConsole->FinalLogMessage();
        if (!LogMessage.IsEmpty())
        {
          FScript->Log(llMessage, LogMessage);
          FConsole->Print(LogMessage + L"\n");
        }
      }
    }
  }
  __finally
  {
    delete FScript;
    FScript = NULL;
  }

  return ExitCode;
}