2011年8月25日 星期四

網絡編程系列(一): 編寫ASP.Net(VB)存取網絡內的電腦名稱

安安!! 這陣子要講的是如何以asp.net編寫網頁版的網絡應用程式。你會問為什麼要學用Asp.net來寫網頁版的網絡應用程式,而不是用VB.NET或C#來寫傳統的桌面應用程式呢? 我覺得有以下很多的好處:
  • 首先是網頁版的網絡應用程式不一定需要在用戶電腦上安裝,(註: 因應功能而定)。
  • 你可以在其他非windows的系統上使用網頁版的網絡應用程式,檢視和管理網絡資源。
  • 可以把已寫好的網絡應用程式碼複製到VB.NET,並修改成桌面應用程式使用。
而首次所寫的範例程式是編寫ASP.Net(VB)存取網絡的電腦名稱,所寫出來的顯示效果就如用網絡芳鄰檢視網內所有電腦的名稱,而我會以LIST元件顯示,顯示結果如下圖:

這次範例只需修改的Default.aspx,首先新增一個專案名為NetServerEnum,並選擇 ASP.NET web application,然後出現了Default.aspx可以作修改。



以下是相關修改的程式碼:
Default.aspx :

   1:  <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="NetServerEnum._Default" %>
   2:  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   3:  <html xmlns="http://www.w3.org/1999/xhtml">
   4:  <head id="Head1" runat="server">
   5:      <title></title>
   6:  </head>
   7:  <body>
   8:   
   9:      <form id="form1" runat="server">
  10:      Network Devices :<br />
  11:      <br />
  12:      <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
  13:      <br />
  14:      <asp:ListBox ID="ListBox1" runat="server" Height="193px" Width="249px">
  15:      </asp:ListBox>
  16:      </form>
  17:   
  18:  </body>
  19:  </html>


