外国人写的一个C#拨号

Sample Image - webdialup.gif

Introduction

I recently changed my home network, basically I added a server to connect the network to the Internet. Unfortunately where I live we can't get broadband Internet, so the Internet connection server needs to dial into our ISP. I needed a simple way to connect, disconnect and see how long the connection has been up. Normally I would use terminal services to establish and view the connection, but since my wife also uses the Internet I needed another simpler way, one that even my wife can use. I built this web application, that displays the current connection's statistics or shows the phonebook entries so that the user can connect.

Using the code

I've wrapped up some of the RAS API's so I could use them with P/Invoke. They are:

  • RasEnumConnections
  • RasGetConnectionStatistics
  • RasHangUp
  • RasEnumEntries
  • InternetDial

I also had to create some structures that these API's could use:

  • RASCONN
  • RasEntryName
  • RasStats

I created a simple class called RASDisplay which has the following methods and properties:

Methods

  • int Connect(string Connection)
  • void Disconnect()

Properties

  • bool IsConnected
  • string ConnectionName
  • double BytesReceived
  • double BytesTransmitted
  • string[] Connections
  • string Duration

The RASDisplay class takes care of all the complexity of using the RAS API. If you not familiar with using the RAS API, you have to pass in the structure sizes, so the API knows which version you are working with. The constructor for this class uses the following code to set the above properties:

Collapse Copy Code
private string m_duration;
private string m_ConnectionName;
private string[] m_ConnectionNames;
private double m_TX;
private double m_RX;
private bool m_connected;
private IntPtr m_ConnectedRasHandle;

public RASDisplay()
{
    m_connected = true;

    RAS lpras = new RAS();
    RASCONN lprasConn = new RASCONN();            

    lprasConn.dwSize = Marshal.SizeOf(typeof(RASCONN));
    lprasConn.hrasconn = IntPtr.Zero;

    int lpcb = 0;
    int lpcConnections = 0;
    int nRet = 0;
    lpcb = Marshal.SizeOf(typeof(RASCONN));


    nRet = RAS.RasEnumConnections(ref lprasConn, ref lpcb, 
                                         ref lpcConnections);


    if(nRet != 0)
    {
        m_connected = false;
        return;
    }

    if(lpcConnections > 0)
    {
        RasStats stats = new RasStats();

        m_ConnectedRasHandle = lprasConn.hrasconn;
        RAS.RasGetConnectionStatistics(lprasConn.hrasconn, stats);

        m_ConnectionName = lprasConn.szEntryName;

        //Work out our duration 
        int Hours = 0;
        int Minutes = 0;
        int Seconds = 0;

        //The RasStats duration is in milliseconds
        Hours = ((stats.dwConnectDuration /1000) /3600);
        Minutes = ((stats.dwConnectDuration /1000) /60) - 
                                              (Hours * 60);
        Seconds = ((stats.dwConnectDuration /1000)) - 
                           (Minutes * 60) - (Hours * 3600);

        m_duration = Hours  +  " hours "  + Minutes + 
                " minutes " + Seconds + " secs";

        //set the bytes transferred and received
        m_TX = stats.dwBytesXmited;
        m_RX = stats.dwBytesRcved;

    }
    else
    {
        //we aren't connected
        m_connected = false;
    }

    //Find the names of the connections we could dial
    int lpNames = 1;
    int entryNameSize=Marshal.SizeOf(typeof(RasEntryName));
    int lpSize=lpNames*entryNameSize;
    RasEntryName[] names=new RasEntryName[lpNames];
    for(int i=0;i<names.Length;i++)
    {
        names[i].dwSize=entryNameSize;
    }

    uint retval = RAS.RasEnumEntries(null,null,names,
                                 ref lpSize,out lpNames);

    m_ConnectionNames = new string[lpNames];

    if(lpNames>0)
    {                
        for(int i=0;i<lpNames;i++)
        {
            m_ConnectionNames[i] = names[i].szEntryName;
        }
    }
}

The code to connect to the Internet uses the InternetDial WinInet API:

Collapse Copy Code
public int Connect(string sConnection)
{
    int intConnection = 0;
    uint INTERNET_AUTO_DIAL_UNATTENDED = 2;
    int retVal = RAS.InternetDial(IntPtr.Zero, sConnection,
            INTERNET_AUTO_DIAL_UNATTENDED,ref intConnection,0);
    return retVal;
}

The code to disconnect is very simple as well:

Collapse Copy Code
public void Disconnect()
{
    RAS.RasHangUp(m_ConnectedRasHandle);
}

The web application that uses the RASDisplay class looks like:

Collapse Copy Code
protected System.Web.UI.WebControls.Label lblName;
protected System.Web.UI.WebControls.Label lblDuration;
protected System.Web.UI.WebControls.Label lblTransmitted;
protected System.Web.UI.WebControls.DataGrid dgAllConnections;
protected System.Web.UI.HtmlControls.HtmlTable tblCurrentConnection;
protected System.Web.UI.WebControls.Button btnDisconnect;
protected System.Web.UI.WebControls.Label lblRecieved;

private void Page_Load(object sender, System.EventArgs e)
{
    if(!IsPostBack)
    {
        BindData();
    }
}

private void BindData()
{
    try
    {
        RASDisplay display = new RASDisplay();

        lblName.Text = display.ConnectionName;
        lblDuration.Text = display.Duration;
        lblRecieved.Text = display.BytesReceived.ToString();
        lblTransmitted.Text = display.BytesTransmitted.ToString();

        if(!display.IsConnected)
        {
            //show the table with stats
            tblCurrentConnection.Visible = false;
        }
        else
        {
            //show the tables with available connections
            dgAllConnections.Visible = false;
        }

        //bind the data
        dgAllConnections.DataSource = display.Connections;
        dgAllConnections.DataBind();

    }
    catch(Exception e){
        Response.Write(e.Message);
    }
}

protected void btnConnect_Click(object sender, EventArgs e)
{
    RASDisplay rasDisplay = new RASDisplay();

    //need to find the text in the first column of the datagrid
    Button btnSender = (Button) sender;
    DataGridItem ob =  (DataGridItem) btnSender.Parent.Parent;

    int ErrorVal = rasDisplay.Connect(ob.Cells[1].Text);

    if(ErrorVal != 0)
    {
        Response.Write(ErrorVal);
    }
    else
    {
        //redirect to the same page, so the display 
        //is refreshed with stats
        Response.Redirect("Default.aspx");
    }
}

protected void btnDisConnect_Click(object sender, EventArgs e)
{
    RASDisplay rasDisplay = new RASDisplay();
    rasDisplay.Disconnect();
    //redirect to the same page, so the display is 
    //refreshed with available connections
    Response.Redirect("Default.aspx");
}

The web application has a DataGrid that displays all the connections on the machine, this DataGrid only gets displayed if the computer isn't connected to the Internet. Otherwise a table with the connection's statistics gets displayed. The web page has a meta refresh tag, to keep the statistics up to date.

Know issues

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值