public static function UpdateStepModules($updatesDir, &$strError, $bSaveUpdaters = False)
 {
     global $DB;
     $strError_tmp = "";
     if (!defined("US_SAVE_UPDATERS_DIR") || StrLen(US_SAVE_UPDATERS_DIR) <= 0) {
         $bSaveUpdaters = False;
     }
     $stime = CUpdateClientPartner::__GetMicroTime();
     $updatesDirFull = $_SERVER["DOCUMENT_ROOT"] . "/bitrix/updates/" . $updatesDir;
     if (!file_exists($updatesDirFull) || !is_dir($updatesDirFull)) {
         $strError_tmp .= "[UUK01] " . str_replace("#FILE#", $updatesDirFull, GetMessage("SUPP_CU_NO_TMP_CAT")) . ". ";
     }
     if (strlen($strError_tmp) <= 0) {
         if (!is_readable($updatesDirFull)) {
             $strError_tmp .= "[UUK03] " . str_replace("#FILE#", $updatesDirFull, GetMessage("SUPP_CU_RD_TMP_CAT")) . ". ";
         }
     }
     $arModules = array();
     if (StrLen($strError_tmp) <= 0) {
         $handle = @opendir($updatesDirFull);
         if ($handle) {
             while (false !== ($dir = readdir($handle))) {
                 if ($dir == "." || $dir == "..") {
                     continue;
                 }
                 if (is_dir($updatesDirFull . "/" . $dir)) {
                     $arModules[] = $dir;
                 }
             }
             closedir($handle);
         }
     }
     if (!is_array($arModules) || count($arModules) <= 0) {
         $strError_tmp .= "[UUK02] " . GetMessage("SUPP_UK_NO_MODS") . ". ";
     }
     if (strlen($strError_tmp) <= 0) {
         for ($i = 0, $cnt = count($arModules); $i < $cnt; $i++) {
             $strError_tmp1 = "";
             $updateDirFrom = $updatesDirFull . "/" . $arModules[$i];
             $updateDirTo = $_SERVER["DOCUMENT_ROOT"] . US_SHARED_KERNEL_PATH . "/modules/" . $arModules[$i];
             CUpdateClientPartner::__CheckDirPath($updateDirTo . "/", true);
             if (!file_exists($updateDirTo) || !is_dir($updateDirTo)) {
                 $strError_tmp1 .= "[UUK04] " . str_replace("#MODULE_DIR#", $updateDirTo, GetMessage("SUPP_UK_NO_MODIR")) . ". ";
             }
             if (strlen($strError_tmp1) <= 0) {
                 if (!is_writable($updateDirTo)) {
                     $strError_tmp1 .= "[UUK05] " . str_replace("#MODULE_DIR#", $updateDirTo, GetMessage("SUPP_UK_WR_MODIR")) . ". ";
                 }
             }
             if (strlen($strError_tmp1) <= 0) {
                 if (!file_exists($updateDirFrom) || !is_dir($updateDirFrom)) {
                     $strError_tmp1 .= "[UUK06] " . str_replace("#DIR#", $updateDirFrom, GetMessage("SUPP_UK_NO_FDIR")) . ". ";
                 }
             }
             if (strlen($strError_tmp1) <= 0) {
                 if (!is_readable($updateDirFrom)) {
                     $strError_tmp1 .= "[UUK07] " . str_replace("#DIR#", $updateDirFrom, GetMessage("SUPP_UK_READ_FDIR")) . ". ";
                 }
             }
             if (strlen($strError_tmp1) <= 0) {
                 $handle = @opendir($updateDirFrom);
                 $arUpdaters = array();
                 if ($handle) {
                     while (false !== ($dir = readdir($handle))) {
                         if (substr($dir, 0, 7) == "updater") {
                             $bPostUpdater = "N";
                             if (is_file($updateDirFrom . "/" . $dir)) {
                                 $num = substr($dir, 7, strlen($dir) - 11);
                                 if (substr($dir, strlen($dir) - 9) == "_post.php") {
                                     $bPostUpdater = "Y";
                                     $num = substr($dir, 7, strlen($dir) - 16);
                                 }
                                 $arUpdaters[] = array("/" . $dir, Trim($num), $bPostUpdater);
                             } elseif (file_exists($updateDirFrom . "/" . $dir . "/index.php")) {
                                 $num = substr($dir, 7);
                                 if (substr($dir, strlen($dir) - 5) == "_post") {
                                     $bPostUpdater = "Y";
                                     $num = substr($dir, 7, strlen($dir) - 12);
                                 }
                                 $arUpdaters[] = array("/" . $dir . "/index.php", Trim($num), $bPostUpdater);
                             }
                             if ($bSaveUpdaters) {
                                 CUpdateClientPartner::__CopyDirFiles($updateDirFrom . "/" . $dir, $_SERVER["DOCUMENT_ROOT"] . US_SAVE_UPDATERS_DIR . "/" . $arModules[$i] . "/" . $dir, $strError_tmp1, False);
                             }
                         }
                     }
                     closedir($handle);
                 }
                 $n = count($arUpdaters);
                 for ($i1 = 0; $i1 < $n - 1; $i1++) {
                     for ($j1 = $i1 + 1; $j1 < $n; $j1++) {
                         if (CUpdateClientPartner::__CompareVersions($arUpdaters[$i1][1], $arUpdaters[$j1][1]) > 0) {
                             $tmp1 = $arUpdaters[$i1];
                             $arUpdaters[$i1] = $arUpdaters[$j1];
                             $arUpdaters[$j1] = $tmp1;
                         }
                     }
                 }
             }
             if (strlen($strError_tmp1) <= 0) {
                 if (strtolower($DB->type) == "mysql" && defined("MYSQL_TABLE_TYPE") && strlen(MYSQL_TABLE_TYPE) > 0) {
                     $DB->Query("SET storage_engine = '" . MYSQL_TABLE_TYPE . "'", True);
                 }
             }
             if (strlen($strError_tmp1) <= 0) {
                 for ($i1 = 0, $n = count($arUpdaters); $i1 < $n; $i1++) {
                     if ($arUpdaters[$i1][2] == "N") {
                         $strError_tmp2 = "";
                         CUpdateClientPartner::__RunUpdaterScript($updateDirFrom . $arUpdaters[$i1][0], $strError_tmp2, "/bitrix/updates/" . $updatesDir . "/" . $arModules[$i], $arModules[$i]);
                         if (strlen($strError_tmp2) > 0) {
                             $strError_tmp1 .= str_replace("#MODULE#", $arModules[$i], str_replace("#VER#", $arUpdaters[$i1][1], GetMessage("SUPP_UK_UPDN_ERR"))) . ": " . $strError_tmp2 . ". ";
                             $strError_tmp1 .= str_replace("#MODULE#", $arModules[$i], GetMessage("SUPP_UK_UPDN_ERR_BREAK")) . " ";
                             break;
                         }
                     }
                 }
             }
             if (strlen($strError_tmp1) <= 0) {
                 CUpdateClientPartner::__CopyDirFiles($updateDirFrom, $updateDirTo, $strError_tmp1, True);
             }
             if (strlen($strError_tmp1) <= 0) {
                 for ($i1 = 0, $n = count($arUpdaters); $i1 < $n; $i1++) {
                     if ($arUpdaters[$i1][2] == "Y") {
                         $strError_tmp2 = "";
                         CUpdateClientPartner::__RunUpdaterScript($updateDirFrom . $arUpdaters[$i1][0], $strError_tmp2, "/bitrix/updates/" . $updatesDir . "/" . $arModules[$i], $arModules[$i]);
                         if (strlen($strError_tmp2) > 0) {
                             $strError_tmp1 .= str_replace("#MODULE#", $arModules[$i], str_replace("#VER#", $arUpdaters[$i1][1], GetMessage("SUPP_UK_UPDY_ERR"))) . ": " . $strError_tmp2 . ". ";
                             $strError_tmp1 .= str_replace("#MODULE#", $arModules[$i], GetMessage("SUPP_UK_UPDN_ERR_BREAK")) . " ";
                             break;
                         }
                     }
                 }
             }
             if (strlen($strError_tmp1) > 0) {
                 $strError_tmp .= $strError_tmp1;
             }
         }
         CUpdateClientPartner::ClearUpdateFolder($updatesDirFull);
     }
     CUpdateClientPartner::AddMessage2Log("TIME UpdateStepModules " . Round(CUpdateClientPartner::__GetMicroTime() - $stime, 3) . " sec");
     if (strlen($strError_tmp) > 0) {
         CUpdateClientPartner::AddMessage2Log($strError_tmp, "USM");
         $strError .= $strError_tmp;
         return False;
     } else {
         foreach (GetModuleEvents("main", "OnModuleUpdate", true) as $arEvent) {
             ExecuteModuleEventEx($arEvent, array($arModules));
         }
         return True;
     }
 }