Jump to content

SOLVED: Unable to display MsgBox from Service

Recommended Posts


I'm unable to display a message box from a compiled AutoIt alerting script that is executed from a service (also a compiled AutoIt script). I used $MB_SERVICE_NOTIFICATION, but the dialog doesn't appear and the alerting script continues as if the OK button had been clicked. The service script uses ShellExecute() to launch the alerter (as opposed to a *Wait() call) so it can continue processing. Note that we used Windows Service Wrapper (winsw) to turn the compiled script into a service but haven't identified any issues from it.

I tried the one-line execute example given in this thread: Message box timeout not working

$iPID = Run(@AutoItExe & ' /AutoIt3ExecuteLine  "MsgBox(2097152, ''' & $sTitle & ''', ''' & $sText & ''')"')

without the timeout code, but no luck: the MsgBox does not appear. (In any case, we don't have AutoIt installed on the target system, so it would have to be converted into a .exe file.)

We're developing and unit-testing on Win 7 Enterprise; the target OS is Win 7 Pro, and the AutoIt version is

Any solutions or suggestions will be much appreciated. Code fragments are below.



The following code fragment is the relevant portion of the alerting script that displays the MsgBox:


; Alert the operator that there's a problem with the recording
$sFeed = $aRecInfo[6]
$sSession = $aRecInfo[2]
$sTemp = $aRecInfo[4]
$sDate = _FormatDate($sTemp)
$sTemp = $aRecInfo[5]
$sTime = _FormatTime($sTemp)
_Debug2("Inactive recording feed " & $sFeed & ", Session=" & $sSession & ", Start Date/Time=" & _
                $sDate & " " & $sTime)
$sErrorMsg = "ERROR: Feed " & $sFeed & " for session " & $sSession & " stopped, notify reporter immediately"


_Debug1("Displaying MsgBox...")
_Debug1("Returned from MsgBox")



And the calling code fragment in the service is:

; Walk through the array backwards so we don't end up evaluating an index that doesn't exist
    For $iIndex = UBound($aFeedArray)-1 To 0 Step -1

            ; Before timing-out the feed, check for a .mpgpart file (=> feed may still be recording)
            $sDirPath = $sDirTemp & "\" & $sFeedTemp & "\" & $aFeedArray[$iIndex][$cSessionName]
            $sMpgPartName = GetMpgPart($sDirPath, $sFeedTemp)
            If StringLen($sMpgPartName) > 0 Then
                ; If .mpgpart file name hasn't changed in more than $iDeadFeedTime seconds, then declare feed dead
                ; ========v Test code to force error v========
                $sMpgPartName = $aFeedArray[$iIndex][$cMpgPartName]
                ; ========^ Test code to force error ^========
                _Debug2("Just set $sMpgPartName to '" & $sMpgPartName & "', should fall into dead-feed code")
                If $sMpgPartName = $aFeedArray[$iIndex][$cMpgPartName] Then
                    ; Name is same => feed is dead: alert the operator and delete the feed w/out stop-processing
                    _Debug2("Feed " & $sFeedTemp & " looks dead -- alerting the operator")
                    _Debug2("Delete GUID " & $aFeedArray[$iIndex][$cGUID])

                    ; ======== Alert app execution ========
                    ; $sAlertApp = @ScriptDir & "\" & "RecAlert.exe"
                    $iChildPid = ShellExecute($sAlertApp, $sDirPath, "", "open")
                    _Debug2("Alert app: ShellExecute(): " & _RetStr($iChildPid, @error, @extended))
                    _ArrayDelete($aFeedArray, $iIndex)                  
                    ; Otherwise, the .mpgpart name has changed, reset the timer, store the name, and continue
                    _Debug2("Feed " & $sFeedTemp & " timeout, but has new .mpgpart file -- continuing")
                    $aFeedArray[$iIndex][$cDateTime] = TimerInit()
                    $aFeedArray[$iIndex][$cMpgPartName] = $sMpgPartName



Edited by tremolux66
Corrected a typo that crept into the code

When the going gets tough, the tough start coding.

Share this post

Link to post
Share on other sites

Hi @tremolux66

Googled this question gave some pretty good results.

It seems like Windows Vista and above user interfaces generated by a service can't be seen.

There's some discussion in the links below, that may help you:

Show a message box from a Windows Service

Do you still use the MessageBox API in your Windows Service?

How to show message box in windows service

Edited by genius257
spell checking

Share this post

Link to post
Share on other sites

@genius257 Thanks for the pointers. I had assumed it was an AutoIt coding issue so I went straight to the forum, but clearly it's not. Perhaps the MsgBox() Help page could be updated to clarify this.

Since our system only has one interactive user logged-in at a time, I can probably just modify the service & rewrite the alerter script so they use a named pipe.

Thanks again.

Edited by tremolux66
Fixed a typo.

When the going gets tough, the tough start coding.

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • SkysLastChance
      By SkysLastChance
      I am having a hard time understanding why this is not working. I was hoping some one could help explain it to me. 
      $tags = $oIE.document.GetElementsByTagName("input") For $tag in $tags $class_value = $tag.GetAttribute("class") If string($class_value) = "fTs-p3298-l0 wplEditControl" Then $target = $tag ExitLoop EndIF Next MsgBox(0,"",$target) If $target = "fTs-p3298-l0 wplEditControl" THEN MsgBox(0,"","itworked") I have tried 
       MsgBox(0,"",$target.Attribute)  MsgBox(0,"",$target.Value)  MsgBox(0,"",$target.InnerText) I would expect to see this in the msgbox
      fTs-p3298-l0 wplEditControl  
    • funkey
      By funkey
      it's quite often, that someone asks how to change the texts of the MsgBox buttons or the InputBox buttons or how to change the position of ta MsgBox. Since years I use CBT hooks for that, but now I made a small UDF out of it for the ease of use. Of course you can build your own GUI or use already existing UDFs to do the same, but I like this way and you can hack (hook) the inbuild InputBox.
      #include-once #include <WinAPI.au3> Global Const $tagCBT_CREATEWND = "ptr lpcs;HWND tagCBT_CREATEWND" Global Const $tagCREATESTRUCT = "ptr lpCreateParams;handle hInstance;HWND hMenu;HWND hwndParent;int cy;int cx;int y;int x;LONG style;ptr lpszName;ptr lpszClass;DWORD dwExStyle" Global $g__hProcDlgBox = DllCallbackRegister("__DlgBox_CbtHookProc", "int", "int;int;int") Global $g__TIdDlgBox = _WinAPI_GetCurrentThreadId() Global $g__hHookDlgBox = _WinAPI_SetWindowsHookEx($WH_CBT, DllCallbackGetPtr($g__hProcDlgBox), 0, $g__TIdDlgBox) Global Const $g__MaxDlgBtns = 5 ; maximum of 5 buttons to rename text Global Const $g__MaxDlgItemId = 11 ; maximun ID of buttons to search is 11 as this is the maximun used in Messagebox Global $g__DlgBoxPosX, $g__DlgBoxPosY, $g__DlgBoxWidth, $g__DlgBoxHeight Global $g__aDlgBoxBtnText[$g__MaxDlgBtns] Global $g__DlgBtnCount = 0 _DlgBox_SetDefaults() OnAutoItExitRegister("__DlgBox_UnregisterHook") Func _DlgBox_SetButtonNames($TxtBtn1 = Default, $TxtBtn2 = Default, $TxtBtn3 = Default, $TxtBtn4 = Default, $TxtBtn5 = Default) $g__aDlgBoxBtnText[0] = $TxtBtn1 $g__aDlgBoxBtnText[1] = $TxtBtn2 $g__aDlgBoxBtnText[2] = $TxtBtn3 $g__aDlgBoxBtnText[3] = $TxtBtn4 $g__aDlgBoxBtnText[4] = $TxtBtn5 $g__DlgBtnCount = @NumParams EndFunc ;==>_DlgBox_SetButtonNames Func _DlgBox_SetPosition($x = Default, $y = Default) ;only for MsgBox, not working and not needed for InputBox $g__DlgBoxPosX = $x $g__DlgBoxPosY = $y EndFunc ;==>_DlgBox_SetPosition Func _DlgBox_SetSize($w = Default, $h = Default) $g__DlgBoxWidth = $w $g__DlgBoxHeight = $h EndFunc ;==>_DlgBox_SetSize Func _DlgBox_SetDefaults() $g__DlgBoxPosX = Default $g__DlgBoxPosY = Default $g__DlgBoxWidth = Default $g__DlgBoxHeight = Default For $i = 0 To UBound($g__aDlgBoxBtnText) - 1 $g__aDlgBoxBtnText[$i] = Default Next EndFunc ;==>_DlgBox_SetDefaults Func __DlgBox_CbtHookProc($nCode, $wParam, $lParam) Local $tcw, $tcs Local $iSearch = 0 Local $ahBtn[$g__DlgBtnCount] If $nCode < 0 Then Return _WinAPI_CallNextHookEx($g__hHookDlgBox, $nCode, $wParam, $lParam) EndIf Switch $nCode Case 3 ;5=HCBT_CREATEWND If _WinAPI_GetClassName(HWnd($wParam)) = "#32770" Then ;Dialoig window class $tcw = DllStructCreate($tagCBT_CREATEWND, $lParam) $tcs = DllStructCreate($tagCREATESTRUCT, DllStructGetData($tcw, "lpcs")) If $g__DlgBoxPosX <> Default Then DllStructSetData($tcs, "x", $g__DlgBoxPosX) If $g__DlgBoxPosY <> Default Then DllStructSetData($tcs, "y", $g__DlgBoxPosY) If $g__DlgBoxWidth <> Default Then DllStructSetData($tcs, "cx", $g__DlgBoxWidth) If $g__DlgBoxHeight <> Default Then DllStructSetData($tcs, "cy", $g__DlgBoxHeight) EndIf Case 5 ;5=HCBT_ACTIVATE For $i = 1 To $g__MaxDlgItemId If IsHWnd(_WinAPI_GetDlgItem($wParam, $i)) Then If $g__aDlgBoxBtnText[$iSearch] <> Default Then _WinAPI_SetDlgItemText($wParam, $i, $g__aDlgBoxBtnText[$iSearch]) $iSearch += 1 If $iSearch >= UBound($ahBtn) Then ExitLoop EndIf Next EndSwitch Return _WinAPI_CallNextHookEx($g__hHookDlgBox, $nCode, $wParam, $lParam) EndFunc ;==>__DlgBox_CbtHookProc Func __DlgBox_UnregisterHook() _WinAPI_UnhookWindowsHookEx($g__hHookDlgBox) DllCallbackFree($g__hProcDlgBox) EndFunc ;==>__DlgBox_UnregisterHook Func _WinAPI_SetDlgItemText($hDlg, $nIDDlgItem, $lpString) Local $aRet = DllCall('user32.dll', "int", "SetDlgItemText", _ "hwnd", $hDlg, _ "int", $nIDDlgItem, _ "str", $lpString) Return $aRet[0] EndFunc ;==>_WinAPI_SetDlgItemText  
      Simple example to see how to use it
      #include "HookDlgBox.au3" _DlgBox_SetButtonNames("1", "two", "3") MsgBox(4, "Test 1", "Custom button texts") _DlgBox_SetPosition(20, 20) MsgBox(66, "Test 2", "Custom position and button texts") _DlgBox_SetButtonNames("Submit", "Don't submit", "Don't know") InputBox("Test 3", "Where were you born?", "Planet Earth") _DlgBox_SetSize(800, 800) InputBox("Test 4", "Where were you born?", "Planet Earth") _DlgBox_SetSize(Default, 800) MsgBox(66, "Test 5", "Strange but working") _DlgBox_SetButtonNames(Default, "Wait", "What?") _DlgBox_SetSize(Default, Default) _DlgBox_SetPosition(500, 500) MsgBox(66, "Test 6", "So far so good!") _DlgBox_SetDefaults() MsgBox(6, "Test 7", "Default position and button texts") Hope you like it.
      Best regards
      HookDlgBox Example.au3
    • Shirdish_chakravarthi
      By Shirdish_chakravarthi
      Hello Guys i am working on automating a flashing tool..When flashing is started if there is any error in connection it pops's up a error window...(as shown below)

       whenever this popup appears i need a msgbox to appear saying "error occured" how can i do this?

    • Nareshm
      By Nareshm
      I have autoit script like this :
      winActivate ("BillReceipt") ControlClick ( "BillReceipt", "", "[NAME:winviewer]", "right") Send ( "{ENTER}") WinWait ("Print") ControlClick ("Print", "", "[CLASS:Button; INSTANCE:13]") Winwait ("Save As") WinActivate ("Save As") Send ("{TAB 5} {Backspace} ^v {Enter}") I need Saved successfully msgbox with file name as i saved like Filename.extension (Example = test.pdf is saved successfull)

      Please Help
    • ChipConnJohn
      By ChipConnJohn
      Hello all,
      I've scripted AutoIT to scrape a web forum I'm part of using the IE.au3 #include.  The script works great if I'm logged in, but doesn't work as a service.  Anyone have any ideas on how I might achieve that or will I have to have the computer logged in at all times?