現在、WindowsMoible5にてWindows2000の共有フォルダに自動マウントする

機能を開発しようとしているのですが、WNetAddConnection3を呼び出すとNotSupportedExceptionエラーが発生し困っています。
※C++で実装するとNotSupportedExceptionエラーは発生しません。

【環境】
 OS :WindowsMobile5(WindowsCE5)
機体:hx2790b
開発環境:VisualStudio2005
言語:VB.net

【やりたい事】
 LAN上のWindows2000の共有フォルダからファイルをコピーしたい。
 その際に、ログイン画面(ユーザー、パスワード、ドメインを入力する
 画面)を表示させずに共有フォルダを利用可能にしたい。

【ソース】
Private Declare Function WNetAddConnection3 Lib "CoreDll.dll" Alias "WNetAddConnection3W" (ByRef hwndOwner As Object, ByRef lpNetResource As NETRESOURCE, ByRef lpPassword As String, ByRef lpUserName As String, ByVal dwFlags As Integer) As Integer
   
   :
   略
   :

Dim netrs As NETRESOURCE
netrs.dwType = RESURCETYPE_ANY
netrs.lpLocalName = vbNullString
netrs.lpRemoteName = "\\hogeWin2k\share"
netrs.lpProvider = vbNullString
    'API呼び出し!
lngRet = WNetAddConnection3(vbNullString, netrs, "USERNAME", "PASSWORD", CONNECT_INTERACTIVE)


よろしくお願い致します。

回答の条件
  • 1人5回まで
  • 登録:2008/09/02 13:52:22
  • 終了:2008/09/03 19:34:42

ベストアンサー

id:ardarim No.1

ardarim回答回数896ベストアンサー獲得回数1442008/09/03 03:55:20

ポイント50pt

.NET Compact Frameworkのマーシャル機能はかなり限定されていますので、文字列を含んだ構造体などは自動的に適切な処理を行ってくれません。この場合、自分でマーシャリング処理を実装して適切なアンマネージド形式の構造体を作ってAPIにポインタを渡す必要があります。

こちらにやり方が書かれています。

Microsoft .NET Compact Framework での高度な P/Invoke

VBでやる場合は、3つめの方法「マネージ文字列ポインタの使用」を使って実装することになります。

時間が作れたらサンプルを作って回答追加しますが、C++の経験もおありのようなので、後学のために自分で挑戦してみるのもよろしいかと思います。

またはサックリ済ませるのであれば、1つめの方法(C++でサンクDLLを作って経由する)の方が手っ取り早いです。

id:hh1108

ardarim様

ありがとうございます。

教えていただいたURLを参考にこちらでもやろうと思うのですが、

なかなか作業時間を確保するのが難しく、、、

もしよろしければ「マネージ文字列ポインタの使用」でサンプルまでご提示いただけるとうれしいです。

2008/09/03 09:33:16

その他の回答(1件)

id:ardarim No.1

ardarim回答回数896ベストアンサー獲得回数1442008/09/03 03:55:20ここでベストアンサー

ポイント50pt

.NET Compact Frameworkのマーシャル機能はかなり限定されていますので、文字列を含んだ構造体などは自動的に適切な処理を行ってくれません。この場合、自分でマーシャリング処理を実装して適切なアンマネージド形式の構造体を作ってAPIにポインタを渡す必要があります。

こちらにやり方が書かれています。

Microsoft .NET Compact Framework での高度な P/Invoke

VBでやる場合は、3つめの方法「マネージ文字列ポインタの使用」を使って実装することになります。

時間が作れたらサンプルを作って回答追加しますが、C++の経験もおありのようなので、後学のために自分で挑戦してみるのもよろしいかと思います。

またはサックリ済ませるのであれば、1つめの方法(C++でサンクDLLを作って経由する)の方が手っ取り早いです。

id:hh1108

ardarim様

ありがとうございます。

教えていただいたURLを参考にこちらでもやろうと思うのですが、

なかなか作業時間を確保するのが難しく、、、

もしよろしければ「マネージ文字列ポインタの使用」でサンプルまでご提示いただけるとうれしいです。

2008/09/03 09:33:16
id:ardarim No.2

ardarim回答回数896ベストアンサー獲得回数1442008/09/03 12:07:06

ポイント35pt

いちおう動くみたいですが、バグ等は保証の限りでありませんので自己責任でお願いします。

MemoryとStringPtrはMicrosoftのページからそのままコピペしています。

いろいろ調べたらこのMicrosoftのページで紹介されているMemoryというクラスもメモリリークのバグがあるようですので見直したほうが良いと思います。

Imports System.ComponentModel
Imports System.Runtime.InteropServices

