Что нового

Проблема с COM Object wodXMPP

ynbIpb

Скриптер
Сообщения
399
Репутация
109
Существует такой замечательный компонент wodXMPP для работы с протоколом XMPP (Jabber) Очень много функций и хорошая документация. Чтоб его использовать необходимо скопировать библиотеку wodXMPP.dll в системную папку (@SystemDir) и зарегистрировать в системе (RegSvr32.EXE wodXMPP.dll). При установке набора с офсайта, это всё делается автоматически.
Простенький пример подключения к серверу:
Код:
$sLogin = "[email protected]"
$sPassword = "testing"
$xmpp = ObjCreate("WeOnlyDo.wodXMPPCom.1")
$xmpp.Login = $sLogin
$xmpp.Password = $sPassword
$xmpp.Connect

While 1
	sleep (100)
WEnd

Возникла заминка в следующем:
В справке написано...
Unlike ActiveX controls, which are licensed the moment you put them on the form (if you have a licensed version of wodXMPP, of course), COM object licensing is not directly supported by any container. Therefore you need to add one more line to your code to license wodXMPP correctly:
XMPP1.LicenseKey = "put.your.key.here"
Тоесть как я понял это должно выглядеть примерно так:
Код:
$xmpp = ObjCreate("WeOnlyDo.wodXMPPCom.1")
$xmpp.LicenseKey = "XXXX-XXXX-XXXX-XXXX"
$xmpp.About

Но, не работает - The requested action with this object has failed.
На офсайте откопал пример на VB
5. Open the code editor and at the top in the (General) section add this code:

Dim WithEvents XMPP1 As wodXMPPCom

6. In Form_Load function initialize the component:

Private Sub Form_Load()
Set XMPP1 = New wodXMPPCom
End Sub


7. If you have the licensed version of wodXMPP, then after you initialize the component, set its LicenseKey property:

Private Sub Form_Load()
Set XMPP1 = New wodXMPPCom
XMPP1.LicenseKey = "xxxx....xxxx"
End Sub
Как правильно подать этот параметр?

з.ы.
топик на англ. форуме: wodXMPP & Autoit
Приглашаю всех желающих помочь разобраться с этим компонентом, может кто простенький джаббер клиент напишет для примера\наглядности работы.
Заранее благодарен.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
ynbIpb
а чем существующий плох? я про JAdmin
http://autoit-script.ru/index.php/topic,2257.0.html
 
Автор
ynbIpb

ynbIpb

Скриптер
Сообщения
399
Репутация
109
Я хочу добиться многопоточности, тоесть работа с протоколом будет в своём потоке (благодаря отдельному компоненту), а Автоит будет сам по себе. К томуже в компоненте реализовано больше возможностей протокола: передача файлов, работа с контакт листом, чат румы, Vcard и т.д.
Также предлагаю Nik_rus перейти на этот компонент.
 
Автор
ynbIpb

ynbIpb

Скриптер
Сообщения
399
Репутация
109
Всё причина найдена!
Дело в том, что на официальном сайте находится кастрированная демо версия компонента, в которой вообще не предусмотренно возможности зарегистрировать его. По этому и вылетает ошибка, так как функции object.LicenseKey там вообще нет.
Я раздобыл нормальную версию и ключ, всё регистрируется и работает. Тут выкладывать это нельзя, так как нарушаются авторские права, но в ПМ дам всем желающим (подсказка: Citron)
Пример с отправкой сообщения:
Код:
AutoItSetOption ( "TrayAutoPause", 0) ; отключаем автоматическую остановку скрипта при клике в трее

; START: ~~~~~~~~~~~~~~ объявляем переменные ~~~~~~~~~~~~~~~~
$sWodXMPP_dll = @SystemDir & "\wodXMPP.dll" ; путь к установленной библиотеке
$sSettings_ini = @ScriptDir & "\settings.ini" ; путь к файлу с настройками
$sLicenseKey = "XXXX-XXXX-XXXX-XXXX" ; лицензионный ключ для компонента WodXMPP
$sBotname = "MyJabber v.0.1" ; имя и версия
; END: ~~~~~~~~~~~~~~~~ объявляем переменные ~~~~~~~~~~~~~~~~

If FileExists ($sWodXMPP_dll) = 0 Then ; если файл не существует
	FileCopy (@ScriptDir & "\wodXMPP.dll", $sWodXMPP_dll, 1) ; копируем в системную папку
	RunWait(@SystemDir & '\regsvr32.exe /s ' & $sWodXMPP_dll) ; регистрируем компонент в системе