Default.aspx.vb

   1:  Default.aspx.vb
   2:   
   3:  Imports System.Runtime.InteropServices
   4:   
   5:  Partial Public Class _Default
   6:      Inherits System.Web.UI.Page
   7:   
   8:  #Region "API Declares"
   9:      Private Const SV_TYPE_WORKSTATION As Integer = &H1
  10:      Private Const SV_TYPE_SERVER As Integer = &H2 ' All Servers 
  11:      Private Const SV_TYPE_SQLSERVER As Integer = &H4 ' SQL Server 
  12:      Private Const SV_TYPE_DOMAIN_CTRL As Integer = &H8
  13:      Private Const SV_TYPE_DOMAIN_BAKCTRL As Integer = &H10
  14:      Private Const SV_TYPE_TIME_SOURCE As Integer = &H20
  15:      Private Const SV_TYPE_SERVER_UNIX As Integer = SV_TYPE_XENIX_SERVER
  16:      Private Const SV_TYPE_NT As Integer = &H1000
  17:      Private Const SV_TYPE_WFW As Integer = &H2000
  18:      Private Const SV_TYPE_POTENTIAL_BROWSER As Integer = &H10000
  19:      Private Const SV_TYPE_BACKUP_BROWSER As Integer = &H20000
  20:      Private Const SV_TYPE_MASTER_BROWSER As Integer = &H40000
  21:      Private Const SV_TYPE_DOMAIN_MASTER As Integer = &H80000
  22:      Private Const SV_TYPE_SERVER_OSF As Integer = &H100000
  23:      Private Const SV_TYPE_SERVER_VMS As Integer = &H200000
  24:      Private Const SV_TYPE_WINDOWS As Integer = &H400000 '/* Windows95 and above */ 
  25:      Private Const SV_TYPE_DFS As Integer = &H800000 '/* Root of a DFS tree */ 
  26:      Private Const SV_TYPE_CLUSTER_NT As Integer = &H1000000 '/* NT Cluster */ 
  27:      Private Const SV_TYPE_DCE As Integer = &H10000000    'RESOURCE ENUMERATION. 
  28:      Private Const SV_TYPE_SERVER_MFPN As Integer = &H4000
  29:      Private Const SV_TYPE_SERVER_NT As Integer = &H8000
  30:      Private Const SV_TYPE_AFP As Integer = &H40
  31:      Private Const SV_TYPE_NOVELL As Integer = &H80
  32:      Private Const SV_TYPE_DOMAIN_MEMBER As Integer = &H100
  33:      Private Const SV_TYPE_PRINTQ_SERVER As Integer = &H200
  34:      Private Const SV_TYPE_DIALIN_SERVER As Integer = &H400
  35:      Private Const SV_TYPE_XENIX_SERVER As Integer = &H800
  36:      Private Const SV_TYPE_ALL As Integer = &HFFFFFFFF
  37:      Private Const NERR_SUCCESS As Integer = 0&
  38:      Private Const ERROR_ACCESS_DENIED As Integer = 5&
  39:   
  40:      Structure Server_info_101
  41:          Public Platform_ID As Integer
  42:          Public Name As String
  43:          Public Version_Major As Integer        Public Version_Minor As Integer
  44:          Public Type As Integer
  45:          Public Comment As String
  46:      End Structure
  47:   
  48:      Declare Function NetApiBufferFree Lib "Netapi32.dll" _
  49:          (ByVal lpBuffer As Integer) As Integer
  50:   
  51:      Private machine As Server_info_101
  52:      Private getResult As String
  53:   
  54:      Declare Unicode Function NetServerEnum Lib "Netapi32.dll" _
  55:         (ByVal Servername As Integer, ByVal level As Integer, _
  56:         ByRef buffer As Integer, ByVal PrefMaxLen As Integer, _
  57:         ByRef EntriesRead As Integer, ByRef TotalEntries As Integer, _
  58:         ByVal ServerType As Integer, ByVal DomainName As String, _
  59:         ByRef ResumeHandle As Integer) As Integer
  60:   
  61:      Declare Unicode Function NetGetJoinInformation Lib "Netapi32.dll" ( _
  62:          ByVal lpServer As Integer, _
  63:          ByRef lpNameBuffer As Integer, _
  64:          ByRef BufferType As Integer) As Integer
  65:   
  66:  #End Region
  67:   
  68:  #Region "Get network device"
  69:   
  70:      Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load, Me.Load
  71:   
  72:          Dim model As New ArrayList
  73:          Dim networkName As String = GetJoinState()
  74:   
  75:          If networkName <> "" Then
  76:              model = GetServerList(networkName)
  77:          End If
  78:   
  79:          If model.Count > 0 Then
  80:              For Each i In model
  81:                  ListBox1.Items.Add(i.ToString)
  82:              Next
  83:          End If
  84:   
  85:      End Sub
  86:   
  87:      Private Function GetServerList(ByVal dnName As String) As ArrayList
  88:   
  89:          Dim i, Result, EntriesRead, TotalEntries, ResumeHandle As Integer
  90:          Dim MaxLenPref As Integer = -1
  91:          Dim level As Integer = 101
  92:          Dim BufPtr As Integer
  93:   
  94:          Result = NetServerEnum(0, level, BufPtr, MaxLenPref, EntriesRead, TotalEntries, _SV_TYPE_ALL, dnName, ResumeHandle)
  95:   
  96:          Dim PCList As New ArrayList
  97:   
  98:          If Result = 0 Then
  99:              For i = 0 To EntriesRead - 1
 100:                  Dim ptr As IntPtr = New IntPtr(BufPtr)
 101:                  machine = CType(Marshal.PtrToStructure(ptr, GetType(Server_info_101)),  _Server_info_101)
 102:                  BufPtr = BufPtr + Len(machine)
 103:                  PCList.Add(machine.Name)
 104:              Next
 105:          End If
 106:   
 107:          NetApiBufferFree(BufPtr)
 108:          Return PCList
 109:   
 110:      End Function
 111:   
 112:      Private Function GetJoinState() As String        
 113:   
 114:          Dim bufptr, dwBufferType, returnJoinState As Integer        
 115:          Dim Networkmode As String = ""
 116:          Dim modename As String = ""
 117:   
 118:          returnJoinState = NetGetJoinInformation(0, _
 119:                                   bufptr, _
 120:                                   dwBufferType)
 121:   
 122:          If returnJoinState = NERR_SUCCESS Then
 123:   
 124:              Select Case dwBufferType
 125:                  Case 0 : Networkmode = "未知"
 126:                  Case 1 : Networkmode = "單一"
 127:                  Case 2 : Networkmode = "工作群組"
 128:                  Case 3 : Networkmode = "網域"                
 129:                  Case Else : Networkmode = "網域模式超出正常類別"
 130:              End Select
 131:   
 132:              Dim ptr As New IntPtr(bufptr)
 133:              modename = Marshal.PtrToStringAuto(ptr)
 134:              If modename <> "" Or Networkmode <> "" Then
 135:                  Label1.Text = Networkmode + " : " + modename
 136:              End If
 137:   
 138:          End If
 139:   
 140:          NetApiBufferFree(bufptr)
 141:          Return modename
 142:   
 143:      End Function
 144:   
 145:  #End Region
 146:   
 147:  End Class


而以上的範例中,會使用到幾個 Win32 API 函式,它們分別是NetGetJoinInformation,NetServerEnum和NetApiBufferFree。而這些Win32 API 函式都是一些 Unmanaged 程式碼(在執行階段以外執行的程式碼)。但我們的程式都是一些 Managed 程式碼(在執行階段控制之下執行的程式碼),所以為了能夠令這些 Unmanaged 程式碼與 Managed 程式碼互動,需要藉著控制封送處理(Marshaling),設定 Unmanaged 程式碼與 Managed 程式碼兩者之間的互動參數成合適的結構才可與互通

因此,我在以上的程式碼包括匯入了System.Runtime.InteropServices的命名空間,此命名空間就是負責控制封送處理 (Marshaling) 行為,定義 Unmanaged 程式碼與Managed程式碼之間的互動參數之結構或字串表示的方式。

另外,先前提及的幾個 Win32 API 函式的功能如下:
NetGetJoinInformation - 查詢目前的網域模式和網域名稱,傳回值是0表示查詢成功。
NetServerEnum - 查詢前的網域中的機器資料包括機器名稱、機器平台版本和提示等,但必須提供網域名稱才能查詢,傳回值是0表示查詢成功。
NetApiBufferFree - 清除查詢網域時的暫存資料。

本範例不太複雜,提供源碼下載參考 :
https://docs.google.com/open?id=0BxRiNrIXEFArSmdzTm5vVnhTOG1YMk1qTzF4MDNIQQ
請下載後以Mircosoft Visual Web developer Express 2008 開啟

沒有留言:

張貼留言