Public Class Form1

    Private Structure NETRESOURCE
        Public dwScope As Integer
        Public dwType As Integer
        Public dwDisplayType As Integer
        Public dwUsage As Integer
        Public lpLocalName As StringPtr
        Public lpRemoteName As StringPtr
        Public lpComment As StringPtr
        Public lpProvider As StringPtr

        Public Sub Free()
            lpLocalName.Free()
            lpRemoteName.Free()
            lpComment.Free()
            lpProvider.Free()
        End Sub
    End Structure

    Private Declare Function WNetAddConnection3 Lib "coredll" Alias "WNetAddConnection3W" ( _
        ByVal hwndOwner As Integer, _
        ByRef lpNetResource As NETRESOURCE, _
        ByVal lpPassword As String, _
        ByVal lpUserName As String, _
        ByVal dwFlags As Integer _
    ) As Integer

    Private Const RESOURCETYPE_ANY As Integer = &H0
    Private Const CONNECT_INTERACTIVE As Integer = &H8

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim lngRet As Integer
        Dim netrs As NETRESOURCE

        netrs.dwType = RESOURCETYPE_ANY
        netrs.lpLocalName = New StringPtr()
        netrs.lpRemoteName = New StringPtr("\\hogeWin2k\share")
        netrs.lpComment = New StringPtr()
        netrs.lpProvider = New StringPtr()

        lngRet = WNetAddConnection3(System.IntPtr.Zero, netrs, "password", "username", CONNECT_INTERACTIVE)

        MsgBox(lngRet)

        netrs.Free()

    End Sub
End Class

Public Class Memory
    <DllImport("coredll.dll", SetLastError:=True)> _
    Private Shared Function LocalAlloc(ByVal uFlags As Integer, _
      ByVal uBytes As Integer) As IntPtr
    End Function

    <DllImport("coredll.dll", SetLastError:=True)> _
    Private Shared Function LocalFree(ByVal hMem As IntPtr) As IntPtr
    End Function

    <DllImport("coredll.dll", SetLastError:=True)> _
    Private Shared Function LocalReAlloc(ByVal hMem As IntPtr, _
      ByVal uBytes As Integer, ByVal fuFlags As Integer) As IntPtr
    End Function

    Private Const LMEM_FIXED As Integer = 0
    Private Const LMEM_MOVEABLE As Integer = 2
    Private Const LMEM_ZEROINIT As Integer = &H40

    Private Const LPTR = (LMEM_FIXED Or LMEM_ZEROINIT)

    ' LocalAlloc を使用して、メモリ ブロックを割り当てます。
    Public Shared Function AllocHLocal(ByVal cb As Integer) As IntPtr
        Return LocalAlloc(LPTR, cb)
    End Function

    ' AllocHLocal で割り当てられたメモリを解放します。
    Public Shared Sub FreeHLocal(ByVal hlocal As IntPtr)
        If Not hlocal.Equals(IntPtr.Zero) Then
            If Not IntPtr.Zero.Equals(LocalFree(hlocal)) Then
                Throw New Win32Exception(Marshal.GetLastWin32Error())
            End If
            hlocal = IntPtr.Zero
        End If
    End Sub

    ' 以前に AllocHLocal で割り当てられたメモリ ブロックのサイズを変更します。
    Public Shared Function ReAllocHLocal(ByVal pv As IntPtr, _
      ByVal cb As Integer) As IntPtr
        Dim newMem As IntPtr = LocalReAlloc(pv, cb, LMEM_MOVEABLE)
        If newMem.Equals(IntPtr.Zero) Then
            Throw New OutOfMemoryException
        End If
        Return newMem
    End Function

    ' マネージ文字列の内容をアンマネージ メモリにコピーします。
    Public Shared Function StringToHLocalUni( _
     ByVal s As String) As IntPtr
        If s Is Nothing Then
            Return IntPtr.Zero
        Else
            Dim nc As Integer = s.Length
            Dim len As Integer = 2 * (1 + nc)
            Dim hLocal As IntPtr = AllocHLocal(len)
            If hLocal.Equals(IntPtr.Zero) Then
                Throw New OutOfMemoryException
            Else
                Marshal.Copy(s.ToCharArray(), 0, hLocal, s.Length)
                Return hLocal
            End If
        End If
    End Function
End Class

Public Structure StringPtr
    Private szString As IntPtr

    Public Sub New(ByVal s As String)
        Me.szString = Memory.StringToHLocalUni(s)
    End Sub

    Public Overrides Function ToString() As String
        Return Marshal.PtrToStringUni(Me.szString)
    End Function

    Public Sub Free()
        Memory.FreeHLocal(Me.szString)
    End Sub
End Structure

id:hh1108

ardarim様

サンプルの提示までいただきありがとうございました。

今回はC#でDLLを作成しそれをVB.net側から利用することにします。

(メモリリークの可能性があるのであればVB.netで実装するのは怖いです)

2008/09/03 19:33:39

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません