Link to home
Start Free TrialLog in
Avatar of SaucyJim
SaucyJim

asked on

Automatically Respond to Network Password Prompt in Outlook 2002 - MAX Points Awarded!

Here's my situation:

I am running a syncronization program on my PC that communicates with a SYNC server. That SYNC server requires Outlook 2002 to be automaticaly checking my email before updating the SYNC server. Once this is complete, my Pocket PC contacts the SYNC server, retrieving my email, contacts, etc...

Here is my problem:

My MAIL server will INTERMITTENTLY either time-out (or some other problem), resulting in a prompt on my PC for a network password for my email. The password IS saved and works MOST of the time. However, occasionally, it fails and the prompt appears.

If I am out of town or away for an extended period of time in a given day, that prompt prevents any further attempts by Outlook to check my MAIL server. This prevents me from receiving critical communications on my Pocket PC until I get home and respond to the password prompt.

Solution Request:

I am guessing that my best solution is to have some sort of script monitoring my Outlook application for the appearance of this password prompt and then automatically respond when it appears. Does this seem like a reasonable solution and is it possible? I have NO experience with Visual Basic, but am a Unix C-Shell guru, so I should hopefully be able to implement any solutions you might present.

I will award max points for this resolution. If you have another idea, I am open to that as well.

Best regards,

SaucyJim
Avatar of vinnyd79
vinnyd79

Add a bas module to your project and paste this code into it:

Option Explicit
Public Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal _
        lpWindowName As String) As Long
Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, _
   ByVal hwnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Public Declare Function SendMessageSTRING Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
Public Declare Function SendMessage Lib "user32" _
   Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _
   ByVal wParam As Long, ByVal lParam As Long) As Long _

Const WM_SETTEXT = &HC
Const WM_SHOWWINDOW = &H18
Const BM_CLICK = &HF5
Public tmrID As Long

Public Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTimer As Long)
Dim hwnd2 As Long, lObjhWnd As Long, MyPass As String, x As Long, i As Long
' EDIT NEXT LINE TO SHOW CAPTION ON PASSWORD DIALOG WINDOW
hwnd2 = FindWindow(vbNullString, "Internet E-mail - mail.optonline.net")
If hwnd2 <> 0 Then
    KillTimer &H0, tmrID
    lObjhWnd = FindWindowEx(hwnd2, 0, "Button", "OK")
    x = FindWindowEx(hwnd2, 0, "Edit", vbNullString)
    x = FindWindowEx(hwnd2, x, "Edit", vbNullString)
   ' ENTER PASSWORD TO SEND TO DIALOG BOX
    MyPass = "MyPassword"
    SendMessageSTRING x, WM_SETTEXT, 256, MyPass
    i = SendMessage(hwnd2, WM_SHOWWINDOW, 0, 0)
    ' CLICK THE OK BUTTON
    i = SendMessage(lObjhWnd, BM_CLICK, 0, 0)
    tmrID = SetTimer(&H0, &H0, 100, AddressOf TimerProc)
    DoEvents
End If
End Sub


Make sure you edit the dialog caption and password in the above example.

Then add this code to your form:

Option Explicit
Private Sub Form_Load()
tmrID = SetTimer(&H0, &H0, 100, AddressOf TimerProc)
End Sub

Private Sub Form_Unload(Cancel As Integer)
KillTimer &H0, tmrID
End Sub



Keep in mind that you when using SetTimer and KillTimer API's you MUST always Kill the Timer before your app exits or VB will shut down on you.


Avatar of SaucyJim

ASKER

I do not understand enough about Visual Basic to simply do what you have indicated here. In fact, I thought Visual Basic (included in Outlook 2002) had a compiler included, but I can't even find a way to start a new project. If this is too much for you to help me with, I'll award points and try another question in another area. Sorry.

SaucyJim
Actually, I may be able to handle this. Are your comments in green once pasted into the module? Once compiled, will my password be text searchable on my PC? Also... if the dialog box is appearing with the password already included, wuld that section be necessary. All I really need to do is click okay.

SaucyJim
You can create macro's and write code to run in VBA but I don't think you can compile an exe with it. It shouldn't matter if you don't need to put in the password. Try this for the TimerProc:

