Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Windows > Проблема с 7zip


Автор: teem0n 20.08.11, 18:51
Здравствуйте!

Нашел скрипт для автоархивации, при простом запуске все отлично работает.
Прописал его для запуска при "завершении работы" - в лог пишется, что процесс завершился с ошибкой 2.

Не подскажете, в чем проблема?

Код:

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Const SRC = """C:\Users\Alex\Dropbox\Мосты\*"""  'каталог и маска для резервирования
    'Const SRC = """%AppData%\Opera\Opera\*"""  'здесь допускаются переменные окружения
    'Const SRC = "@files.txt"  'можно взять список каталогов из текстового файла
     
    'куда копировать?
    Const PREFIX = "DropboxFullBackup"  'префикс имени архива, условное название архивируемого ресурса
    Const BackupFolder = "C:\backup\"
    Const EXT = ".7z"  'расширение архивного файла
    Const HISTORY = 3  'количество полных архивов в истории
     
    'чем упаковывать?
    Const PROGRAM = """C:\Program Files (x86)\7-Zip\7z.exe"""  'если 7-Zip установлен
    'Const PROGRAM = "7z.exe"  'если архиватор лежит рядом со скриптом
    Const OPTIONS = "-r -mx5 -x@exclude.txt"  'опции архиватора
     
    'где отмечать?
    Const REPORT = "report.txt"  'файл журнала
     
    'не завершать скрипт аварийно
    On Error Resume Next
     
    '== ОБЩИЕ ОПРЕДЕЛЕНИЯ
     
    'записать сообщение в журнал
    Sub Log(msg)
       Const APPEND = 8 'добавить в конец файла
       Dim fso, f
       Set fso = CreateObject("Scripting.FileSystemObject")
       Set f = fso.OpenTextFile(REPORT, APPEND, True)
       f.WriteLine Now & " " & msg
       f.Close
    End Sub
     
    'объект для работы с файлами
    Dim fso
    Set fso = WScript.CreateObject("Scripting.FileSystemObject")
     
    Dim full 'имя последнего полного архива
     
    '== СОЗДАНИЕ АРХИВА
     
    'выбрать способ архивации
    Dim arg, cmd
    cmd = "" 'команда архиватора
    Set arg = WScript.Arguments
    If arg.Count > 0 Then
       If arg.Item(0) = "diff" Then
          cmd = "u"
       ElseIf arg.Item(0) = "full" Then
          cmd = "a"
       Else
          cmd = ""
       End If
    End If
     
    'полный архив
    If cmd = "a" Then
       'имя нового архива
       full = BackupFolder & PREFIX & "-" & FormatDateTime(Date, vbShortDate) & "-full" & EXT
       Log full & ": Start!"
       'если сегодня архив уже делали - не продолжать
       If (fso.FileExists(full)) Then
          Log full & ": создан РАНЕЕ и не будет перезаписан"
          WScript.Quit
       End If
       'опции командной строки
       opt = OPTIONS
     
    'разностный архив
    ElseIf cmd = "u" Then
       'найти полный архив
       Dim dir, fc, f, last
       Set dir = fso.GetFolder(BackupFolder) 'рабочий каталог
       Set fc = dir.Files 'коллекция файлов
       full = ""
       last = 0 'дата последнего полного архива
       For Each f In fc
          If Left(f.name, Len(PREFIX & "-")) = PREFIX & "-" _
          And Right(f.name, Len("-full" & EXT)) = "-full" & EXT _
          And f.DateLastModified > last Then
             full = f.name
             last = f.DateLastModified
          End If
       Next
       'без полного архива не продолжать
       If Len(full) = 0 Then
          Log "ОШИБКА! Полный архив НЕ НАЙДЕН, разностный архив не может быть создан"
          WScript.Quit
       End If
       'имя нового архива
       diff = BackupFolder & Left(full, Len(full) - Len("full" & EXT)) & FormatDateTime(Date, vbShortDate) & EXT
       Log diff & ": Start!"
       'если сегодня архив уже делали - не продолжать
       If (fso.FileExists(diff)) Then
          Log diff & ": создан РАНЕЕ и не будет перезаписан"
          WScript.Quit
       End If
       'опции командной строки
       opt = OPTIONS & " -u- -up0q3x2z0!" & diff
     
    'справка
    Else
       WScript.Echo "Ежедневное разностное резервное копирование:" & vbCrLf _
       & SRC & vbCrLf _
       & vbCrLf _
       & "Отчет в файле:" & vbCrLf _
       & REPORT & vbCrLf _
       & vbCrLf _
       & "Опции командной строки:" & vbCrLf _
       & "full  - создание полного архива" & vbCrLf _
       & "diff  - создание разностного архива"
       WScript.Quit
    End If
     
    'если нет файла со списком исключений exclude.txt - создать
    'файл указан в опциях архиватора и поэтому должен существовать, хотя бы пустой
    If Not fso.FileExists("exclude.txt") Then
       Dim tf
       Set tf = fso.CreateTextFile("exclude.txt")
       tf.Close
    End If
     
    'создать архив
    MsgBox(PROGRAM & " " & cmd & " " & full & " " & opt & " " & SRC)
    Dim sho, ret
    Set sho = WScript.CreateObject("WSCript.Shell")
    ret = sho.Run(PROGRAM & " " & cmd & " " & full & " " & opt & " " & SRC, 1, true) '7 = в свернутом виде
     
    'результат
    Dim msg
    Select Case ret
    Case 0
       msg = "Ok"
    Case 1
       msg = "Некоторые файлы были ЗАНЯТЫ и поэтому не добавлены в архив"
    Case 2
       msg = "ОШИБКА при создании архива"
    Case 7
       msg = "ОШИБКА в командной строке"
    Case 8
       msg = "ОШИБКА - недостаточно памяти"
    Case 255
       msg = "ОШИБКА - создание архива было ПРЕРВАНО пользователем"
    Case Else
       msg = "ОШИБКА при создании архива, код " & ret
    End Select
    If cmd = "a" Then
       Log full & ": " & msg
    Else
       Log diff & ": " & msg
    End If

