Войти

Показать полную графическую версию : СОМ-интерфейс на AutoIt-е


abb269
05-08-2009, 10:29
Здравствуйте,
Подскажите, пожалуйста, в каком направлении смотреть.
Нужно реализовать на AutoIt-е СОМ-интерфейс, который на VBA выглядит примерно так

' Обработка событий
Public WithEvents stClient As StServer

Private Sub Class_Initialize()
If stClient Is Nothing Then
Set stClient = New StServer
If Err.Number <> 0 Then MsgBox ("Error " & Err.Description)
If stClient Is Nothing Then
MsgBox ("Невозможно установить соединение")
Else
'MsgBox ("Соединение установлено")
End If
End If
End Sub

Private Sub Class_Terminate()
If stClient Is Nothing Then
MsgBox ("Соединение уже разорвано")
Else
Set stClient = Nothing
'MsgBox ("Соединение разорвано")
End If
End Sub

Private Sub stClient_Connected()
' обработка события
бла-бла-бла
End Sub

Private Sub stClient_Disconnected(ByVal reason As String)
' обработка события
бла-бла-бла
End Sub


'Методы
Private stSrv As StServerTest
Sub КнопкаСтарт_Щелчок()
' ---------------- установка соединения
If stSrv Is Nothing Then
Set stSrv = New StServerTest
If Not stSrv.stClient.IsConnected() Then MsgBox ("Убедитесь что установлено соединение с сервером")
Else
MsgBox ("Соединение уже установлено")
End If ' конец установки соединения

Call stSrv.stClient.Test(...)
...
end sub


Заранее спасибо за квалифицированный ответ.

amel27
05-08-2009, 12:28
Нужно реализовать на AutoIt-е СОМ-интерфейс »В такой формулировке задача нерешаема, т.к. AutoIt - процедурный язык, а не объектный... максимум, что можно сделать - реализовать часть методов на AutoIT через вызов внешнего AutoIT-скрипта с параметрами.

В чем, собственно, проблема? Описание размыто и непонятно, описание некоторых типов вообще пропущено.

abb269
05-08-2009, 12:56
Спасибо за ответ.
А проблема вот в чем. Есть биржевой терминал с СОМ-интерфейсом, я подключаюсь к нему через экселевский VBA (из которого и взял фрагменты кода интерфейса). И за этой связкой (терминал-Эксель) присматривает супервизор, который я написал на AutoIt. Немного продвинувшись в среду AutoIt-а, я решил в своей конструкции выкинуть вообще эксель. С переносом вычислений особых проблем не возникло, а вот как перекинуть коннект?
Получается, что ни как. Жаль.
Еще раз спасибо.

amel27
05-08-2009, 13:10
abb269, подключиться к существующему COM-серверу без проблем, нельзя определить свои COM-объекты... приведите полный код VBA-модулей, иначе не ясно, где ссылка на VBA-компоненты, а где на терминальные... и желательно: уже реализованную часть на AutoIT + описание интерфейсов терминала. Без полной картины нельзя дать однозначного ответа.

abb269
05-08-2009, 15:14
Не могу не сказать еще раз спасибо.
Вот структура VBA-код модуля сервера (тип Class Modules, имя StserverTest)

Public WithEvents stClient As StServer

Private Sub Class_Initialize()
If stClient Is Nothing Then
Set stClient = New StServer
If Err.Number <> 0 Then MsgBox ("Error " & Err.Description)
If stClient Is Nothing Then
MsgBox ("Невозможно установить соединение")
Else
'MsgBox ("Соединение установлено")
End If
End If
End Sub

Private Sub Class_Terminate()
If stClient Is Nothing Then
MsgBox ("Соединение уже разорвано")
Else
Set stClient = Nothing
'MsgBox ("Соединение разорвано")
End If
End Sub

Private Sub stClient_Connected()
Range("connection_status_time").Value = Now
Range("connection_status").Value = "соединен"
End Sub

Private Sub stClient_Disconnected(ByVal reason As String)
Range("connection_status_time").Value = Now
Range("connection_status").Value = "НЕТ СОЕДИНЕНИЯ : " & reason
End Sub

