This project is read-only.

hangup method fails

Mar 31, 2010 at 1:23 PM

Hi Jeff

Thanks for all your effort with the dotRAS library, its a really nice product.

 

I am writing an application which uses dotRAS to make a modem dialup connection, do some work, and then close the connection.  The modem is exclusively used by this app, although there are several numbers that it dials.  So there is only ever 1 PPP connection made out via the modem, which i sequentially connect then disconnect.  I opted to use synchronous dialling in my app:

I am using dotRAS v1.1.3530 and VB in Visual Studio 2005.

My dev machine is Server 2003 but the deployment machine will be XP.

My problem is that the connection.Hangup() method is failing

 

Private Sub RunDialler()
        Try
            blnConnected = False
            If rasPhoneBook Is Nothing Then
                rasPhoneBook = New RasPhoneBook
                rasPhoneBook.Open()
            End If
            If rasDialler Is Nothing Then
                rasDialler = New DotRas.RasDialer
            End If
            rasDialler.EntryName = mstrDialupConnectionName
            rasDialler.PhoneBookPath = rasPhoneBook.Path
            handle = rasDialler.Dial(New System.Net.NetworkCredential(mstrDialUpAccountName, mstrDialupConnectionPassword))

.....(this all works fine)

Private Sub DisconnectDialler()
        If Not rasDialler Is Nothing Then
            For Each connection In rasDialler.GetActiveConnections()
                Console.WriteLine("ID: {0}", connection.EntryId.ToString())
                Console.WriteLine("Name: {0}", connection.EntryName)

                Dim blnHungUp As Boolean = False
                While Not blnHungUp
                    blnHungUp = connection.HangUp()
                End While
 
            Next

            rasDialler.Dispose()
            rasDialler = Nothing
        End If

        If Not rasPhoneBook Is Nothing Then
            rasPhoneBook.Dispose()
            rasPhoneBook = Nothing
        End If
        blnConnected = False
    End Sub

 

'-----------------------

 

I can see the connection in my systray, it basically stays connected even after the hangup method is called.

I am thinking the problem is that the GetActiveConnections method returns a read-only collection, so the rasHandle on the connection object is not the same handle as the one in the RunDialler sub, but how to code it to say something along the lines of: connection(handle).Hangup  ???

 

Any help appreciated

 

 

Mar 31, 2010 at 3:35 PM
Edited Mar 31, 2010 at 3:39 PM

There was an issue identified recently with HangUp that may cause the connection state machine to become corrupted during hangup. The 1.1 SDK allowed the application to terminate directly after the connection is closed, which Windows tells not to let that happen in their SDK. I've already attempted to fix the issue with the 1.2 SDK, the effective fix for 1.1 should be to do a Thread.Sleep(1000) to let the state machine finish cleanup before your application will be terminated. Where you put the Thread.Sleep does not matter, as long as it happens before you application terminates. You can use more than a 1 second delay if you want, however the 1.2 SDK will be doing a 1 second delay.

As for what you mentioned earlier from GetActiveConnections, the collection returned to you is a read-only collection yes... internally it's not. I just have that being returned to ensure the collection remains intact from what was returned by Windows.

Give that a shot and let me know what happens.

Edit: You will probably need to restart your machine if you haven't by the time you read this to let Windows clean up the RAS connections.

Apr 1, 2010 at 9:18 PM

Hi Jeff

Thanks for the prompt reply.

Yeah, I read that thread, hopeful that it might help, but unfortunately it hasn't, although I suspected it wasn't going to, as I have waited for much longer in debug than 1000 milliseconds, and anyway the application doesnt terminate at that point.

Here is the output of ?connection in the Immediate Window:

ConnectionOptions: 15
    Device: Name = "USB Modem", DeviceType = "MODEM"
    EntryId: {System.Guid}
    EntryName: "MyRasConnection"
    Handle: {DotRas.RasHandle}
    PhoneBookPath: "C:\Documents and Settings\All Users\Application Data\Microsoft\Network\Connections\Pbk\rasphone.pbk"
    SessionId: {DotRas.Luid}
    SubEntryId: 1

