2

私たちの会社には、UNCが次のような共有ポイントドキュメントサーバーがあります:\\ theserver.ourdomain.com \ rootdirectory

現在、このドライブはローカルコンピューターのZ:\にマップされています。Z:\にアクセスするには、(ログインするたびに)資格情報(この場合は、ログオンに使用したユーザー名とパスワード)を指定して、ルートディレクトリ内のフォルダーとファイルにアクセスする必要があります

ファイルをSharePointサーバーにコピーする必要がある状況にあります。マップされたネットワークドライブを使用せずにファイルをサーバーにコピーできるようにしたい(パスにZ:\を指定する必要はありません)。GetDirectories()、GetFiles()、IO.File.Copy()などの基本的なIO関数を実行できるように、資格情報を提供するにはどうすればよいですか?

私は次のことを調べましたが、それらを機能させることに失敗しました:

  1. プレーンテキストのユーザー名とパスワードを指定し、その呼び出しからトークンを取得し、WindowsIdentityクラスの新しいインスタンスを使用してそのユーザーを偽装することによるLogonUserAPI呼び出し。トークンを取得できましたが、なりすましが機能していないようです。アクセス拒否エラーを取得し続けました。
  2. CredUIPromptForCredentials / CredUIPromptForWindowsCredentials API呼び出しですが、これらは、資格情報を入力でき、実際には何もしない、凝ったWindowsUI用であることに気付きました。

    <DllImport("advapi32.dll", SetLastError:=True)> _
    Private Shared Function LogonUser(lpszUsername As String, lpszDomain As String, _
                                              lpszPassword As String, dwLogonType As Integer, _
                                              dwLogonProvider As Integer, ByRef phToken As IntPtr) As Boolean
    End Function
    
    <DllImport("kernel32.dll", CharSet:=CharSet.Auto)> _
    Private Shared Function CloseHandle(handle As IntPtr) As Boolean
    End Function
    
    '// logon types
    Public Const LOGON32_LOGON_NETWORK As Integer = 3
    Public Const LOGON32_LOGON_NEW_CREDENTIALS As Integer = 9
    
    '// logon providers
    Public Const LOGON32_PROVIDER_WINNT50 As Integer = 3
    Public Const LOGON32_PROVIDER_WINNT40 As Integer = 2
    Public Const LOGON32_PROVIDER_WINNT35 As Integer = 1
    Public Const LOGON32_PROVIDER_DEFAULT As Integer = 0
    
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim token = IntPtr.Zero
        Dim success = LogonUser("username", "domain", "password", _
                                LOGON32_LOGON_NEW_CREDENTIALS, _
                                LOGON32_PROVIDER_DEFAULT, token)
    
        If Not success Then
            Me.RaiseLastWin32Error()
        End If
    
        Using identity = New WindowsIdentity(token)
            Using impersonated = identity.Impersonate()
                Try
                    Dim info = New DirectoryInfo("\\theserver.ourdomain.com\rootdirectory\")
                    Dim files = info.GetDirectories()
                Catch ex As Exception
                Finally
                    impersonated.Undo()
                End Try
                If Not CloseHandle(token) Then
                    Me.RaiseLastWin32Error()
                End If
            End Using
        End Using
    
    End Sub
    
    Private Sub RaiseLastWin32Error()
        Dim hr = Marshal.GetLastWin32Error()
        Dim ex = Marshal.GetExceptionForHR(hr)
    
        If ex IsNot Nothing Then
            Throw ex
        End If
        Throw New SystemException(String.Format("Call resulted in error code {0}", hr))
    End Sub
    
4

2 に答える 2

0

これは非常に異なるアプローチであるため、あなたの質問に対する直接の答えではありません。ご迷惑をおかけして申し訳ありませんが、SharePoint Webサービスを使用してファイルをロードし、情報を取得することを検討しましたか?

私はいくつかの理由でこのアプローチを提案します:

  1. 発生している問題は、SharePointがSystem.IOと100%互換性がない可能性のあるWebDavを実装しているために発生している可能性があります。私はここの内部の専門家ではありません、私は確かに互換性について知りません、しかしそれはもっともらしいようです。
  2. あなたが持っているUNCの場所は、Webサービスが必要とするURLに簡単にマッサージすることができます。
  3. プロキシに直接クレデンシャルを設定でき、時間がかかる場合があります。(ただし、これらの呼び出しは別のWebサーバーから行うため、例のアプリプールのクレデンシャルで十分です)

念のため、サニタイズおよび簡略化されたコードを次に示します。

// location takes the form http://server.name.com/site/library/folder/document.ext

public string UploadDocument(string location, byte[] fileContents)
{
    var result = String.empty;
    var destination = new string[1];
    destination[0] = location;
    var fileName = Path.GetFileName(location);
    var fieldInfo = new FieldInformation[0];
    CopyResult[] copyResults;

    _copyService.Url = "http://server.name.com/_vti_bin/Copy.asmx";
    _copyService.Credentials = CredentialCache.DefaultCredentials;
    _copyService.CopyIntoItems(fileName, destination, fieldInfo, fileContents, out copyResults);

    var errorCode = copyResults[0].ErrorCode;
    if (errorCode != CopyErrorCode.Success)
    {
        if (errorCode == CopyErrorCode.DestinationCheckedOut)
            result = "File is currently checked out. Please try again later.";
        else
            result = "Error uploading content.";
    }

    return result;
}

_copyServiceは、実行時の実装がCopy.asmxSharePointWebサービスからVisualStudioツールによって生成されたプロキシである場合に挿入する依存関係です。

Lists.asmx Webサービスを使用して、フォルダーの内容とドキュメントのメタデータを取得することもできます。このアプローチの最大の欠点は、情報のクエリにはCAMLの知識が必要であり、結果の処理はそれほど簡単ではないことです。ただし、サービスはMSDNに合理的に文書化されており、操作はすべてアプリケーションで機能しています。

于 2012-06-12T21:50:53.347 に答える
0

さて、私はWNetAddConnection2APIの助けを借りてこれを解決することができました。このAPIは、ネットワークドライブのマッピングにも使用されますが、ドライブ文字を指定せずにこのメソッドを呼び出して、接続を追加するだけにすることができます。

たとえば、ドライブXが\\ server \ shareにマップされているとします。サーバー上のファイルにアクセスするには、ユーザー名とパスワードが必要だとします。Windows 7を再起動すると、その接続が失われる可能性があります(Windowsが一部のネットワークドライブに再接続できなかったという通知が表示されます)。そのサーバーのファイルへのアクセスを必要とするアプリケーションがあり、資格情報を提供せずにそのサーバーにアクセスしようとすると、アクセス拒否の例外が発生します。WNetAddConnection2の呼び出しに成功すると、マップされていないネットワークドライブが修正されるだけでなく、System.IO名前空間を介してファイル/ディレクトリにアクセスできるようになります。

私たちはSharepointを使用しており、これは私にとってはうまくいきました。他の人にも返信してくれてありがとう。

于 2012-06-13T20:49:25.343 に答える