Запустить от юзера агент-odbc должен быть на сервере

  • Автор темы Karlosss
  • Дата начала
K

Karlosss

Все привет!
Есть база на сервере, в базе есть форма документа с полями выбора условий для отчета. Юзер выбирает условия отбора, нажимает на кнопку для формирования отчета в excel.
По кнопке запускается агент. Агент обращается по odbc к БД Оракл. Вопросы:
1. Каким образом можно настроить агент или odbc, чтобы при работе он использовал odbc драйвер с сервера, а не локально?
2. При работе агент спрашивает пароль для доступа к БД Оракл, хотя в скрипте имя и пароль посылаются на сервер. Как запомнить пароль чтобы он не спрашивал его постоянно?
 
X

Xalet

А вы уверены, что агент на сервере запускается, потому как, судя по вопросам, такое ощущение, что с клиентской машины.
 
K

Karlosss

Да , именно с клиентской машины. Вопрос как раз в том чтобы с клиентской машины запускался агент таким образом чтобы использовал odbc драйвер сервера.
 
N

nvyush

Запускать агента методом Agent.RunOnServer
По условию задачи
Есть база на сервере, в базе есть форма документа с полями выбора условий для отчета. Юзер выбирает условия отбора, нажимает на кнопку для формирования отчета в excel.
пользователю нужно, чтобы агент исполнялся на клиенте. По крайней мере формировать отчёт в ёкселе на сервере проблематично, недавно обсуждалось.
 
T

TIA

пользователю нужно, чтобы агент исполнялся на клиенте.
Да пусть запускается на клиенте, только ещё пинает RunOnServer. Серверный агент пусть выскребает данные из Оракла и складывает в документ. Клиентский агент пусть читает такой документ и формирует отчёт в Excel.
Параметры для формирования условий отбора можно через тот же документ передавать.
 
K

Karlosss

Да пусть запускается на клиенте, только ещё пинает RunOnServer. Серверный агент пусть выскребает данные из Оракла и складывает в документ. Клиентский агент пусть читает такой документ и формирует отчёт в Excel.
Параметры для формирования условий отбора можно через тот же документ передавать.


Да , спасибо , идею я понял, буду пробовать.
 
K

Karlosss

Сделал следующую конструкцию:
1. Текущий документ , в котором пользователь определяет критерии для отчета.
2. Агент , который запускается на сервере , но толкается из текущего документа пользователем.

Пользователь выбирает критерии поиска и клик на кнопку для создания отчета. Текущий док сохраняется, в нужное поле вставляется его id. Запускается агент на сервере. Выполняется запрос к базе оракл. Создается текстовый файл, куда записывается результат запроса. Файл вкладывается в документ , который находится в базе по id. Далее снова переходим на локальное выполнение кода. Находим док поиска по id , достаем из него результаты запроса в виде текст. файла и строим отчет.
Это все вернее так должно было быть. Но не получается. Агента отдельно я дебажил и код на кнопке тоже . Может где то принципиально ошибся или просто описАлся. Проверьте плз.

На кнопке:
Код:
Sub Click(Source As Button)
Dim ws As New NotesUIWorkspace
Dim session As New NotesSession
Dim db As NotesDatabase
Dim agent As NotesAgent
Dim rtitem As NotesRichTextItem
Dim object As NotesEmbeddedObject
Dim EWindow As Variant
Dim WorkBooks As Variant
Dim WorkSheet As Variant

Set db = session.CurrentDatabase
Dim doc As NotesDocument
Dim doc_temp As NotesDocument
Dim uidoc As NotesUIDocument
Set uidoc=ws.CurrentDocument
Set doc= uidoc.Document
Set view=db.GetView("Отчеты")
myID=doc.NoteID
doc.myID = doc.NoteID
Call uidoc.save()
Call uidoc.close(True)

Call db.getAgent("odbc4").runOnServer(myID) ' Толкаем агента на сервере, передаем id документа для вставки вложения

Set doc_temp=view.GetDocumentByKey(myID)

Set rtitem = doc_temp.GetFirstItem( "Body" )
Set object=rtitem.GetEmbeddedObject("otchet_suvd.txt")
Call object.ExtractFile( "c:\Temp\otchet_suvd.txt" )' - достаем файл и строим по нему отчет

