Показать полную графическую версию : Считать переменную из файла
Udar_Nick
24-06-2016, 15:34
Приветствую уважаемый форум и прошу помощи!
Есть скрипт на VBS, делающий архив баз 1С
В скрипте как переменная указывается название базы, которую надо заархивировать. Баз стало много и хотелось бы бэкапить их одним скриптом и одним заданием.
Видится, что существующий скрипт надо обернуть в цикл, который будет считывать из текстового файла название базы (одна строка - одно название базы), записывать его в некую переменную, которая будет подставляться в нужное место строки архивации и так для всех указанных баз.
Поскольку я абсолютный чайник в VBS, очень прошу дать наводку, примеры...
Заранее СПАСИБО :-)
megaloman
24-06-2016, 16:51
Вариант 1.' Cписок баз
MasNames = Array("Base1", _
"Base2", _
"Base3")
Mas_1 = LBound(MasNames)
Mas_N = UBound(MasNames)
For Mas_i = Mas_1 To Mas_N
Call ArcBackups(MasNames(Mas_i))
Next
Sub ArcBackups(BaseName)
MsgBox BaseName
End Sub
Существующий скрипт надо оформить в виде подпрограммы (у меня условно ArcBackups), и дописать вызывающую её часть, которая будет передавать в эту подпрограмму в виде аргумента имя базы. Как вариант, список имён можно определить в массиве в этой вызывающей процедуре. Достоинство варианта - не надо держать еще какой-то текстовый файл.
Вариант 2. Идеология та же, но, по Вашей идее, список баз храним в текстовом файлеSpisNames = "Z:\я16062417.txt" 'Cписок баз
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FileExists(SpisNames) Then
Set FSpis = FSO.OpenTextFile(SpisNames, 1)
Do
iString = FSpis.ReadLine
If Len(Trim(iString)) <> 0 Then Call ArcBackups(iString)
Loop While Not FSpis.AtEndOfStream
FSpis.Close
End If
Sub ArcBackups(BaseName)
MsgBox BaseName
End Sub
Base1
Base2
Base3
Base4
Base5
Base6
Base7
Base222
Вариант 3. И всё-таки я бы предпочел сделать эту работу в cmd - скрипте, ИМХО, надёжнее получится. Но, не зная подробностей Вашего задания, его не привожу.
Udar_Nick
24-06-2016, 18:22
Вариант 3. И всё-таки я бы предпочел сделать эту работу в cmd - скрипте, ИМХО, надёжнее получится. Но, не зная подробностей Вашего задания, его не привожу. »
Большое спасибо, буду разбираться с предложенным Вами.
Третий вариант не получится - там задача сначала пройтись по всем существующим в кластере 1С соединеным клиентам и выкинуть их из базы В cmd (насколько мне известно) такое не получится
А подскажите как ?
Существующий скрипт надо оформить в виде подпрограммы
Положу сюда тело скрипта (если это не оффтоп)
'имя пользователя базы 1С:Предприятия
UserName = "user"
'пароль пользователя базы 1С:Предприятия
UserPass = "pass"
'имя сервера 1С:Предприятия
ServerName = "server"
'имя базы 1С:Предприятия к которой подключаемся
BaseName = "test_baza"
LockPermissionCode = "123456"
LockMessageText = "БАЗА ЗАКРЫТА НА СОЗДАНИЕ РЕЗЕРВНОЙ КОПИИ И ОБНОВЛЕНИЕ."
Dim Connector
Dim AgentConnection
Dim Cluster
Dim WorkingProcess
Dim WorkingProcessConnection
Dim ibDesc
Dim connections
Dim ConnectString
Set connector = CreateObject("v83.COMConnector.1")
Set AgentConnection = Connector.ConnectAgent(ServerName)
Set Cluster = AgentConnection.GetClusters()(0)
'Указываем доступ к консоли 1С:Предприятия (только в том случае если определён администратор кластера, иначе прописать просто " " (пробелЫ))
AgentConnection.Authenticate Cluster, " ", " "
'Список процессов кластера
Processes = AgentConnection.GetWorkingProcesses(Cluster)
Dim j
'Перебираем все процессы в кластере
For j = LBound(Processes) To UBound(Processes)
Set WorkingProcess = AgentConnection.GetWorkingProcesses(Cluster)(j)
'Проверяем на наличие остановленых процессов
If (WorkingProcess.MainPort <> "0") Then
ConnectString = WorkingProcess.HostName & ":" & WorkingProcess.MainPort
Set WorkingProcessConnection = Connector.ConnectWorkingProcess(ConnectString)
WorkingProcessConnection.AddAuthentication UserName, UserPass
InfoBases = WorkingProcessConnection.GetInfoBases()
For Each InfoBase In InfoBases
' Ищем нужную базу
If UCase(InfoBase.Name) = UCase(BaseName) Then
' Устанавливаем запрет на подключение новых соединений
InfoBase.ConnectDenied = True
InfoBase.DeniedFrom = CStr(Now())
' Запрет действует 15 минут, если скрипт не отработает нормально
InfoBase.DeniedTo = CStr(Now() + 1 / 96 * 1)
InfoBase.DeniedMessage = LockMessageText
InfoBase.PermissionCode = LockPermissionCode
WorkingProcessConnection.UpdateInfoBase (InfoBase)
End If
Next
Set ibDesc = WorkingProcessConnection.CreateInfoBaseInfo()
ibDesc.Name = BaseName
Connections = WorkingProcessConnection.GetInfoBaseConnections(ibDesc)
'Удаление всех соединений заданной ИБ сервера 1С
Dim i
Dim Connection
For i = LBound(Connections) To UBound(Connections)
Set Connection = connections(i)
If (Connection.AppID <> "COMConsole") Then
WorkingProcessConnection.Disconnect Connection
End If
Next
End If
Next
'''''''''''''''''''''''''''''
strComm = """C:\Program Files (x86)\1cv8\8.3.4.437\bin\1cv8.exe"" CONFIG /S"& ServerName &"\"& BaseName &" /Nuser /Ppass /UC"& LockPermissionCode &" /DumpIB ""\\SERVER\BACKUP\1C\"& Dat & BaseName &".dt"" /Out ""\\SERVER\BACKUP\1C\log\"& Dat & BaseName &"_dump.log"""
strComm2 = """C:\Program Files (x86)\1cv8\8.3.4.437\bin\1cv8.exe"" CONFIG /S"& ServerName &"\"& BaseName &" /Nuser /Ppass /UC"& LockPermissionCode &" /UpdateDBCfg /Out ""\\SERVER\BACKUP\1C\log\"& Dat & BaseName &"_update.log"""
Set oWshShell = CreateObject("WScript.Shell")
oWshShell.Run strComm, 0, true
oWshShell.Run strComm2, 0, true
' Отключаем блокировку базы
InfoBases = WorkingProcessConnection.GetInfoBases()
For Each InfoBase In InfoBases
' Ищем нужную базу
If UCase(InfoBase.Name) = UCase(BaseName) Then
' Отключаем запрет на подключение новых соединений
InfoBase.ConnectDenied = False
'InfoBase.DeniedMessage = ""
'InfoBase.PermissionCode = ""
WorkingProcessConnection.UpdateInfoBase (InfoBase)
End If
Next
megaloman
24-06-2016, 19:27
Udar_Nick, Я не уверен, что получится с Вашим конкретным скриптом, но попробуйте вместо моего MsgBox BaseName (или ниже, для отладки) вставить полностью Ваш скрипт. В Вашем скрипте закомментируйте строку (в начале строки поставьте ' ). Случайно у нас имена Вашей переменной и параметра моей процедуры совпали :)
' BaseName = "test_baza"
Естественно, в вызывающем модуле пропишите Ваши имена баз, пару штук для начала.
megaloman
24-06-2016, 22:27
Udar_Nick, Вот и Вариант 3.
Пишем bat-файл, где вызываем Ваш vbs-скрипт (я обозвал файл с ним ArcBackups.vbs) и в параметре передаём в него имя базы @Echo On
wscript ArcBackups.vbs "Base1"
wscript ArcBackups.vbs "Base2"
wscript ArcBackups.vbs "Base3"
Ваш скрипт слегка дорабатываем: Set WS_arg=WScript.Arguments
If WS_arg.Count <> 0 Then
BaseName=WS_arg(0)
MsgBox BaseName
End If
Опять же, в батнике пропишите свои имена баз, вместо моего MsgBox BaseName (или ниже, для отладки) вставить полностью Ваш скрипт, лишь в Вашем скрипте закомментируйте строку (в начале строки поставьте ' ) где Вы указываете имя базы.
' BaseName = "test_baza"
ИМХО, этот вариант должен работать.
Если будете настаивать, можно написать в батнике и чтение имён из текстового файла, имхо, это не имеет смысла.
Mas_1 = LBound(MasNames)
Mas_N = UBound(MasNames)
For Mas_i = Mas_1 To Mas_N »
Тут можно просто «For Each MasName In MasNames» применить.
Udar_Nick
28-06-2016, 14:46
а научите пожалуйста как сделать так, чтобы в случае ошибки в выполнении строки:
oWshShell.Run strComm, 0, true
создавался файл Error.pid в определенной папке
Udar_Nick, «в случае ошибки» — что именно Вы под этим подразумеваете?
Udar_Nick
28-06-2016, 15:50
Udar_Nick, «в случае ошибки» — что именно Вы под этим подразумеваете? »
в моем скрипте эта строчка вызывает 1С:
C:\Program Files (x86)\1cv8\8.3.4.437\bin\1cv8.exe с некими параметрами. Делается дамп базы данных.
Хотелось бы, если errorlevel выполнения этой строки не 0 (т.е произошла какая-то ошибка), то сделать файлик error.pid (и записать в него errorlevel например). Нужно для мониторинга Нагиосом
в cmd это вот так выглядит:
set RunProgramm = "c:\program.exe param1"
%RunProgramm%
if %ERRORLEVEL% GTR 0 goto err
:err
echo %ERRORLEVEL% >> c:\error.pid
Dim lngErrLevel
lngErrLevel = oWshShell.Run(strComm, 0, True)
If lngErrLevel Then
With WScript.CreateObject("Scripting.FileSystemObject").CreateTextFile("c:\error.pid")
.Write CStr(lngErrLevel)
.Close
End With
End If
Нужно для мониторинга Нагиосом »
Надеюсь, «Нагиос» удаляет этот файл после обработки?
Далее, в одном случае Вы пишете, чтобы файл «создавался», а ниже приводите пример дополнения файла данными (а не создания).
Udar_Nick
28-06-2016, 16:59
а ниже приводите пример дополнения файла данными (а не создания). »
ошибся, писал "с руки", а не копипастил из рабочего скрипта
Большое спасибо за помощь
Udar_Nick
29-06-2016, 12:12
А помогите мне, пожалуйста, еще раз в продолжении этой задачи...
Необходимо из определенной сетевой шары \\server\share выбрать самый последний по дате\времени изменения файл с маской *.dt (не рекурсивно) и если его возраст не более N часов, то сделать echo (не MsgBox) "имя файла пробел размер файла пробел дата\время изменения" и выйти с кодом 0, иначе сделать такое же echo, но выйти с кодом 2. В случае если файлов *.dt в папке вообще нет, выйти с кодом 1
помучался денек и понял, что навыков в VBS для этого у меня пока маловато....
Большое спасибо всем откликнувшимся! :-)
Апдейт
Пока смог накидать как найти самый последний модифицированный файл в папке
Set odFSO = CreateObject("Scripting.FileSystemObject")
sDir = "V:\temp"
Set GetFiles = odFSO.GetFolder(sDir).Files
For Each File in GetFiles
FileDate = File.DateLastModified
If FileDate > MaxFileDate Then Lastfile = File : MaxFileDate = FileDate
Next
MsgBox LastFile
megaloman
29-06-2016, 22:24
А помогите мне, пожалуйста, еще раз в продолжении этой задачи... -ИМХО, это другая уже темаPapka = "\\server\share"
inMaska = "^.*\.dt$"
Nhour = 5
' Papka = "D:\CMD\JS_Host"
' inMaska = "^.*\.xls$"
Set FSO = CreateObject("Scripting.FileSystemObject")
OutCode = 1
Filedata = DateSerial(2000, 1, 1)
If FSO.FolderExists(Papka) Then
Set Fol = FSO.GetFolder(Papka)
Set Files = Fol.Files
Set Re = New RegExp
Re.Pattern = inMaska
Re.IgnoreCase = True
For Each File In Files
Filename = File.Name
If Re.Test(Filename) Then
OutCode = 2
If File.DateLastModified > Filedata Then
Filedata = File.DateLastModified
Filesize = File.Size
End If
End If
Next
End If
If OutCode = 2 Then
If DateDiff("h", Filedata, Now) <= Nhour Then OutCode = 0
WScript.Echo "+++ " + CStr(Now) + vbCrLf + _
Filename + " " + CStr(Filesize) + " " + CStr(Filedata) + " Код=" + CStr(OutCode)
End If
WScript.Quit (OutCode)Если интересует пакетный режим (раз Вы так настаиваете на Echo), то vbs-файл можно запускать ручками посредством cscript, либо батникомEcho Off
cls
cscript //NoLogo name-vbs-script.vbs
Echo %Errorlevel%
pause
Udar_Nick
30-06-2016, 09:39
Если интересует пакетный режим (раз Вы так настаиваете на Echo), то vbs-файл можно запускать ручками посредством cscript, либо батником »
Я правильно понимаю, что в случае запуска батником, на выходе получаем только Errorlevel и не получаем имя файла,размер и его дату?
Большое спасибо Вам за помощь!
megaloman
30-06-2016, 10:45
Udar_Nick, неправильно, если запускаете в графическом режиме, то на echo придётся нажать ОК для завершения скрипта, а в пакетном режиме после выдачи echo со всей инфой скрипт не потребует никаких дополнительных действий. Батник написан для иллюстрации того, что всё выдаётся и что errorlevel возвращается как задумано. В норме для работы надо только одна строка с запуском vbs скрипта. Единственное, что не предусмотрел, echo vbs-скрипта вовсе не выдаётся при отсутствии файлов и скрипт завершается без какой-либо выдачи с кодом 1, как Вы и требовали. Пририсовать в последнем if секцию else с echo об отсутствии файлов - нет проблемы.
а в пакетном режиме… »
Полагаю, имелся в виду консольный режим. А «пакетный» — это подавление вывода и ошибок по «//b», как в GUI, так и в CUI режимах.
megaloman
30-06-2016, 11:18
Iska, скорее всего Вы правы, в моём случае я имел ввиду, что скрипт зачем-то нужен как какая-то утилита для другого скрипта именно в консоли, чтобы не надо было ничего дополнительно нажимать. Иначе зачем настаивать на echo?
Udar_Nick
30-06-2016, 12:14
Иначе зачем настаивать на echo? »
Если делать echo - Нагиос выводит это в дополнительные сведения. Очень удобно, что помимо самого alert сразу видно, чем он вызван. Не уверен, что это будет работать с MsgBox
Спасибо еще раз, с помощью Вас megaloman и Вас Iska мне таки удалось написать свой скриптик и оно даже уже работает :-)
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.