Автор: Akina 20.08.11, 20:22
Хотя бы на секунду задумайся - от имени какой учётной записи он запускается при завершении...

Автор: teem0n 20.08.11, 20:26
А разве он запускается не непосредственно перед завершением работы? :blink: Тогда, видимо, от имени текущей. :(

Если не так и проблема в этом - как можно реализовать данную задачу?

Автор: teem0n 21.08.11, 10:52
Также вопрос: как с помощью батника/vbs запустить программу от администратора? :oops:

Автор: --= Eagle =-- 21.08.11, 16:21
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    runas

Автор: teem0n 21.08.11, 20:31
Цитата --= Eagle =-- @
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    runas

Спасибо!

Я вот подумал: у меня же учетка обладает правами админа... Что не так тогда?

Автор: nash 21.08.11, 20:39
В том, что ты пытаешься стартовать процесс, в то время когда ОС все процессы финиширует.

Автор: ValterG 22.08.11, 05:24
teem0n
Событие "завершение работы" придумано для того, чтобы корректно ЗАКРЫТЬ задачу, а не плодить новые :-)
Максимум что можно сделать - сказать, что НИЗЗЯ завершать. Юзер либо снимет такую задачу, либо отменит завершение.
+++++++++++++++++++++++++++++++
Кстати есть честное решение. Заранее в отдельном потоке запустить 7zip с нужными параметрами и засуспедить (suspend) поток. Когда будет "завершение" - отпустить поток. Но если там длительная операция - опять поимеем сообщение для юзера.
И возможен геморой - система может поток закрыть.