i=2 
Print "Запуск Excel ..."
Set EWindow = CreateObject("Excel.Application")' 

If EWindow Is Nothing Then 
Print "Excel не найден"
End If

Set WorkBooks=EWindow.Workbooks
WorkBooks.Add
EWindow.visible = True
Set WorkSheet=EWindow.ActiveWorkBook.ActiveSheet
WorkSheet.Cells(1,1).value = "ФИО"
.....	
Open "c:\Temp\otchet_suvd.txt" For Input As fileNum			 
Do While Not Eof(fileNum)
Line Input #fileNum, st
razbor=Split(st, ",")

WorkSheet.Cells(i,1).value = razbor(0)
WorkSheet.Cells(i,2).value = razbor(1)

Loop	
Close	#fileNum	
End Sub

Агент на сервере:
Код:
Sub Initialize
Dim ws As New NotesUIWorkspace
Dim db As NotesDatabase
Dim session As New NotesSession
Dim doc As NotesDocument
Dim doc_otch As NotesDocument
Dim view As NotesView
Dim uidoc As NotesUIDocument
Set db=session.CurrentDatabase
'===== stream==================
Dim stream As NotesStream
Dim rtitem As NotesRichTextItem
Dim object As NotesEmbeddedObject
Dim item As NotesItem
Dim pathname As String
Dim stttr As Variant
'=============================
Dim con As New ODBCConnection
Dim qry As New ODBCQuery
Dim result As New ODBCResultSet

'=========Подключение к ODBC================

Call con.ConnectTo("ORACLE","имя","пароль") 'подключение к ODBC
status = con.ConnectTo ("имя odbc")
If Status = False Then
Messagebox "Не могу подключиться к источнику данных ODBC: " + odb, 16, "Внимание !!!"
Exit Sub
End If

Set qry = New ODBCQuery
Set result = New ODBCResultSet
Set qry.Connection = con
Set result.Query = qry

qry.SQL={запрос} ...

If Not result.Execute Then
Messagebox result.GetExtendedErrorMessage,,result.GetErrorMessage
Call result.Close(DB_CLOSE)	
Call con.Disconnect
Exit Sub
End If

'============Создание текстового файла=================================
pathname="c:\Temp\otchet_suvd.txt" ' change location
Set stream = session.CreateStream

If Not stream.Open(pathname, "windows-1251") Then
Messagebox pathname+" не найден",, "Open failed"
Call stream.Close
Exit Sub
End If


'=====================================================================
result.cacheLimit =DB_ALL
result.CacheLimit=DB_NONE
'result.Execute
If Not result.IsResultSetAvailable Then Exit Sub 
If result.FirstRow Then		 
Do 
......................читаем результат запроса и складываем его в текст файл		

stttr =result.GetValue("CONTACTS")+","+temp_fil & Chr(10)
Call stream.WriteText(stttr)

If result.IsEndOfData Then If result.IsEndOfData Then Exit Do
result.NextRow
Loop

End If
Call stream.Close
Call result.Close(DB_CLOSE)	
Call con.Disconnect	
Set view = db.GetView("Отчеты")
Set doc_otch=view.GetDocumentByKey(myID)
Set rtitem = New NotesRichTextItem( doc_otch, "Body" )
Set object = rtitem.EmbedObject(EMBED_ATTACHMENT, "", "c:\Temp\otchet_suvd.txt") ' вкладываем текст файл в документ поиска
Call doc_otch.Save(True,True)
End Sub
 
T

TIA

0. Что конкретно не получается?
1. Вставь option declare.
2. Как в агенте получен myID
3. Что будет, если пользователь повторно, из того же документа запустит поиск
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
472
особливо мне нра пассаж с временным файлом ;), в общем темпе...
доступ у подписанта д.б. соответ, и у юзера от имени кот. запущают домину
а потом с доступностью ОДБЦ и ёваного юзер систем сорцов, из-под доминошного юзера, тоже вопросы...
а не прощели jdbc заюзать было (изначально)
и из потока генерить документ с вложением (это хоть и не проще, но зато секурней и файло не надо на диске держать)
 
K

Karlosss

