Q&A-ネットワーク編 |
ネットワークに関する質問をまとめました。
ユーザ名を取得するには
Winsock コントロールで、TCPの再接続がうまく行かない
ネットワークに接続されている全てのコンピュータ名を取得するには?
サーバの日付、時刻を取得するには?
ログインしたユーザ名を取得するにはどうしたらよいのですか?
A APIの
GetUserName または WSH のオブジェクトを使用します
ユーザ名を取得する方法は、大きく分けてAPIを使用する方法と、WSH
(Windows Script Host)のオブジェクトを使用する方法があります。APIを使用する場合は、APIの宣言等が面倒ですが、環境に依存しないコードが作成できます。一方、WSH
を使用する場合、APIの宣言等は不要で手軽にコードを作成できるのですが、反面、WSH
がインストールされている環境でなければ使用できません。
■ APIを使用する場合
ユーザ名を取得する API は GetUserName
を使用すれば取得できますが、1つだけ注意することがあります。ユーザ名を取得する時バッファーのサイズを指定する
UNLEN という定数が
APIビューアに現れません。このサイズは、Visual C++ の
ヘッダーファイルを検索すると以下のように定義されてます。
#define UNLEN 256
これを、VBで宣言するには、以下の宣言を標準モジュールに入れます。
Public Const UNLEN = 256
Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" _
(ByVal lpBuffer As String, nSize As Long) As Long
これで、以下のようにユーザ名が取得できます。
Dim strBuf As String
strBuf = Space(UNLEN + 1)
GetUserName strBuf, UNLEN
'ラベルにユーザ名を表示
lblName.Caption = strBuf
また、この strBuf の内容は、C言語で使用する NULL文字(Chr$(0))で終了する文字列になっているので、ユーザ名の後ろに Chr$(0)と空白が付加されています。VBで扱い易いように、このChr$(0)以降の文字を以下のように削除します。
Dim strBuf As String
Dim intPos As Integer
strBuf = Space(UNLEN + 1)
GetUserName strBuf, UNLEN
'Chr$(0)以降の文字を削除
intPos = InStr(strBuf, Chr$(0))
If intPos > 0 Then
strBuf = Left$(strBuf, intPos - 1)
End If
'ラベルにユーザ名を表示
lblName.Caption = strBuf
■ WSHを使用する場合
WSH を使用する場合のコードは簡単です。
Dim WshNetwork As Object
Dim strUserName As Object
Set WshNetwork = CreateObject("WScript.Network")
stUserName = WshNetwork.UserName
MsgBox strUserName
Set WshNetwork = Nothing
見ても分かる通り、CreateObject で "WScript.Network"
のオブジェクトを WshNetwork に作成して、WshNetwork のUserNameプロパティを参照するだけです。
同様に WshNetwork
のプロパティには、以下のようなプロパティがあります。
ComputerName | コンピュータ名 |
UserDomain | ドメイン名 |
UserName | ユーザ名 |
(注意)WSHを使用する場合には、以下のような環境のいずれかが必要です。
・Internet Explorer の 5.0 以上
・Windows NT 4.0 のOption Pach
・Windows 98
・MSのサイトよりダウンロード
詳細に付いては以下を参照してください。
http://www.asia.microsoft.com/Japan/Developer/Scripting/
(注意)このページの内容は、Visual
Basic5.0(SP3) 、Visual Basic6.0(SP3)を対象に記述されています。他のバージョンでは、対応できないこともあるので、ご注意願います。
(注意)
ここでの情報については、あくまでも各自の責任にて、充分にテストを行ってご使用ください。内容に関する質問については、回答できる保証がありませんので、予めご了承願います
Q Winsock コントロールで、TCPの再接続がうまく行かない
Winsock
コントロールで、TCP/IPのプログラムを作成していますが、一旦
Connect メソッドで接続を行うと、Close
を行っても再接続がうまく行きません。どうしたらよいのですか?
A LocalPort
に 0 を設定します
TCP で接続する場合、ローカル
ポート番号を指定しないときは LocalPort プロパティに 0
を設定してください。これを行わないと、一旦 Connect
メソッドで接続を行うと、接続が自動的に解除するまで次の Connect
が成功しません(解除の時間はサーバの設定などでまちまちです)。
詳細に付いては、Microsoft
の以下のサイトを参考にしてください。(1999/5/26
のアドレスです、見つからない場合は、検索で文書番号の
J030442 を検索してください)
http://www.asia.microsoft.com/japan/support/kb/articles/j030/4/42.htm
(注意)このページの内容は、Visual
Basic5.0(SP3)
を対象に記述されています。他のバージョンでは、対応できないこともあるので、ご注意願います。
(注意)
ここでの情報については、あくまでも各自の責任にて、充分にテストを行ってご使用ください。内容に関する質問については、回答できる保証がありませんので、予めご了承願います。
Q ネットワークに接続されている全てのコンピュータ名を取得するには?
エクスプローラが表示するような、ネットワークに接続されているコンピュータ名をすべて取得するにはどうしたら良いでしょうか?
A WNetOpenEnum、WNetEnumResource
等のAPIで取得できます。
ネットワークに接続されているコンピュータ名を、取得するには、以下のようなAPIを使用すれば、取得できます。
Dim nr As NETRESOURCE
Dim lpnr As LPNETRESOURCE
Dim bnr(1000) As Byte
Dim strRemoteName As String
Dim hEnum As Long
Dim BufSize As Long
Dim ret As Long
strRemoteName = String$(512, 0)
' NETRESOURCE構造体を設定
nr.dwScope = RESOURCE_GLOBALNET
nr.dwType = RESOURCETYPE_ANY
nr.dwDisplayType = RESOURCEDISPLAYTYPE_DOMAIN
nr.dwUsage = RESOURCEUSAGE_CONTAINER
nr.lpRemoteName = "DomainName"
nr.lpProvider = "Microsoft Windows Network"
' 設定された NETRESOURCE でオープン
ret = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, nr, hEnum)
BufSize = 1000
' WNetEnumResource で接続されているコンピュータの情報を取得
Do While WNetEnumResource(hEnum, 1, bnr(0), BufSize) = NO_ERROR
'取得したデータを strRemoteName にコピー
MoveMemory lpnr, bnr(0), Len(lpnr)
lstrcpy strRemoteName, lpnr.lpRemoteName
'strRemoteName の後ろの Chr$(0) をカット
Debug.Print Left$(strRemoteName, InStr(strRemoteName, vbNullChar) - 1)
Loop
WNetCloseEnum hEnum
strRemoteName に取得したコンピュータ名が入ります。
ここで、重要なのは lpRemoteName
で指定されている、ドメインの名称です。ここで指定されたドメインに接続されている、全てのコンピュータ名が取得できます。この例では
DomainName
というドメインに接続されている全てのコンピュータ名を取得できます。
また、ドメイン名が不明の場合は、lpRemoteName に ""
を設定してください。strRemoteName
に接続されたドメイン名が入ります。取得されたドメイン名を、再度
lpRemoteName
にセットして、上記のコードを実行すれば、コンピュータ名が取得できます。
以下は、宣言部です。標準モジュールに入れてください。
Type NETRESOURCE
dwScope As Long
dwType As Long
dwDisplayType As Long
dwUsage As Long
lpLocalName As String
lpRemoteName As String
lpComment As String
lpProvider As String
End Type
Type LPNETRESOURCE
dwScope As Long
dwType As Long
dwDisplayType As Long
dwUsage As Long
lpLocalName As Long
lpRemoteName As Long
lpComment As Long
lpProvider As Long
End Type
'================================================
'dwScope // リソースの範囲
'列挙するリソースの範囲を指定します。次の値のいずれかを指定します
'================================================
'現在接続されているすべてのリソース(dwUsage パラメータ
'は無視されます)
Public Const RESOURCE_CONNECTED = &H1
'呼び出し側のネットワークコンテキスト内([ネットワーク
'コンピュータ]に表示される範囲)のリソース(dwUsage
'パラメータは無視されます)
Public Const
RESOURCE_CONTEXT = &H5
'ネットワーク上のすべてのリソース
Public Const
RESOURCE_GLOBALNET = &H2
'記憶されている接続(dwUsage
パラメータは無視されます)
Public Const
RESOURCE_REMEMBERED = &H3
'================================================
'dwType // リソースの種類
'列挙するリソースの種類を指定します。次の値を組み合わせて指定します
'================================================
'すべてのリソース(RESOURCETYPE_DISK または RESOURCETYPE_PRINT
'との組み合わせは不可)
Public Const
RESOURCETYPE_ANY = &H0
'すべてのディスクリソース
Public Const
RESOURCETYPE_DISK = &H1
'すべての印刷リソース
Public Const
RESOURCETYPE_PRINT = &H2
'================================================
'dwUsage // リソースの用途
'列挙するリソースの用途を指定します。次の値を組み合わせて指定します。
'================================================
'0 すべてのリソース
' すべての接続可能なリソース
Public Const
RESOURCEUSAGE_CONNECTABLE = &H1
' すべてのコンテナリソース
Public Const
RESOURCEUSAGE_CONTAINER = &H2
'================================================
'dwDisplayType // 表示タイプ
'エクスプローラなどで表示されるオブジェクトのタイプ
'================================================
'一般
Public Const
RESOURCEDISPLAYTYPE_GENERIC = &H0
'ドメイン
Public Const
RESOURCEDISPLAYTYPE_DOMAIN = &H1
'サーバ
Public Const
RESOURCEDISPLAYTYPE_SERVER = &H2
'共有
Public Const
RESOURCEDISPLAYTYPE_SHARE = &H3
'================================================
'WNetOpenEnum 戻り値
'================================================
'lpNetResource パラメータがコンテナリソースを指していません。
Public Const
ERROR_NOT_CONTAINER = 1207&
'dwScope パラメータまたは dwType
パラメータの値が無効です。
Public Const
ERROR_INVALID_PARAMETER = 87 ' dderror
'ネットワークがありません。
Public Const
ERROR_NO_NETWORK = 1222&
'ネットワーク固有のエラーが発生しました。エラーの詳細は、
'WNetGetLastError 関数で取得できます。
Public Const
ERROR_EXTENDED_ERROR = 1208&
'================================================
'WNetEnumResource 戻り値
'================================================
'列挙が成功し、要求したデータがバッファに格納されました。
'アプリケーションは、引き続きこの関数を呼び出して、列挙
'を続けることができます。
Public Const NO_ERROR = 0
'これ以上列挙するエントリはありません。このときのバッファ
'の内容は、未定義です。
Public Const
ERROR_NO_MORE_ITEMS = 259&
'================================================
'まだ列挙できるエントリが残っています。
Public Const
ERROR_MORE_DATA = 234
'hEnum ハンドルが無効です。
Public Const
ERROR_INVALID_HANDLE = 6&
'ERROR_EXTENDED_ERROR、ERROR_NO_NETWORK も返されます。
'================================================
Declare Function WNetOpenEnum Lib
"mpr.dll" Alias "WNetOpenEnumA" ( _
ByVal dwScope As
Long, _
ByVal dwType As
Long, _
ByVal dwUsage As
Long, _
LPNETRESOURCE As Any,
_
lphEnum As Long)
As Long
Declare Function WNetEnumResource Lib
"mpr.dll" Alias "WNetEnumResourceA" ( _
ByVal hEnum As
Long, _
lpcCount As Long,
_
lpBuffer As Any,
_
lpBufferSize As Long)
As Long
Declare Function WNetCloseEnum Lib
"mpr.dll" ( _
ByVal hEnum As
Long) As Long
Declare Sub MoveMemory Lib
"kernel32" Alias "RtlMoveMemory" ( _
Destination As Any,
_
Source As Any,
_
ByVal Length As
Long)
Declare Function lstrcpy Lib
"kernel32" Alias "lstrcpyA" ( _
ByVal lpString1 As
Any, _
ByVal lpString2 As
Any) As Long
(注意)このページの内容は、Visual
Basic5.0(SP3)、Visual Basic6.0(SP3)
を対象に記述されています。他のバージョンでは、対応できないこともあるので、ご注意願います。
(注意)
ここでの情報については、あくまでも各自の責任にて、充分にテストを行ってご使用ください。内容に関する質問については、回答できる保証がありませんので、予めご了承願います。
サーバの日付、時刻を取得するには、どうしたら良いでしょうか?
A net time
コマンドまたは API の NetRemoteTOD を使用します
サーバの日付、時刻を取得するには、WindowsNT または
Windows2000 では NetRemoteTOD というAPIが用意されていますが、Windows95
や Windows98 では、NetRemoteTOD が使用できないので、DOSプロンプトの
Net Time コマンドを使用してください。
■ NetRemoteTOD の場合
以下のようなAPIを使用してください。
Dim ret As Long
Dim lngPtr As Long
Dim b() As Byte
Dim todi As TIME_OF_DAY_INFO
b = "\\Server" & Chr$(0) 'サーバ名
ret = NetRemoteTOD(b(0), lngPtr)
If lngPtr <> 0 Then
MoveMemory todi, ByVal lngPtr, Len(todi)
NetApiBufferFree lngPtr
End If
todi
の各変数に、日付、時刻が設定されます。意味は、次の構造体の宣言を見れば、わかりますよね(^^
以下は、宣言部です。標準モジュールに入れてください。
Type TIME_OF_DAY_INFO
tod_elapsedt As Long
tod_msecs As Long
tod_hours As Long
tod_mins As Long
tod_secs As Long
tod_hunds As Long
tod_timezone As Long
tod_tinterval As Long
tod_day As Long
tod_month As Long
tod_year As Long
tod_weekday As Long
End Type
Public Const NERR_Success = 0
Declare Function NetRemoteTOD Lib "netapi32.dll" ( _
lpBuffer As Byte, _
lpbyteptr As Long) As Long
Declare Function NetApiBufferFree Lib "netapi32.dll" ( _
lpbyteptr As Long) As Long
Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
Destination As Any, _
Source As Any, _
ByVal Length As Long)
■ Net Time コマンド の場合
以下のような、コマンドを実行してください。
Shell "command.com /c net time \\Server>c:\temp\temp"
ここで、\\Server がサーバ名です。これを実行すると、以下のような文字列が c:\temp\temp にセットされます。
\\kitsvr の現在の時刻は 00/03/15 午後 05:14 です
コマンドは正常に終了しました。
このファイルを開いて、文字列を解析すれば、日付、時刻が取得できます。
(注意)このページの内容は、Visual
Basic6.0(SP3)
を対象に記述されています。他のバージョンでは、対応できないこともあるので、ご注意願います。
(注意)
ここでの情報については、あくまでも各自の責任にて、充分にテストを行ってご使用ください。内容に関する質問については、回答できる保証がありませんので、予めご了承願います。