Private Sub stClient_OrderFailed(ByVal cookie As Long, ByVal reason As String)
Range("order_status_time").Value = Now
Range("order_status").Value = 1 ' ОШИБКА ОТПРАВКИ приказа на сервер
Range("order_status_note").Value = reason & " * " & cookie
End Sub

Private Sub stClient_OrderSucceeded(ByVal cookie As Long)
Range("order_status_time").Value = Now
Range("order_status").Value = 0 ' успех отправки приказа на сервер
Range("order_status_note").Value = cookie
End Sub

Private Sub stClient_SetPortfolio( _
ByVal portfolio As String, _
ByVal cash As Double, _
ByVal leverage As Double, _
ByVal comission As Double, _
ByVal saldo As Double)

Range("a_portfolio").Value = PortfolioArray
Range("set_portfolio_time") = Now

End Sub

Private Sub stClient_UpdateOrder( _
ByVal portfolio As String, _
ByVal symbol As String, _
ByVal state As Long, _
ByVal action As Long, _
ByVal otype As Long, _
ByVal validity As Long, _
ByVal price As Double, _
ByVal amount As Double, _
ByVal stopp As Double, _
ByVal filled As Double, _
ByVal datetime As Date, _
ByVal orderid As String, _
ByVal orderno As String)

...
End Sub

Private Sub stClient_UpdatePosition( _
ByVal portfolio As String, _
ByVal symbol As String, _
ByVal avprice As Double, _
ByVal amount As Double, _
ByVal planned As Double)

...
End Sub

Private Sub stClient_UpdateQuote( _
ByVal symbol As String, _
ByVal datetime As Date, _
ByVal opn As Double, _
ByVal high As Double, _
ByVal low As Double, _
ByVal closse As Double, _
ByVal last As Double, _
ByVal volume As Double, _
ByVal size As Double, _
ByVal bid As Double, _
ByVal ask As Double, _
ByVal bidsize As Double, _
ByVal asksize As Double, _
ByVal open_int As Double, _
ByVal go_buy As Double, _
ByVal go_sell As Double, _
ByVal go_base As Double, _
ByVal go_base_backed As Double)

...
End Sub

Private Sub stClient_AddBar( _
ByVal symbol As String, _
ByVal interval As Long, _
ByVal datetime As Date, _
ByVal opn As Double, _
ByVal high As Double, _
ByVal low As Double, _
ByVal closse As Double, _
ByVal volume As Double)

...
End Sub


А в клиентской части (не знаю, верно ли использую это название), т.е. там где вызываются методы, вот такой код (тип Modules, имя abb)



Private stSrv As StServerTest

Sub RunConnect()
If stSrv Is Nothing Then
Set stSrv = New StServerTest
If Not stSrv.stClient.IsConnected() Then
MsgBox ("Убедитесь что установлено соединение с сервером")
End If
Else
MsgBox ("Соединение уже установлено")
End If
End Sub

Sub PlaceOrder()
If stSrv Is Nothing Then
MsgBox ("Соединение не установлено!")
Else
Response = MsgBox("Выставить приказ?", vbYesNo)
If Response = vbYes Then
Call stSrv.stClient.PlaceOrder( _
Range("portfolio").Value, _
Range("quote_ticker").Value, _
Range("o_action_new").Value, _
Range("o_type_new").Value, _
Range("o_validity_new").Value, _
Range("o_price_new").Value, _
Range("o_amount_new").Value, _
0, _
0)
End If
End If
End Sub

и т.д.



Общая структура интерфейса такая

МЕТОД --> СОБЫТИЯ, вызываемые методом
ListenQuotes (1 параметр)/CancelQuotes (1 параметр) --> UpdateQuote (18 параметров)
ListenBidAsks (1 параметр)/CancelBidAsks (1 параметр) --> UpdateBidAsk (7 параметров)
ListenTicks (1 параметр)/CancelTicks (1 параметр) --> AddTick (4 параметра)
GetBars (4 параметра) --> AddBar (8 параметров)
ListenPortfolio (1 параметр)/CancelPortfolio (1 параметр) --> SetPortfolio (5 параметров);UpdateOrder (13 параметров);AddTrade (6 параметров);UpdatePosition (5 параметров)
PlaceOrder (9 параметров) --> OrderSucceeded (1 параметр);OrderFailed (2 параметра)
CancelOrder (3 параметра) --> -
GetSymbols() --> AddSymbol (10 параметров)
- --> Connected ()
- --> Disconnected (1 параметр)
IsConnected () -->??? True/False