EndIf


If FileExists ($sSettings_ini) = 0 Then  ; если ini файл не существует, то 
	$hSettings_ini = FileOpen ($sSettings_ini, 2) ; открываем файл для записи с затиранием
	FileWrite ($hSettings_ini, "[general]" & @CRLF _ ; записываем структуру ini файла
							 & "jid=" & @CRLF _ 
							 & "pass=")
	FileClose ($hSettings_ini) ; закрываем ini файл
	TrayTip ($sBotname, "Please edit the file settings.ini", 3, 1) ; показываем уведомление о необходимости отредактировать его
	Sleep (3000)
	Exit
EndIf
; START: ~~~~~~~~~~~~~~ читаем настройки из ini файла ~~~~~~~~~~~~~~~~
$sJID = IniRead ($sSettings_ini, "general", "jid", ""); читаем Jabber ID
$sPASS = IniRead ($sSettings_ini, "general", "pass", ""); читаем пароль
; END:   ~~~~~~~~~~~~~~ читаем настройки из ini файла ~~~~~~~~~~~~~~~~
$xmpp = ObjCreate("WeOnlyDo.wodXMPPCom.1")
$xmpp.LicenseKey = $sLicenseKey ; передаём компоненту лиц. ключ
;$xmpp.About
$xmpp.Security = 0 ; не использовать безопасное соединение
$xmpp.Authentication = 0 ; автоматический выбор метода аутентификации
$xmpp.Login = $sJID
$xmpp.Password = $sPASS
$xmpp.Connect


While 1
	sleep (100)
	$iStatus =  $xmpp.State ; определяем статус соединения
	If $iStatus = 5 Then ; если 5 -  соединён
		TrayTip ($sBotname&"  Status", "Connected!", 3, 1)
		Sleep (3000)
		TrayTip ("", "", 0); убираем подсказку
		$xmpp.SendText ("[email protected]mail.com", "Hello World! (Test Message)"); отправляем сообщение
		Sleep (3000)
		$xmpp.Disconnect ; отключаемся от сервера
	EndIf
	
	If $iStatus = 0 Then ; если 0 - отсоединён 
		TrayTip ($sBotname&"  Status", "Disconnected!", 3, 1)
		Sleep (3000)
		Exit
	EndIf
WEnd

При методе отправки object.SendText необходимо чтобы адресат был в контактлисте и авторизован, иначе сообщение не доходит.
 

Nik_rus

Python The Snake.
Сообщения
214
Репутация
62
Идея какбэ хорошая но и какбэ не очень.
Не знаю, у меня внутренний стереотип, что COM может работать криво.
Хотя можно попробовать... однако придется с собой таскать эту либу - даже при компиленном варианте.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Nik_rus
ну еще и не забывай про лицензирование. обсуждаемая либа - не опенсорс, и даже на фри ;)
 

Nik_rus

Python The Snake.
Сообщения
214
Репутация
62
Kaster, абсолютно согласен.
 
Автор
ynbIpb

ynbIpb

Скриптер
Сообщения
399
Репутация
109
Всё ясно. Можно тогда пока темку не прикрывать, я в процессе освоения буду тут вопросы задавать и делиться наработками.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
ynbIpb
без проблем. процесс закрытия темы регламентирован правилами. пока все пучком, тему никто не закроет.
 
Автор
ynbIpb

ynbIpb

Скриптер
Сообщения
399
Репутация
109
Вот и первая проблема. Не пойму как получать сообщения?
из справки ясно что это вроде как: object.IncomingMessage за это отвечает
Но как его применить не пойму.

онлайн справка: XMPP Help
база примеров: example
 
Автор
ynbIpb

ynbIpb

Скриптер
Сообщения
399
Репутация
109
UP!

Народ выручайте! Так и не могу заставить получать входящие сообщения.
Дано: пример на Visual Basic 5 - Simple_example_VB_5.rar(в комплекте: исходник, скомпиленый вариант, Runtime если не запускается, сам компонент и аккаунт для теста)
Ошибочка вышла, это был пример для *.OCX компонента. Вот правильный: Simple_example_VB_5_new.rar



Задача: воссоздать его на AutoIt.
Моя попытка:
Код:
#NoTrayIcon
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

OnAutoItExitRegister( "_Jdisconnect" )
$sWodXMPP_dll = @SystemDir & "\wodXMPP.dll"
$sSettings_ini = @ScriptDir & "\settings.ini"