Public Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTimer As Long)
Dim hwnd2 As Long, lObjhWnd As Long, MyPass As String, x As Long, i As Long
' EDIT NEXT LINE TO SHOW CAPTION ON PASSWORD DIALOG WINDOW
hwnd2 = FindWindow(vbNullString, "Internet E-mail - mail.optonline.net")
If hwnd2 <> 0 Then
    KillTimer &H0, tmrID
    lObjhWnd = FindWindowEx(hwnd2, 0, "Button", "OK")
    i = SendMessage(hwnd2, WM_SHOWWINDOW, 0, 0)
    ' CLICK THE OK BUTTON
    i = SendMessage(lObjhWnd, BM_CLICK, 0, 0)
    tmrID = SetTimer(&H0, &H0, 100, AddressOf TimerProc)
    DoEvents
End If
End Sub
You said:

Keep in mind that you when using SetTimer and KillTimer API's you MUST always Kill the Timer before your app exits or VB will shut down on you.

My questions:

What does this mean and why are we discussing timers?

What does API stand for?

How do you kill the timer?

Can your comments remain in the code or do I need to remove them. They appear as green, so I am assuming it knows they're comments.

When answering, please remember... I know almost nothing about VB. :(

I am pasting the actual contents of my module (called Module1) and my form (called UserForm1) below. I started with nothing, inserted your contents between the starting "Private Sub  UserForm_Click()" and ending "End Sub" in UserForm1 and in between the starting "Sub Project1 ()" and ending "End Sub" in Module1. Please let me know if this is the right idea.

START MODULE1 HERE

Sub Project1()

    Option Explicit
    Public Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
    Public Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
    Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal _
        lpWindowName As String) As Long
    Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, _
    ByVal hwnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
    Public Declare Function SendMessageSTRING Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
    Public Declare Function SendMessage Lib "user32" _
    Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _
    ByVal wParam As Long, ByVal lParam As Long) As Long _

    Const WM_SETTEXT = &HC
    Const WM_SHOWWINDOW = &H18
    Const BM_CLICK = &HF5
    Public tmrID As Long

    Public Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal dwTimer As Long)
   
        Dim hwnd2 As Long, lObjhWnd As Long, MyPass As String, x As Long, i As Long
        ' EDIT NEXT LINE TO SHOW CAPTION ON PASSWORD DIALOG WINDOW
        hwnd2 = FindWindow(vbNullString, "Internet E-mail - mail.optonline.net")

        If hwnd2 <> 0 Then

            KillTimer &H0, tmrID
            lObjhWnd = FindWindowEx(hwnd2, 0, "Button", "OK")
            x = FindWindowEx(hwnd2, 0, "Edit", vbNullString)
            x = FindWindowEx(hwnd2, x, "Edit", vbNullString)
           ' ENTER PASSWORD TO SEND TO DIALOG BOX
            MyPass = "MyPassword"
            SendMessageSTRING x, WM_SETTEXT, 256, MyPass
            i = SendMessage(hwnd2, WM_SHOWWINDOW, 0, 0)
            ' CLICK THE OK BUTTON
            i = SendMessage(lObjhWnd, BM_CLICK, 0, 0)
            tmrID = SetTimer(&H0, &H0, 100, AddressOf TimerProc)
            DoEvents
   
        End If

    End Sub
   
End Sub

END MODULE1 HERE

START USERFORM1 HERE

Private Sub UserForm_Click()

    Option Explicit
   
    Private Sub Form_Load()

        tmrID = SetTimer(&H0, &H0, 100, AddressOf TimerProc)

    End Sub

    Private Sub Form_Unload(Cancel As Integer)

        KillTimer &H0, tmrID

    End Sub

End Sub

END USERFORM1 HERE
I am receiving a compile error on the following line:

Public Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long

Here is the error:

    Compile Error:

    Only comments may appear after End Sub, End Function, or End Property

Any idea why that is happening?
More questions and comments:

(1) When I invoke this macro from within Outlook, I receive the following error:

    Sub or Function not defined.

(2) Assuming we eventually get this working, how do I have it running all the time waiting for the password prompt to appear. Does it replay every certain number of minutes?

I know this is a lot. I understand if you can't show me all this stuff. If you like, I can create separate questions so you receive more points for practically training me from scratch on VB.

SaucyJim
Keep in mind that you when using SetTimer and KillTimer API's you MUST always Kill the Timer before your app exits or VB will shut down on you.

What does this mean and why are we discussing timers?
The SetTimer API will start a timer that fires at a specific interval. If you don't kill the timer it will continue to run after you close your app and cause an error.
The above code is constantly looking for the password window.

The following line is starting a timer every 100ms and checking for the window. If you want to check for the password window once a minute change the value to 60000

tmrID = SetTimer(&H0, &H0, 100, AddressOf TimerProc)

What does API stand for?
Application Programmers Interface

