Antoine.st String Parameters

文字列引数 (受け取り)

vb@ml.acty-net.ne.jp の [vb 24348] ユーザー名の取得 で、これらの Win32 API がうまく動かないという話題が出ていたので、ちょっと追試してみました。結果としては、何の問題もなく動きましたけど...。


  Imports System.Text
  Imports System.Runtime.InteropServices

  <DllImport("advapi32.dll")> _
  Public Overloads Shared Function GetUserName( _
     ByVal lpBuffer As StringBuilder, _
     ByRef nSize As Integer) As Boolean
  End Function

  <DllImport("advapi32.dll")> _
  Public Overloads Shared Function GetUserName( _
     ByVal lpBuffer As IntPtr, _
     ByRef nSize As Integer) As Boolean
  End Function

  <DllImport("Mpr.dll")> _
  Public Shared Function WNetGetUser( _
      ByVal lpName As String, _
      ByVal lpUserName As StringBuilder, _
      ByRef lpnLength As Integer) As Integer
  End Function

  Public Const UNLEN As Integer = 256

  '
  ' By GetUserName() API
  '
  Private Sub Button1_Click( _
      ByVal sender As System.Object, _
      ByVal e As System.EventArgs _
  ) Handles Button1.Click

      Dim sb As StringBuilder = New StringBuilder(100)
      Dim ln As Integer = sb.Capacity
      Dim result As Boolean

      result  = GetUserName(sb, ln)

      MsgBox(sb.ToString())

  End Sub

  '
  ' By WNetGetUser() API
  '
  Private Sub Button2_Click( _
      ByVal sender As System.Object, _
      ByVal e As System.EventArgs _
  ) Handles Button2.Click

      Dim sb As StringBuilder = New StringBuilder(100)
      Dim ln As Integer = sb.Capacity
      Dim result As Integer

      result = WNetGetUser(vbNullString, sb, ln)

      MsgBox(sb.ToString())

  End Sub

C ライクにやるのなら、↓でしょうね。ただ、この方法だと、メモリの確保とか解放とか面倒なので、一般的には StringBuilder を使うことになるのかな。


  Private Sub Button3_Click( _
      ByVal sender As System.Object, _
      ByVal e As System.EventArgs _
  ) Handles Button3.Click

      Dim lp As IntPtr
      Dim s As String
      Dim ln As Integer

      s = Space(UNLEN)
      ln = Len(s)
      lp = Marshal.AllocHGlobal(ln)

      GetUserName(lp, ln)
      s = Marshal.PtrToStringAnsi(lp)
      MsgBox(s)

      Marshal.FreeHGlobal(lp)

  End Sub

さらに、というかなんというか、Visual Basic .NET では、↓のような書き方もできます。Immutable 属性を持つ String 型で受け取れるのは、間でランタイムがごにょごにょやってくれているからだと推測されます。


  Declare Ansi Function GetUserNameByDeclare _
      Lib "advapi32.dll" _
      Alias "GetUserNameA" _
  ( _
      ByVal lpBuffer As String, _
      ByRef nSize As Integer _
  ) As Integer

  Public Const UNLEN As Integer = 256

  Private Sub Button4_Click( _
      ByVal sender As System.Object, _
      ByVal e As System.EventArgs _
  ) Handles Button4.Click

      Dim s As String
      Dim ln As Integer

      s = Space(UNLEN)
      ln = Len(s)

      GetUserNameByDeclare(s, ln)
      MsgBox(s)

  End Sub