If FileExists ($sWodXMPP_dll) = 0 Then 
    FileCopy (@ScriptDir & "\wodXMPP.dll", $sWodXMPP_dll, 1) ; copy to system folder
    RunWait(@SystemDir & '\regsvr32.exe /s ' & $sWodXMPP_dll) ; register a component in the system
EndIf
$xmpp = ObjCreate("WeOnlyDo.wodXMPPCom.1")

$Form1 = GUICreate("Simple Example wodXMPP ActiveX", 528, 410)
$Label1 = GUICtrlCreateLabel("Jabber ID:", 8, 8, 53, 17)
$Label2 = GUICtrlCreateLabel("Password:", 8, 32, 53, 17)
$Input1 = GUICtrlCreateInput("", 65, 5, 215, 21) ; jabber ID
$Input2 = GUICtrlCreateInput("", 65, 30, 215, 21) ; password
$List1 = GUICtrlCreateList("", 288, 5, 233, 357)
$Checkbox1 = GUICtrlCreateCheckbox("Register as new user", 8, 60, 177, 17)
$Button1 = GUICtrlCreateButton("Go online", 8, 90, 132, 35)
$Button2 = GUICtrlCreateButton("Offline", 148, 90, 132, 35)
GUICtrlSetState ($Button2, $GUI_DISABLE)
$Label3 = GUICtrlCreateLabel("Send message to:", 8, 327, 89, 17)
$Input3 = GUICtrlCreateInput("", 104, 324, 177, 21)
$Edit1 = GUICtrlCreateEdit("", 8, 348, 218, 50, BitOR ($ES_MULTILINE, $ES_AUTOVSCROLL, $ES_MULTILINE, $ES_WANTRETURN))
$Button3 = GUICtrlCreateButton("Send", 230, 348, 50, 50)
GUICtrlSetState ($Button3, $GUI_DISABLE)
$Label4 = GUICtrlCreateLabel("", 288, 368, 233, 35, $SS_CENTER)
If FileExists ($sSettings_ini) Then
    GUICtrlSetData ($Input1, IniRead ($sSettings_ini, "general", "jid", ""))
    GUICtrlSetData ($Input2, IniRead ($sSettings_ini, "general", "pass", ""))
EndIf
GUISetState(@SW_SHOW)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Button1
            _Connect_to_server()
        Case $Button2
            _Disconnect_from_server()
        Case $Button3
            _send_message ()
    EndSwitch
WEnd

Func _Connect_to_server()
    $sJid = GUICtrlRead ($Input1)
    $sPass = GUICtrlRead ($Input2)
    If $sJid = "" Or $sPass = "" Then
        GUICtrlSetData ($Label4, "Error! Please enter your login and password")
        Return
    EndIf
    GUICtrlSetData ($Label4, "Connecting...")
    $xmpp.Security = 0 
    $xmpp.Authentication = 0 
    $xmpp.Login = $sJid
    $xmpp.Password = $sPass
    $conn_timer_begin = TimerInit()
    $iStatus =  $xmpp.State 
    If $iStatus = 0 Then 
        $xmpp.Connect 
        While $iStatus <> 5 
            sleep (200)
            $iStatus =  $xmpp.State 
            $conn_timer_diff = TimerDiff($conn_timer_begin)
            If  $conn_timer_diff >= 20000 And $iStatus = 0 Then
                GUICtrlSetData ($Label4, "Error! Not Connected")
                Return
            EndIf
        WEnd
    EndIf
    GUICtrlSetData ($Label4, "Online!")
    GUICtrlSetState ($Button1, $GUI_DISABLE)
    GUICtrlSetState ($Button2, $GUI_ENABLE)
    GUICtrlSetState ($Button3, $GUI_ENABLE)
EndFunc

Func _send_message ()
    $sMessageText = GUICtrlRead ($Edit1)
    $sRecipient = GUICtrlRead ($Input3)
    If $sMessageText = "" or $sRecipient = "" Then
        GUICtrlSetData ($Label4, "Error! Nothing to send or no the recipient.")
        Return
    EndIf
    $xmpp.SendText ($sRecipient, $sMessageText)
    GUICtrlSetData ($Edit1, "")
EndFunc

Func _Disconnect_from_server()
    $xmpp.Disconnect
    GUICtrlSetData ($Label4, "Offline!")
    GUICtrlSetState ($Button2, $GUI_DISABLE)
    GUICtrlSetState ($Button3, $GUI_DISABLE)
    GUICtrlSetState ($Button1, $GUI_ENABLE)
EndFunc

Func _Jdisconnect () 
    $xmpp.Disconnect 