How do you kill the timer?
With this line:  
KillTimer &H0, tmrID

Also the tmrID variable is declared as public so it can be used to called the KillTimer API from anywhere in your app.


In the above module the declarations must be in the top form area. You have them
inside a Sub routine called Project1().

Remove the "Sub Project1()" line and also remove an end sub from the bottom of the module.
I don't have office installed on the pc im on now but you could try this on your UserForm:

Private Sub UserForm_Initialize()
        tmrID = SetTimer(&H0, &H0, 100, AddressOf TimerProc)
End Sub

Private Sub UserForm_Terminate()
        KillTimer &H0, tmrID
End Sub




Also, You could leave the comments in.
Im sure there is a better way to do this from Outlook but this example works for me in Excel VBA. I added a UserForm with 2 buttons and a module.Just adjust the window caption and timer interval in the module and also the timer interval on the user form.

' User Form Code
Private Sub CommandButton1_Click()
' start timer every 3 sec
tmrID = SetTimer(&H0, &H0, 3000, AddressOf TimerProc)
End Sub

Private Sub CommandButton2_Click()
' kill timer
KillTimer &H0, tmrID
End Sub





' module code

Option Explicit
Public Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent _
                As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent _
                As Long) As Long
Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
            (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 _
        As Long, ByVal hwnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As _
        Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Const WM_SHOWWINDOW = &H18
Const BM_CLICK = &HF5
Public tmrID As Long

Public Sub TimerProc(ByVal hwnd As Long, ByVal uMsg As Long, _
                  ByVal idEvent As Long, ByVal dwTimer As Long)
Dim pwWin As Long, lObjhWnd As Long, x As Long

pwWin = FindWindow(vbNullString, "Internet E-mail - myMail Account")  
If pwWin <> 0 Then
    KillTimer &H0, tmrID
    lObjhWnd = FindWindowEx(pwWin, 0, "Button", "OK")
    x = SendMessage(lObjhWnd, BM_CLICK, 0, 0)
    tmrID = SetTimer(&H0, &H0, 3000 AddressOf TimerProc)  ' 3 sec
    DoEvents
End If
End Sub
I wanted to post a brief comment here. I have been too busy to dig into your solutions and suggestions, but I hope to get back to this project soon. Please keep this thread open for the time being. I will award points once my problem has been solved.

Best regards... SaucyJim
Okay... call me retarded. I have no idea what I am doing here. Can anyone explain how to set this stuff up in layman's terms. I simply do not understand enough about Visual Basic to simply create this stuff. I am look for step-by-step instructions. I mean details like:

(1) Create a new macro by clicking Tools > Macro > Visual Basic Editor
(2) Right click on blah blah and create a UserForm named so and so

I really cannot seem to get it otherwise. I want a SIMPLE macro that looks for the password prompt window and simply clicks OK assuming the password field is populated. Is it really this complicated? Remember - I know nothing about how Visual Basic operates!

Sorry... but this is too frustrating.

SaucyJim
ASKER CERTIFIED SOLUTION
Avatar of vinnyd79
vinnyd79

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Okay... EXCELLENT... now I am making progress. I have replaced the string with "Enter Network Password" which is what the very top blue sectio of the dialog box states. I hope that is correct.

The next question is that I stopped Outlook but was not afforded the opportunity to allow macros when I restarted. Any recommendations?

SaucyJim
One more question: Can I use the task manager to see this timer start and end?

SaucyJim
You probably have your security settings set to high. If you goto Tools>Macro>Security and set the setting to Medium it will ask if you want to enable Macro's when you first start Outlook. No,you will not see the timer in Task Manager. The timer will start when outlook starts and stop when it quits.
Nope... tried both medium and low setting before I asked. I am not being prompted. Help!

;)

SaucyJim
Okay... for those who do not know... I figured this out and my script now works properly. Here was the problem...

I would close Outlook and restart and NOT get prompted to enable macro's, right? My security setting were set to medium, so I should have been prompted. The problem was that Outlook was not really closed. I have it set to still access email and present task and appointment reminders when closed, so it is STILL RUNNING when closed. So... I opened the task manager and killed the Outlook.EXE process ans restarted. Lo, and behold, I was prompted for the macros, responded, and my automation is now running.

Thanks, Vinny... points are now being awarded. You rock!

Best regards,

SaucyJim
Hi Jim, Did you ever get this working correctly?

Vinny
I did... and thought I had awarded points accordingly. I just did that again and confirmed you got your points. Thanks so much!

SaucyJim