А про код на AutoIt-е можно сказать, что он смысловой нагрузки не несет. Он просто входит в биржевой терминал (вводит имя и пароль), вводит в Эксель начальные установки (типа тикера, размера позиции и т.д), периодически читает данные в Экселе и посылает отчет в виде е-мейла.
Да забыл сказать, что все это что-то типа торгового робота.

amel27
06-08-2009, 13:21
не знаю, верно ли использую это название »Перенос программы с объектного языка на процедурный нетривиальная задача и без понимания всех деталей работы исходной программы лучше за нее не браться... Хотя ИМХО весь код, который не связан с обработкой асинхронных событий (т.е. вызванных внешними источниками - пользователем, сторонними процессами и т.п.) вполне можно вынести за пределы Excel на любую удобную платформу, но это лучше делать постепенно - заменяя события и прочие объектные фичи на прямой вызов методов (aka функций), чтобы не нарушать функциональность... Короче, нужно хорошо взвесить все ЗА и ПРОТИВ прежде чем браться за подобное мероприятие.

abb269
06-08-2009, 22:06
2amel27
А можно чуть конкретнее?
Как написать свой обработчик какого-нибудь события на AutoIt? как его объявить?
Или лучше за это на AutoIt-e не браться, а просто оставить интерфейс на Экселе и вызывать экселевские макросы из AutoIt-а?..
На этот раз - извините.

amel27
07-08-2009, 09:25
Как написать свой обработчик какого-нибудь события на AutoIt? »хороший вопрос, вообще-то для этого есть ObjEvent(), но если для MS Word этот метод работает, то для MS Excel почему-то нет... :idontnow: на форуме оффсайта вопрос поднимался, но ответа никто так и не дал: Failing to hook Excel events. Error on ObjEvent() call with Excel, but not with Word (http://www.autoitscript.com/forum/index.php?showtopic=72109)... собственно, пример для WORD:
$oWord = ObjCreate("Word.Application")
$oWord.Visible = 1
$oWord.Activate ()
$hwnd = WinGetHandle("[ACTIVE]")

$oMyError = ObjEvent("AutoIt.Error","MyErrFunc")
$oMyEvent = ObjEvent($oWord, "Evt_")

$oWord.Documents.Add ()
$oWord.Documents.Add ()
$oWord.ActiveDocument.Close ()

While WinExists($hwnd)
Sleep(50)
WEnd

Func Evt_DocumentBeforeClose()
ConsoleWrite("Captured Mesage: DocumentBeforeClose" &@CRLF)
EndFunc

Func Evt_NewDocument()
ConsoleWrite("Captured Mesage: NewDocument" &@CRLF)
EndFunc

Func Evt_Quit()
ConsoleWrite("Captured Mesage: Quit" &@CRLF)
EndFunc

Func MyErrFunc()
Dim $msgTxt
$msgTxt = "We intercepted a COM Error !" & @CRLF & @CRLF & _
"err.description is: " & @TAB & $oMyError.description & @CRLF & _
"err.windescription:" & @TAB & $oMyError.windescription & @CRLF & _
"err.number is: " & @TAB & hex($oMyError.number,8) & @CRLF & _
"err.lastdllerror is: " & @TAB & $oMyError.lastdllerror & @CRLF & _
"err.scriptline is: " & @TAB & $oMyError.scriptline & @CRLF & _
"err.source is: " & @TAB & $oMyError.source & @CRLF & _
"err.helpfile is: " & @TAB & $oMyError.helpfile & @CRLF & _
"err.helpcontext is: " & @TAB & $oMyError.helpcontext

Msgbox(0,"AutoItCOM Test", $msgTxt)
ConsoleWrite($msgTxt & @LF)

Local $err = $oMyError.number
If $err = 0 Then $err = -1

$g_eventerror = $err ; to check for after this function returns
Endfunc




© OSzone.net 2001-2012