EndFunc

Основная проблема: я не могу понять принципа работы с эвентами в объектах.

Вот, что мне дали буржуи:

The secret is ObjEvent function. You should learn o use it o be able to get the most out of this.
Another good thing is AutoItObject.au3 (search the forums). It makes registering redundant. That means the user doesn't have to be admin to be able to use your app.
Example would (or could) be:

Код:
#NoTrayIcon
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#AutoIt3Wrapper_UseX64=n

#include <GUIListBox.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include "AutoItObject.au3"

_AutoItObject_Startup()
; Error monitoring
Global $oError = ObjEvent("AutoIt.Error", "_ErrFunc")
Func _ErrFunc()
    ConsoleWrite("! COM Error !  Number: 0x" & Hex($oError.number, 8) & "   ScriptLine: " & $oError.scriptline & " - " & $oError.windescription & @CRLF)
    Return
EndFunc   ;==>_ErrFunc


OnAutoItExitRegister( "_Jdisconnect" )

$sSettings_ini = @ScriptDir & "\settings.ini"

;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$sWodXMPP_dll = @ScriptDir & "\wodXMPP.dll"
$sCLSID = "{19DCD07D-C515-45FD-A008-AB0D90743EDE}"
$sIID = "{D79294AB-FB41-43DF-A625-885D4E2E8AAC}"

;~ $xmpp = ObjCreate("WeOnlyDo.wodXMPPCom.1")
$xmpp = _AutoItObject_ObjCreateEx($sWodXMPP_dll, $sCLSID, $sIID)
Global $oEvent = ObjEvent($xmpp, "wodXMPP1_", "_IwodXMPPComEvents")
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

$Form1 = GUICreate("Simple Example wodXMPP ActiveX", 528, 410)
$Label1 = GUICtrlCreateLabel("Jabber ID:", 8, 8, 53, 17)
$Label2 = GUICtrlCreateLabel("Password:", 8, 32, 53, 17)
$Input1 = GUICtrlCreateInput("", 65, 5, 215, 21) ; jabber ID
$Input2 = GUICtrlCreateInput("", 65, 30, 215, 21) ; password
$List1 = GUICtrlCreateList("", 288, 5, 233, 357)
$Checkbox1 = GUICtrlCreateCheckbox("Register as new user", 8, 60, 177, 17)
$Button1 = GUICtrlCreateButton("Go online", 8, 90, 132, 35)
$Button2 = GUICtrlCreateButton("Offline", 148, 90, 132, 35)
GUICtrlSetState ($Button2, $GUI_DISABLE)
$Label3 = GUICtrlCreateLabel("Send message to:", 8, 327, 89, 17)
$Input3 = GUICtrlCreateInput("", 104, 324, 177, 21)
$Edit1 = GUICtrlCreateEdit("", 8, 348, 218, 50, BitOR ($ES_MULTILINE, $ES_AUTOVSCROLL, $ES_MULTILINE, $ES_WANTRETURN))
$Button3 = GUICtrlCreateButton("Send", 230, 348, 50, 50)
GUICtrlSetState ($Button3, $GUI_DISABLE)
$Label4 = GUICtrlCreateLabel("", 288, 368, 233, 35, $SS_CENTER)
If FileExists ($sSettings_ini) Then
    GUICtrlSetData ($Input1, IniRead ($sSettings_ini, "general", "jid", ""))
    GUICtrlSetData ($Input2, IniRead ($sSettings_ini, "general", "pass", ""))
EndIf
GUISetState(@SW_SHOW)

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $Button1
            _Connect_to_server()
        Case $Button2
            _Disconnect_from_server()
        Case $Button3
            _send_message ()
    EndSwitch
WEnd

Func _Connect_to_server()
    $sJid = GUICtrlRead ($Input1)
    $sPass = GUICtrlRead ($Input2)
    If $sJid = "" Or $sPass = "" Then
        GUICtrlSetData ($Label4, "Error! Please enter your login and password")
        Return
    EndIf
    GUICtrlSetData ($Label4, "Connecting...")
    $xmpp.Security = 0
    $xmpp.Authentication = 0
    $xmpp.Login = $sJid
    $xmpp.Password = $sPass
    $conn_timer_begin = TimerInit()
    $iStatus =  $xmpp.State
    If $iStatus = 0 Then
        $xmpp.Connect
        While $iStatus <> 5
            sleep (200)
            $iStatus =  $xmpp.State
            $conn_timer_diff = TimerDiff($conn_timer_begin)
            If  $conn_timer_diff >= 20000 And $iStatus = 0 Then
                GUICtrlSetData ($Label4, "Error! Not Connected")
                Return
            EndIf
        WEnd
    EndIf
    GUICtrlSetData ($Label4, "Online!")
    GUICtrlSetState ($Button1, $GUI_DISABLE)
    GUICtrlSetState ($Button2, $GUI_ENABLE)
    GUICtrlSetState ($Button3, $GUI_ENABLE)
