• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Object Variable Not Set при выполнении агента

  • Автор темы dozer
  • Дата начала
D

dozer

Добрый день!

У нас на сервере Lotus Domino 6.5.4 работает документооборот. В одной из баз ежедневно выполняется агент - по определенному критерию делает выборку из всех документов и вносит в поля этих документов изменения. Однако недавно этот агент перестал отрабатывать. В дизайнере смотрю свойства агента - там написано, что он запустился во столько-то, закончился во столько-то. Захожу в log.nsf и смотрю там сообщения. Оказывается, через некоторое время после запуска агента выдается такое сообщение:
AMgr: Agent ('agent_name' in 'db_name') error message: Object variable not set
На этом все. И такая беда происходит каждый день, т.е. агент затыкается на одном и том же документе, как я понимаю. Но вопрос в том, как же найти, что это за документ, где именно он останавливается...

Есть ли какие-то варианты? Может нужно что-то дописать в сам агент, чтобы при некорректном завершении, он выдавал ID поврежденного документа?
 
A

allex

Пройтись дебагером в агенте не пробовали ?
Покажите код агента.
 

ToxaRat

Чёрный маг
Green Team
06.11.2007
3 332
42
BIT
0
это называется обработчик ошибок
вначале агента пишешь
on error goto err1
.....
.....
твой существуйщий код
....
....
exit sub

err1:
print "Err=" & err & ", Error=" & error & ", Line=" & erl
exit sub

получишь место в каком происходит ошибка при желании добавишь в принт и ИД проблемного дока
 
D

dozer

allex, я раньше с дизайнером дел не имел, поэтому пока ничего не пробовал. Сейчас сделал копию БД на локальный комп, буду на ней эксперементировать.
Как именно пройтись дебагером? Пока что-то не нашел...
Вот код агента:
Sub Initialize
Dim session As NotesSession
Dim db As NotesDatabase
Dim dc As NotesDocumentCollection
Dim doc As NotesDocument
Dim tempdoc As NotesDocument
Dim createDate As NotesDateTime
Dim nowDate As NotesDateTime

Dim item As NotesItem
Dim days As Integer
Dim profile As NotesDocument

Set session = New NotesSession
Set db = session.CurrentDatabase

Set profile = db.GetProfileDocument ("ArchTuning")
If profile Is Nothing Then
Exit Sub
Else
Sw = profile.GetItemValue("SettoArchiveSw")(0)
If Sw="1" Then
Set item = profile.GetFirstItem ("SettoArchiveDays")
If item Is Nothing Then
Exit Sub
Else
tempDays = profile.SettoArchiveDays (0)
If tempDays="" Then Exit Sub
days = Cint(tempDays)
End If
Else
Exit Sub
End If
End If

search$ = {Form = "Document" & Status = "X" & Archive != "1"}
Set db = session.CurrentDatabase
Set dc = db.Search(search$, Nothing, 0)
Set dc = db.UnprocessedDocuments

Set doc = dc.GetFirstDocument
Set nowDate = New NotesDateTime ("")
Call nowDate.SetNow

While Not doc Is Nothing
If doc.GetItemValue ("AuthorSite")(0) = session.UserName Then
Set arcDate = New NotesDateTime (doc.LastModified)

Call arcDate.AdjustDay (days)
ExpDays = arcDate.TimeDifference (nowDate) /60/60/24

If ExpDays > 0 Then
Call ArcResp (doc)
Print "Архивирование 1 "
doc.Archive = "1"
Forall itm In doc.Items
If itm.IsAuthors Then
itm.IsAuthors = False
itm.IsReaders = True
End If
End Forall
Call doc.Save (True, True)
End If
End If
Set tempdoc = dc.GetNextDocument (doc)
Delete doc
Set doc = tempdoc
Wend

End Sub

ToxaRat, я вставил эти строки после первой и перед последней в своем агенте (текст агента в предыдущем сообщении) и прогнал его еще раз. Вот что получил в ответ:
Compiling script...
1 error(s) found
Compiling script...
Err=0, Error=, Line=0
Что не так? И как именно добавить туда ID документа?
 
A

allex

А вот такая конструкция для чего ?
Код:
Set tempdoc = dc.GetNextDocument (doc)
Delete doc
Set doc = tempdoc

Сразу Set doc = dc.GetNextDocument (doc) нельзя ?

Вот тут я так понимаю ты архивируешь респонсы, а если их нет ?
Код:
If ExpDays > 0 Then 
Call ArcResp (doc)


Код:
print "Err=" & err & ", Error=" & error & ", Line=" & erl &" при обработке док. с UI" & doc.UniversalID
 