0. Что конкретно не получается?
1. Вставь option declare.
2. Как в агенте получен myID
3. Что будет, если пользователь повторно, из того же документа запустит поиск

0:Насколько я понимаю, после операции Call db.getAgent("odbc4").runOnServer(myID) на сервере должен отработать агент и я должен получить object, при этом должна быть какая-то временная задержка пока агент отрабатывает , а на деле строка по быстрому пролетает и object пустой.
1: В option- Uselsx "*LSXODBC" , в declare ничего нет.
2. Вот как он получен хз, по идее строка Call db.getAgent("odbc4").runOnServer(myID) должна передать его агенту,но... дело для меня новое , есть подозрение , что делаю я что-то не так, вот и прошу совета , что я делаю не так?
3. В данном случае пользователь тут я, на сервер win2003 залогинен я с правами админа, сервер запущен от меня, база подписана сервером. Запускать можно много раз , но ничего не меняется.

Скорее всего я не правильно передаю myID агенту...


Добавлено:
А это правильно, кстати? Вьюха подходит, мб, надо указать 2й параметр True?

Не очень понял , что здесь имелось ввиду? В принципе я дебажил и кнопку и агент отдельно , все отрабатывало, надо вот теперь как это все соединить...



Добавлено:
особливо мне нра пассаж с временным файлом ;), в общем темпе...
доступ у подписанта д.б. соответ, и у юзера от имени кот. запущают домину
а потом с доступностью ОДБЦ и ёваного юзер систем сорцов, из-под доминошного юзера, тоже вопросы...
а не прощели jdbc заюзать было (изначально)
и из потока генерить документ с вложением (это хоть и не проще, но зато секурней и файло не надо на диске держать)

Делал как умел, можно так , можно по другому - не принципиально, цель пока заставить работать odbc сервера.
Как я и писал уже , сервер запущен от меня. На java писать не умею, ведь jdbc использует java так ведь?
Может быть я в общем не правильно собрал конструктор , подскажите как сделать лучше. Ведь то что я написал это не строго, предложения принимаются :O_0:
 
N

nvyush

1: В option- Uselsx "*LSXODBC" , в declare ничего нет.
Имелось ввиду добавить в раздел Options строку Option Declare. Это заставляет компилятор проверить явное объявление всех переменных. Бережёт от ошибок типа неициализированных переменных и вообще полезно.

Непонятно, а зачем собственно временный файл класть аттачем в рт-поле? Не проще в само рт-поле поместить нужную информацию?
 
H

hosm

п.2. В агенте должно быть получение документа, переданного ему, примерно так
Код:
Dim s as new Notessession
noteid = s.CurrentAgent.parameterdocid
if noteid <> "" then
Set doc = s.CurrentDatabase.GetDocumentByID(noteid) ' документ, переданный агенту
end if
 
H

hosm

проверь myID до этой команды:
Set doc_otch=view.GetDocumentByKey(myID)
"В принципе я дебажил и кнопку и агент отдельно" - не на сервере ведь агент отлаживался, локально?
А агент именно на сервере вообще запускается?
Проверь Return value status = notesAgent.RunOnServer(...). Status of the operation where 0 indicates success.
С ОДБС работает, результаты в файл записывает? Обрати внимание на сообщение lmike. Папка темповая там есть нужная?
+ при наличии прав можно пытаться почистить за собой файл с помощью команды kill имяфайла.
попробуй просто поменять в агенте одно поле в переданном документе - например, заменить на тек.время и сохранить документ. Если так работает, значит, нормально с получением-передачей документов и просто запуском агента на сервере.
Потом отладь работу с серверной БД, запись в файл. Возможно, надо повысить уровень безопасности агента - allow restricted operations.
А потом и в документ запиши...
result.cacheLimit =DB_ALL
result.CacheLimit=DB_NONE
зачем оба варианта сразу?
 
T

TIA

Karlosss
Смотри ещё лог сервера. Там наверняка есть сообщение об ошибке серверного агента, какой-нибудь Object variable not set.
Для уточнения ошибочной операции, добавь обработчик ошибок с выводом Error$, Erl, GetThreadInfo(10)