Автор: teem0n 22.08.11, 06:35
Цитата ValterG @
teem0n
Событие "завершение работы" придумано для того, чтобы корректно ЗАКРЫТЬ задачу, а не плодить новые :-)
Максимум что можно сделать - сказать, что НИЗЗЯ завершать. Юзер либо снимет такую задачу, либо отменит завершение.
+++++++++++++++++++++++++++++++
Кстати есть честное решение. Заранее в отдельном потоке запустить 7zip с нужными параметрами и засуспедить (suspend) поток. Когда будет "завершение" - отпустить поток. Но если там длительная операция - опять поимеем сообщение для юзера.
И возможен геморой - система может поток закрыть.

Получается, то, что я задумал, вообще невозможно сделать?

Такая мысль возникла: может можно средствами скрипта (например, "Отправить в...->сжатая zip-папка"), не запуская .ехе, сделать это?

Ведь в таком варианте должно сработать!

Автор: Akina 22.08.11, 07:30
Цитата teem0n @
Получается, то, что я задумал, вообще невозможно сделать?

А, по-моему, тебе как раз дали всё необходимое для эксперимента...
Цитата ValterG @
Максимум что можно сделать - сказать, что НИЗЗЯ завершать.

То есть в твоём скрипте можно отменить выключение, выполнить необходимую операцию, а после её завершения снова инициировать выключение. И остаётся предусмотреть такую мелочь, что это повторное завершение снова запустит скрипт, т.е. надо где-то сделать статическую пометку, что скрипт уже отработал.
Попробуй...

Автор: Qraizer 22.08.11, 07:43
Вроде бы, в процессе завершения нельзя создавать новые процессы, иначе хотя бы как они получат уже посланные ранее нотифи о завершении работы системы и поймут, что надо выгружаться, зато можно создавать новые нитки, иначе было бы невозможно отлаживать эти самые процедуры завершения, ибо отладчику требуется создавать новые нити при аттаче.

Автор: teem0n 22.08.11, 08:31
Цитата Akina @
Цитата teem0n @
Получается, то, что я задумал, вообще невозможно сделать?

А, по-моему, тебе как раз дали всё необходимое для эксперимента...
Цитата ValterG @
Максимум что можно сделать - сказать, что НИЗЗЯ завершать.

То есть в твоём скрипте можно отменить выключение, выполнить необходимую операцию, а после её завершения снова инициировать выключение. И остаётся предусмотреть такую мелочь, что это повторное завершение снова запустит скрипт, т.е. надо где-то сделать статическую пометку, что скрипт уже отработал.
Попробуй...

Классный вариант, вполне устраивает!

Попробовал так:

WScript.Shell.Run("shutdown /a")

Не работает :( Как правильно остановить выключение?

Автор: Akina 22.08.11, 09:03
Цитата teem0n @
А разве он запускается не непосредственно перед завершением работы? Тогда, видимо, от имени текущей.

Всё-таки собрался и нашёл.
Цитата http://support.microsoft.com/kb/311787/en-us
Shutdown scripts run after the user logs off

Цитата http://technet.microsoft.com/ru-ru/library/cc771106(v=WS.10).aspx
Сценарии завершения работы выполняются с правами локальной системы и имеют полные права, связанные с запуском в качестве локальной системы.

Автор: teem0n 22.08.11, 09:25
Ок. А как запускать с указанием учетки?

Попробовал так: runas /noprofile /user:mymachine\alex shutdown -a > ""C:\1.txt""

Валится с ошибкой.

Автор: teem0n 23.08.11, 06:01
Сделал через скрипт cmd в итоге!

Автор: teem0n 24.08.11, 09:36
Всем спасибо!

Автор: Vkrem 21.12.18, 21:41
Апнем тему! Прошу подсказать, КАК в этом прекрасном скрипте использовать опцию ""Const SRC = "@files.txt" 'взять список каталогов из текстового файла"?? Что-то никак не разберусь, прошу подсказать.
пс: пробовал разное заполнение, кодировки и тд, все время получаю ошибку "ОШИБКА в командной строке"

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)