H

hosm

1. понимаю, что вопрос не к вам, но зачем сперва искать документы, а потом брать необработанные агентом?
Собственно, это о строчках:
Код:
Set dc = db.Search(search$, Nothing, 0)
Set dc = db.UnprocessedDocuments
Какой у агента Target установлен - все документы в БД?
2. добавить после получения перед обработкой документа проверку - никогда не помешает:
Код:
if doc.IsValid and not doc.isdeleted and not isEmpty(doc.Items) then
поможет, если агент сбивается на каком-то конкретном документе
3. убедиться, что в профайле есть данный итем, перед его получением:
Код:
if profile.hasItem("SettoArchiveSw") then 
Sw = profile.GetItemValue("SettoArchiveSw")(0) 
else 
Exit sub
end if


Err=0, Error=, Line=0 говорит, что отработал без ошибок.
В ArcResp тоже желательно написать обработчик ошибок, ошибка может быть и там. В зависимости от того, это sub или function перед меткой обработки ошибок "err1:" надо написать exit sub или exit function (не забыли это сделать в коде агента?)
 
D

dozer

allex, по поводу первого вопроса: данный агент написан не мной и вообще я только начинаю со всем этим разбираться, поэтому ответить с какой целью так сделано, к сожалению, не могу. Но исправлять пока не спешу, т.к. этот агент раньше точно работал корректно. Значит что-то не так с самими документами в базе.

А вот код для ArcResp:
Sub ArcResp (doc As NotesDocument)

Dim responses As NotesDocumentCollection
Dim response As NotesDocument
Dim tempdoc As NotesDocument

Set responses = doc.Responses
Set response = responses.GetFirstDocument
While Not response Is Nothing
Call ArcResp (response)
response.Archive = "1"
Forall itm In response.Items
If itm.IsAuthors Then
itm.IsAuthors = False
itm.IsReaders = True
End If
End Forall
Call response.Save (True,True)
Set tempdoc = responses.GetNextDocument (response)
Delete response
Set response = tempdoc
Wend

End Sub

OKEN, Target - All documents in database

Сегодня на работе жара, так что по остальным замечаниям посмотрю завтра и отпишусь.

Заранее спасибо за помощь!
 
H

hosm

Сразу Set doc = dc.GetNextDocument (doc) нельзя использовать, если документ doc как-то убивается из базы, в данном агенте этого не делается. Так что можно и сразу получать, и так, как написано в агенте - это не должно приводить к ошибке.

Уточню по п.1
Если Target - все документы и документы отбираются по db.UnprocessedDocuments, то условие, по которому документы отбирались изначально (Form = "Document" & Status = "X" & Archive != "1"), в общем-то, не проверяется и не нужно.
Почему изменено определение коллекции документов для обработки при архивировании - вопрос к разработчикам СЭД, наверно, в этом был глубокий смысл =)
В коллекцию попадают все документы в базе и поэтому никто не гарантирует наличие в них "AuthorSite" (тут может быть одна из причин ошибки).

По п.2 Иногда серверный агент получает в обработку "пустые" документы, стабы или невалидные документы (документы, к которым нет доступа). Тогда responses может быть и Nothing, так что можно добавить еще в ArcResp указание не обрабатывать подобные документы:
Код:
Set responses = doc.Responses
if responses is nothing then Exit sub ' на всякий случай
Set response = responses.GetFirstDocument
While Not response Is Nothing
if response.Isvalid and not response.isDeleted and not isEmpty(response.items) then ' отсекаем "битые"
Call ArcResp (response) 
... ' и т.д. код агента
Call response.Save (True,True)
end if
Set tempdoc = responses.GetNextDocument (response)
Delete response
Set response = tempdoc
Wend

P.S. И главное чуть не забыли...
Проверка doc.GetItemValue ("AuthorSite")(0) = s.username в серверном агенте предполагает, что в документе поле AuthorSite содержит имя сервера, поэтому на локальном компьютере агент может не выдавать ошибки, так как не сможет обработать ни одного документа!
Если у вас локальная копия БД, можно закомментировать эту проверку (или вместо s.username написать то, что в документах должно быть в этом поле). При достаточном доступе к документам в базе можно попробовать запустить локально агент (это совет только для тестирования, вкупе с обработчиком ошибок (или даже отладчиком) для определения "битого" документа, на сервере в итоговом варианте так делать не надо!!!)
 
D

dozer

Я снова тут ))
(из-за перебоев пропала одна моя тема, некоторые сообщения в этой теме и мой пароль! пришлось восстанавливать)
Ну а теперь к делу...