По поводу 2 го параметра GetDocumentByKey посмотри хелп.
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
472
Karlosss
java - это не страшно, достаточно нагуглить готовые пример и вставить его в агент (на форуме они есть) и в серверном файловом пути домины (jvm/lib/ext) прописать оракловый файл с библиотекой... (.jar)
нужен именно JDBC Thin, для оракла (чтобы не устанавливать полный клиент, а обойтись одним файлом)
для отладки на клиенте - в аналогичное место положить библу
общая инфа по ждбц
оракловый вариант

по файловому пути - домина юзает \"свой\" темп, и его надо получить (источника не помню, приведу код):<div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">код</div></div><div class="sp-body"><div class="sp-content">
Код:
\'Class_TempFolderManager:

Const ERR_UNSUPPORTED_PLATFORM = 20300 \' arbitrary value
Private agentLog As NotesLog
Class TempFolderManager
m_path As String
m_files List As Integer

Function Unique As String
Dim unik
unik = Evaluate(\"@Unique\")
Unique = Strtoken(unik(0), \"-\", -1)	\' drop the username part of the ID which is always the same for this user
End Function

Sub New
m_path = GetNotesTempDirectory & \"/\" & Unique
Mkdir m_path
End Sub

Public Property Get Path As String
Path = m_path
End Property

Function NewFilename(Byval strSuffix$, Byval bManage As Boolean) As String
Dim strFName$
strFName = Unique
If strSuffix <> \"\" Then strFName = strFName & \".\" & strSuffix
NewFilename = m_path & \"/\" & strFName
If bManage Then
m_files(NewFilename) = 0
End If
End Function

Sub Manage(Byval strPath$)
m_files(strPath) = 1
End Sub

Sub Unmanage(Byval strPath$)
On Error Resume Next
Erase m_files(strPath)
End Sub

Function ClearFiles( ) As Boolean
\' erase all files under management but leave the directory so that we can use it more.
\' return True if all files were successfully erased.
On Error Goto failed
ClearFiles = True
Forall ffileno In m_files
Kill Listtag(ffileno)
nextFile:
End Forall
Erase m_files
Exit Function
failed:
ClearFiles = False
Resume nextFile
End Function

Sub Delete
On Error Resume Next
If ClearFiles Then Rmdir m_path
End Sub
End Class
Declare Function w32_OSGetSystemTempDirectory Lib \"nnotes\" Alias \"OSGetSystemTempDirectory\" ( Byval S As String) As Integer
Declare Function mac_OSGetSystemTempDirectory Lib \"NotesLib\" Alias \"OSGetSystemTempDirectory\" ( Byval S As String) As Integer
Declare Function linux_OSGetSystemTempDirectory Lib \"libnotes.so\" Alias \"OSGetSystemTempDirectory\" ( Byval S As String) As Integer

Function GetNotesTempDirectory() As String
\' Returns the path of the temporary directory used by Notes.
\' Not same as system or user temp dir that you can get e.g. with Environ(\"TEMP\") in Windows.
\' Main reasons to use this instead: works crossplatform, and partitioned servers each need
\' their own temp dir to avoid interfering with each other.
Dim session As New NotesSession
Dim d As String * 256
Dim s%
Select Case session.Platform
Case \"Linux\"
s% = linux_OSGetSystemTempDirectory(d)
Case \"Macintosh\"
s% = mac_OSGetSystemTempDirectory(d)
Case \"Windows/32\"
s% = w32_OSGetSystemTempDirectory(d)
Case Else
Error ERR_UNSUPPORTED_PLATFORM, \"In GetNotesTempDirectory, platform not supported: \" & session.Platform
End Select
GetNotesTempDirectory = Left$(d, s%)
End Function
 
H

hosm

done. link removed
Если еще посоветуете в личку, как назвать тему и описать по-русски правильно и поудобней (например, для удобства поиска), цены Вам не будет.
что-то не никак складно не придумывается, сплю на ходу, так уж сегодня получилось...
А если вместо мессаг "модераторы" вдруг сами запостите хорошее решение - смело заплюсую))) :(
Почитайте "пользование кодебейз", там же написано всё )
а то только 2-3 человека в КБ решения пишут, остальніе либо не знают, либо боятся ;)
 
Мы в соцсетях:

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