6 posts in this topic
I'm actually really proud of myself today. I'm always keen on using AutoIT wherever I can, as I've been developing in it since the age of 14 and whenever I meet any new technical staff or developers at the different clients I visit it always gets a mention and a demonstration. So we had a minor problem today at one of our clients, whereby they had an existing Windows Service implemented with a config file but the source-code was missing, which limited the ability of our company to enhance the interface in any way.
Now considering the fact that I was paid to develop this I will refrain from divulging any company names or "secrets" as, of course, there are clauses in my contract that state that my work belongs to them. I am however a SAP ABAP developer by trade so anything that falls outside of the defined limits of this trade I can technically share, but regardless I'll keep the information limited.
So the requirement was to pull data from IBM Websphere, write it out to a file and post it into SAP through a custom built RFC. It turned out to be much less complicated than I imagined and through the research on these forums, I had discovered that similar things had been attempted but that nothing concrete had been written for AutoIT specifically (The MQ part, not the SAP part). So without further adieu I present my thinking.
I started out with the IBM Websphere dll using DllOpen and DllCall. After a few frustrating attempts at creating COM objects through the DLL Call. I finally discovered that there was another dll that I could register using regsrv32. It was called MQAX200.dll
Once this dll was registered on the system I could access the following piece of code;
EnvSet("MQSERVER", $iniServer) ;MQ Server Environment Variable $MQSess = ObjCreate("MQAX200.MQSession") $QMgr = ObjCreate("MQAX200.MQQueueManager") $QMgr = $MQSess.AccessQueueManager($iniQM) ;Queue Manager ConsoleWrite("Connected" & @CRLF)
After this was complete and I successfully tested my connection I added the following to read from MQ;
$Queue = $QMgr.AccessQueue($iniQueue, 2) ;Queue (2=MQOO_INPUT, 16=MQOO_OUTPUT) While 1 $GetMsg = $MQSess.AccessMessage $GetOptions = $MQSess.AccessGetMessageOptions $Queue.Get($GetMsg, $GetOptions) If $Queue.ReasonCode = 2033 Then ;When there aren't any new messages sleep for 2 seconds. Sleep(2000) Else #EndRegion Accessing MQ #Region Write File $MsgData = $GetMsg.MessageData ....
I then wrote this out to a file and attempted my SAP connection using the following code;
Dim $LoggedIn = False $oConnection = $LogonControl.NewConnection $oConnection.System = $System $oConnection.ApplicationServer = $AppServer $oConnection.SystemNumber = $SysNumb $oConnection.User = $User $oConnection.Password = $Password $oConnection.Client = $Client $oConnection.Language = $Language $LoggedIn = $oConnection.Logon(0, True) Return $LoggedIn
which resulted in failure as the SAP COM object wasn't registered on the system. After attempting to register the correct object without installing SAP GUI, I ended up with a slightly different solution for an executable supplied by SAP called startrfc.exe;
$foo = Run(@ComSpec & " /c " & $RFCExec & " -3 -h " & $AppServer & " -s " & $SysNumber & " -F " & $RFC & " -u " & $User & " -p " & $Password & " -c " & $Client & " -l " & $Language & " -E FNAME=" & $FilePath & " -E PNAME=" & $Program, "", @SW_HIDE, $STDERR_CHILD + $STDOUT_CHILD) While 1 $line = StdoutRead($foo) If @error Then ExitLoop ConsoleWrite($line) $LogFile = FileOpen(StringReplace($FilePath, "\In\","\Logs\"), 2) FileWrite($LogFile, $Line) FileClose($LogFile) FileMove($FilePath, StringReplace($FilePath, "\In\","\Out\")) WEnd While 1 $line = StderrRead($foo) If @error Then ExitLoop ConsoleWrite($line) $ErrFile = FileOpen(StringReplace($FilePath, "\In\","\Errors\E"), 2) FileWrite($ErrFile, $Line) FileClose($ErrFile) FileMove($FilePath, StringReplace($FilePath, "\In\","\Errors\")) WEnd
One last piece of code that you should keep in mind if you attempt this so that your program doesn't stop when a COM error is returned (MQ returns an error that indicates there is no data available on the queue as you see with the reason code check earlier);
Global $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc") ;Catch COM errors
In conclusion, I really enjoyed implementing something that'll be used for the foreseeable future at a powerful company and writing it in my favorite language. I hope you find some use in these snippets.
This will be running as a Windows Service from now on using srvany.exe.