OKEN, большое спасибо! Советы помогли. На локальной базе все получилось отработать. Оказалось много битых доков, т.е. с потерянными связями. Но когда начал пробовать на живой, сразу пошли сюрпризы. Первый из них - обработчик ошибок не работает. Запускаю агент вручную, он думает-думает, потом просто выдает окошко Object variable not set, а в строке состояния пусто - ни ошибки, ни UI, ничего.
Сейчас разница между локальной базой и рабочей только в одной строчке агента:
Рабочая база: doc.GetItemValue ("AuthorSite")(0) = s.username
Локальная база: doc.GetItemValue ("AuthorSite")(0) = "реальное значение этого поля"
Как обойти Object variable not set, я теперь знаю. Но все-таки хотелось, чтобы сообщение об ошибке выходило, т.к. в других документах есть еще кое-какие косяки, которые нужно поправить. Без них агент до конца так и не отработает.
 
O

Omh

Ответ от госпожи OKEN (у неё, к сожалению, в данный проблемы со входом на форум):
"Агент должен быть подписан сервером (s.username).
Ну, код там так написан и поле так заполняется.
Надо переделывать на проверку сервера текущей бд, по-хорошему, но это не к тебе предложение.
В обработчике ошибок есть проверка на Nothing документа перед выводом унида?"
 
O

Omh

Не, ну госпожа OKEN просто чудо, нет?
Вот её ответ:

1. "Запускаю агент вручную, он думает-думает" - это наверно, поиск выполняет (db.Search), который потом не использует никак. Если закомментировать его - быстрее думать начал бы. ;)

Опять же эта дурацкая проверка на AuthorSite...
Подобный агент подписывается сервером и на сервере запускать его лучше консольной командой (если есть соответствующие права), подставив нужное имя БД и агента.
Выдержка из хелпа Domino Administrator) по Tell Amgr Run:
Runs the agents that you designate with these arguments:
"db name" 'agent name'
Example: Tell Amgr Run "DatabaseName.nsf" 'AgentName'
Смотреть принты тогда надо в логе сервера.
Если нет прав на использование консоли или лень разбираться с этим, ставить на тестовой БД расписание агента на 5-10-15 минут, подписывать сервером и ждать его запуска.

2. За окошко "Object variable not set". Обработчик ошибок не должен содержать ошибки =)
в исчезнувших сообщениях были примеры обработчика с проверкой документа на Nothing.
Думаю, вам не жалко описать лишнюю переменную для обработчика ошибок, чтоб не дублировать общий код обработчика в процедуре. Сейчас приведу код только для указанного выше обработчика:
Код:
Dim ErrText as String
On Error Goto err1
...
exitF:
Exit Sub
err1:
if not doc is Nothing then
ErrText = " при обработке документа с UI=" & doc.UniversalID
end if
Print "Err=" & Err & ", Error=" & Error & ", Line=" & Erl & ErrText & ", " & getthreadinfo(1)
resume exitF
End Sub
Надеюсь, вы успели какую-то обработку ошибок вписать в ArcResp, проверив там свою переменную для Notesdocument на Nothing. Если нет, покатит такой вариант - меняйте doc на response и действуйте аналогично приведенному коду.
 
D

dozer

Не, ну госпожа OKEN просто чудо, нет?
Да уж, такой подробной помощи я точно не ожидал! ))
Большое спасибо...



1. "Запускаю агент вручную, он думает-думает" - это наверно, поиск выполняет (db.Search), который потом не использует никак. Если закомментировать его - быстрее думать начал бы.

Я уже закомментировал строчку
Код:
Set dc = db.UnprocessedDocuments
а вот
Код:
search$ = {Form = "Document" & Status = "X" & Archive != "1"}
Set db = session.CurrentDatabase
Set dc = db.Search(search$, Nothing, 0)
оставил, т.к. там идет выборка закрытых, но еще не заархивированных документов и она работает - теперь архивируются только закрытые документы, а не просто все старые.
Тут поясню - это все происходит в базе согласования договоров, так что в архив идут только завершенные согласования, еще действующие не должны туда уходить, хоть они и подходят по срокам.

Опять же эта дурацкая проверка на AuthorSite...
Подобный агент подписывается сервером и на сервере запускать его лучше консольной командой.


Здесь мне еще нужно повнимательней поковыряться...

2. За окошко "Object variable not set". Обработчик ошибок не должен содержать ошибки =)
в исчезнувших сообщениях были примеры обработчика с проверкой документа на Nothing.


Вот с этим тоже надо еще поработать.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!