EndFunc

Func _send_message ()
    $sMessageText = GUICtrlRead ($Edit1)
    $sRecipient = GUICtrlRead ($Input3)
    If $sMessageText = "" or $sRecipient = "" Then
        GUICtrlSetData ($Label4, "Error! Nothing to send or no the recipient.")
        Return
    EndIf
    $xmpp.SendText ($sRecipient, $sMessageText)
    GUICtrlSetData ($Edit1, "")
EndFunc

Func _Disconnect_from_server()
    $xmpp.Disconnect
    GUICtrlSetData ($Label4, "Offline!")
    GUICtrlSetState ($Button2, $GUI_DISABLE)
    GUICtrlSetState ($Button3, $GUI_DISABLE)
    GUICtrlSetState ($Button1, $GUI_ENABLE)
EndFunc

Func _Jdisconnect ()
    $xmpp.Disconnect
EndFunc

;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Func wodXMPP1_Connected()
    ConsoleWrite(">Fired when wodXMPP connects. So, it should be connected now." & @CRLF)
EndFunc

Func wodXMPP1_Disconnected($iErrorCode, $sErrorText)
    ConsoleWrite("-Fired when wodXMPP disconnected -> ErrorCode = " & $iErrorCode & ", ErrorText = " & $sErrorText & @CRLF)
EndFunc

Func wodXMPP1_IncomingMessage($oContact, $oChatRoom, $oMessage)
    ConsoleWrite("+>Fired when new message is received -> Message from " & $oContact.Nick & ":" & @TAB & $oMessage.Text & @CRLF)
EndFunc
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Third good thing that you could use is TLBViewer.au3 (again search for it). That's how I expanded your script.

edit: untested of course. :idiot:
And using wodXMPP.dll from script's dir.


--------------- updated ---------------
Вот ещё разработчики компонента мне дали наводку:
Hi,

Well, theoretically it should look something like this in VBS (our simple sample, just added IncomingMessage event, and additional comment):
Код:
Option Explicit 
Dim XMPP1 
Set XMPP1 = WScript.CreateObject( "WeOnlyDo.wodXMPPCom.1", "wod_") 

' please change these lines, from here 
WScript.echo "Please edit this file to setup Login and Password properties" 

XMPP1.Login = "somename( at )wippien( point )com" 
XMPP1.Password = "password" 
XMPP1.Blocking = True 
'XMPP1.Register = True ' register new account 
XMPP1.Connect 

you can add someone to your contact list... 
XMPP1.SendText "someone( at )wippien( point )com", "Hello there!" 

'Some kind of a message loop 
'should be implemented here 
'to keep wodXMPP working, 
'since it would otherwise "die" 
'at the end of script execution 

Sub wod_Disconnected() 
WScript.Echo "Done and disconnected" 
End Sub 

Sub wod_IncomingMessage(Contact, Message) 
WScript.Echo "Message From " & Contact.JID & vbcrlf & "Text: " & Message.Text 
End Sub

Hope this helps.

Regards,
Damba
----------------- updated -----------------
Удалось добиться срабатывания пустого эвента Connected.
Код:
$xmpp = ObjCreate("WeOnlyDo.wodXMPPCom.1")
; добавил после создания объекта вот это
$XmppEvent = ObjEvent ($xmpp, "xmpp_")
; и в конце создал функцию с этим префиксом и самим названием эвента
Func xmpp_Connected()
	MsgBox (0, "", "Конектед!!!", 3)
EndFunc

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

beve

Осваивающий
Сообщения
104
Репутация
30
Но! Срабатывает он только один раз, повторно уже нет. пока не перезапустишь полностью скрипт.
Действительно только один раз. Кстати в "варианте от ненаших" эта функция wodXMPP1_Connected() работает аналогично. Еще добавлю такое:
если отослать сообщение этому jid-номеру, а потом запустить скрипт и авторизоваться с этим jid-номером, то срабатывает функция wodXMPP1_IncomingMessage(), которая принимает отосланное ранее (когда jid был вне сети) сообщение, но, опять таки, только в этом случае.
 
Верх