Could the problem be permissions on the shared pbk?

 

Apr 1, 2010 at 10:35 PM

I don't think it's permissions on the phone book, the GetActiveConnections method just retrieves information reported by Windows. The handles that it receives are from the RasEnumConnections API as well, so it's either Windows is reporting the wrong handle, or your application may not have the proper permission to cause the operating system to hang up a connection. If the method didn't work at all on the operating system I'm sure I'd be hearing a lot more bug reports than just you, especially since the 1.1 SDK has been out for 7 months now.

Normally with the interop methods if an unexpected value comes back from Windows it'll throw a RasException indicating the problem, which means in your situation Windows is reporting the hangup attempt is underway. That means either the handle DotRas is storing is bad, which would cause a RasException with a code of 6 (ERROR_INVALID_HANDLE) to be thrown, or something is happening under the hood in the RAS API.

Q: Are you having this problem on your Win2k3 server or the XP clients?

Apr 2, 2010 at 9:42 AM

 

>Q: Are you having this problem on your Win2k3 server or the XP clients?

On the development W2k3 server.  I will try deploying to the clients today, and let you know about that environment.

Thanks for all your input.

Apr 13, 2010 at 5:32 PM

Hi Jeff

Sorry for the delay in replying, I have been working on other urgent projects :)

I tried deploying to the xp clients and I get the message:

DotRas.RasException: An incorrect structure size was detected.
   at DotRas.ThrowHelper.ThrowRasException(Int32 errorCode)
   at DotRas.RasHelper.GetEntryProperties(RasPhoneBook phoneBook, String entryName)
   at DotRas.RasEntryCollection.Load()
   at DotRas.RasPhoneBook.Open(String phoneBookPath)
   at DotRas.RasPhoneBook.Open()
   at <my function>CheckPhoneBookForConnection(String connectionName, String connectionDDI, String connectionModem, String deviceType)

when I try to open the phone book

Now I am worried, as I think this means I have used a version of dotRas which is incompatible with xp.

Apr 13, 2010 at 5:51 PM

I know that feeling, the priorities of projects I work on seems to change daily or hourly.

Yes that error means you've used a copy of the project that is incompatible with that version of Windows XP.. What's the full version of the DLL you're referencing (including build version)? And what copy of XP are you using on your clients, XP, XP SP1, XP SP2, etc?

Apr 14, 2010 at 10:21 AM

hehe my trouble is I'm too slow for my employers, so I never seem to finish something to a satisfactory level before the next thing comes along.

Client XP machines are running on XP Professional version 2002 SP3

Dll is 1.1.3530.40303

Cheers

 

 

Apr 14, 2010 at 2:34 PM

Well there's your problem. The DLL version you're using is for Windows Vista / Windows 2008 Server or later. I have all of the build versions identified on the downloads page so I can reference them later if an issue like this arises. You might want to revisit the getting started section under documentation, particularly the section choosing your build type. It'll help you understand why it's not working, if you're interested. That might also explain why it doesn't work on your developer workstation.

Basically, to fix your problem you need to use the WINXP or WINXPSP2 build type.

Apr 14, 2010 at 3:22 PM

Thanks Jeff, that was indeed one of my problems.  I have now compiled with the WINXPSP2 dll, and it is working on the deployment machines up to the hangup method.  However, this still fails to hang up the modem which appears in Network connections window saying 'Connected' still, and i get this behaviour on the development machine and the production client machines.  I tried adding a thread.sleep immediately after the hangup, but no difference, even when sleeping for 600s.  I might be forced to wait for the connection to time out as an interim measure to get this deployed, and I will revisit all the code to see if there is some other problem.

Cheers

 

 

Apr 14, 2010 at 5:00 PM
Edited Apr 14, 2010 at 5:02 PM

Have you tried to disconnect the connection through Windows?

There is a warning on the RasDialer in the help file that if it's not properly disposed of the connection can be left in an inconsistent state. That might what is surrounding the problems you've been experiencing. Basically what you'll see is you'll call hangup, or dial, nothing will happen. If you're developing the app, dial a connection asynchronously, and click stop in the debugger before the connection finishes so the component is not disposed the handle that Windows sends to the RasDialer cannot be used to call HangUp to terminate the connection process. Since Windows cannot retrieve the handle itself (it's not an active connection at that point) the handle is lost and the connection cannot be stopped without rebooting the machine.

Edit: I see in your code above you are calling Dispose on the component, but how you're using the component could be what's causing the issues you're seeing. I can only see part of the code, so I have to assume that's what's causing the issue. I'll keep working with you on this till we can resolve the issue.

Apr 15, 2010 at 12:12 PM

Really appreciate your assistance on this, Jeff.

I am dialling synchronously at the moment.  I made this decision based on the fact that the process is a linear one: 

1 dial

2 ftp

3 disconnect

4. Start again dialling a different remote modem  while there is still work to do

After a hangup failure, I can clearly see the connection in Windows, it's not inconsistent, and can be disconnected from Windows UI, there is no issue with this, it disconnects cleanly, and no reboot required.

Clearly, adding a thread.sleep after the hangup method is completely ineffective with synchronous dialling as by then the important events you allude to have passed already.

So I am now going to try changing to asynchronous dialling again and code the pause in the way you suggest, and hopefully that will fix it.  I will let you know how this goes.

 

 

Apr 15, 2010 at 2:58 PM

Come to think of it, someone did report a bug recently with HangUp that it wasn't allowing the connection to finish cleanup of a connection. I changed the code not too long ago for 1.2, basically just adding a Thread.Sleep(1000) so Windows has the time it needs.

Apr 15, 2010 at 3:14 PM

Is 1.2 available yet?

 

Apr 15, 2010 at 5:08 PM

Not for release no, but there is always the development copy on the source code tab you can download and compile yourself. It uses .NET 4.0 MSBuild now, so you'll need 4.0 installed to compile it, but it still makes use of .NET 2.0 framework for runtime.

Apr 16, 2010 at 3:28 PM

Hi Jeff

First of all, I obtained the use of an XP development machine, with a modem and with a soundcard - this speeded things up considerably on the troubleshooting, eliminating a load of variables.

I changed to asynchronous dialling, I moved the Dialer.Dispose() to above the hangup.

One or both of these changes resolved the issue.

It was important also to declare with global scope the thread I use to run the asynchronous dialling, otherwise I was able to mimic the same failure with the Hangup method as before.

It was probably a schoolboy error to only declare the asychronous dialling function with local scope, but it highlights a potential banana skin for future users of what is essentially a really nice application.

In summary, the Dial method exibits problems with hangup, the DialAsync does not, as long as its run in a separate thread of execution, and that thread is declared with global scope.  In the end I was able to compile and deploy from either XP or Win2k3, this was irrelevant.

Far be it for a lazy lump like me to give you any advice after all the work you have put into this project, but if there was one thing I would like to have seen, it would be source code for an example application that can be used to demonstrate the dotRAS component is working correctly, as once I had put together one of these it was fairly straightforward to identify the problem. 

If you have a place where you accept donations for all the fine work you put in, please link it and I will gladly make a small contribution.

If any other user wishes to obtain an example application that connects and then disconnects when ready please reply to this thread.

 

 

Apr 16, 2010 at 4:51 PM

There were examples included with the SDK that showed how to use the dialer on a Windows form. Were you looking for something more specific? It just demonstrated basic functionality, the app was letting the form handle disposal of the component. If you have an idea of what you'd like put into one of the examples besides what's already there, I can definitely make that happen.

Thanks for the offer, but right now donations are not accepted. If you want to help me out, put up another review on the download! :)

Glad to hear you got everything working. Happy coding!

Apr 16, 2010 at 5:07 PM

Ah, ok, I skimmed the examples and didnt pay too much attention, the project names distracted me :D

Review added, thanks for your help on this

 

Apr 16, 2010 at 5:12 PM

You're more than welcome. If you have any other questions, feel free to ask. :)