1

my goal is: Get the items within the folders in a SharePoint 2010 library. I'm struggling trying to get some Items from a SharePoint 2010 Library using CSOM with PowerShell. I tried three different methods that i found in the internet but still without success. Also the Microsoft's Documentation is really sh*t in this aspect, hope somebody can help me. So here we go:

1.Method A

            [Microsoft.SharePoint.Client.FileInformation]$fileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx, $file.ServerRelativeUrl);
            [System.IO.FileStream]$writeStream = [System.IO.File]::Open("$($libraryTargetPath)\$($file.Name)", [System.IO.FileMode]::Create);
            $fileInfo.Stream.CopyTo($writeStream);
            $writeStream.Close();

With the A method I get this error:

Method invocation failed because [System.Net.ConnectStream] doesn't contain a method named 'CopyTo'.
+ $fileInfo.Stream.CopyTo <<<< ($writeStream);
+ CategoryInfo : InvalidOperation: (CopyTo:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

The [System.Net.ConnectStream] can't find the method CopyTo
I was lookign information about this, in the System.Net namespace and in the "Microsoft.SharePoint.Client.FileInformation" class but without success :(

2.Method B

            $binary = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx, $file.ServerRelativeUrl)
            $Action = [System.IO.FileMode]::Create
            $new = "$($libraryTargetPath)\$($file.Name)"
            $stream = New-Object System.IO.FileStream $new, $Action
            $writer = New-Object System.IO.BinaryWriter($stream)
            $writer.write($binary)
            $writer.Close()

Method B don't give me a error, but in stead of downloading the Items, it makes empty files in the destination folder. So this method isn't downloading the items, just making new files.

3.Method C

            $binary = $file.OpenBinary()
            $stream = New-Object System.IO.FileStream("$($libraryTargetPath)\$($file.Name)"), Create
            $writer = New-Object System.IO.BinaryWriter($stream)
            $writer.write($binary)
            $writer.Close()

I'm not sure if method C belongs to CSOM or to the SharPoint built-in Server side client, if it's so please let me know. This is the error i'm getting:

Method invocation failed because [Microsoft.SharePoint.Client.File] doesn't contain a method named 'OpenBinary'. At C:\Users\Administrator\Desktop\SharePointOnPremisesBackUp\SharePointOnPremisesBackUp.ps1:77 char:31
+ $binary = $file.OpenBinary <<<< ()
+ CategoryInfo : InvalidOperation: (OpenBinary:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound

And here PowerShell can't find the OpenBinary() method in Microsoft.SharePoint.Client.File and there is nearly not information about this method.

Here is the complete function I'm trying to use:

function GetDocumentLibs ($ctx, $web)
{
    Function  IterateFoldersRecursively([Microsoft.SharePoint.Client.Folder]$folder, [Microsoft.SharePoint.Client.ClientContext]$ctx)
    {
      # make sure that the "Web.Context.Url" is the current web url
      if ($web.Context.Url.StartsWith($SiteCollectionUrl) -eq $true)
      {
        $files = $folder.Files
        $ctx.Load($folder.Files)
        $ctx.Load($folder.Folders)
        $ctx.ExecuteQuery()

        foreach ($subFolder in $folder.Folders)
        {
            IterateFoldersRecursively $subFolder $ctx
        }

        # Check if folder Exist and Skip

        $libraryTargetPath = "$($TargetPath)\$($folder.ServerRelativeUrl.Replace('/', '\'))"
        New-Item -Path $libraryTargetPath -ItemType Directory -Force

            foreach ($file in $files)
            {
            # Method 1
            [Microsoft.SharePoint.Client.FileInformation]$fileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx, $file.ServerRelativeUrl);
            [System.IO.FileStream]$writeStream = [System.IO.File]::Open("$($libraryTargetPath)\$($file.Name)", [System.IO.FileMode]::Create);
            $fileInfo.Stream.CopyTo($writeStream)
            $writeStream.Close()

            # Method 2
            $binary = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($ctx, $file.ServerRelativeUrl)
            $Action = [System.IO.FileMode]::Create
            $new = "$($libraryTargetPath)\$($file.Name)"
            $stream = New-Object System.IO.FileStream $new, $Action
            $writer = New-Object System.IO.BinaryWriter($stream)
            $writer.write($binary)
            $writer.Close()

            # Method 3
            $binary = $file.OpenBinary()
            $stream = New-Object System.IO.FileStream("$($libraryTargetPath)\$($file.Name)"), Create
            $writer = New-Object System.IO.BinaryWriter($stream)
            $writer.write($binary)
            $writer.Close()

            # delete folder
            }
       }
    }
    $folder = $web.GetFolderByServerRelativeUrl($web.ServerRelativeUrl)
    $ctx.Load($folder)
    $ctx.ExecuteQuery()

    IterateFoldersRecursively $folder $ctx
}                                               

the tools I'm using:

  1. Sapien's PowerShell Studio
  2. PowerShell V2 with CSOM
  3. SharePoint 2010 OnPremises

Please if you have any Solution, Reference, Documentation or tutorial that can be useful tell me. Thanks in advance.

Lykanox
  • 31
  • 5

1 Answers1

1

After a lot of research i found a solution and decide to use this method:

function GetDocumentLibs ($ctx, $web)
{
    $site = $ctx.Site
    $ctx.Load($site)
    $ctx.ExecuteQuery()
    $siteUrl = $site.Url

    Function IterateFoldersRecursively([Microsoft.SharePoint.Client.Folder]$folder, [Microsoft.SharePoint.Client.ClientContext]$ctx)
    {
        if ($web.Context.Url.StartsWith($SiteCollectionUrl) -eq $true)
        {
            $files = $folder.Files
            $ctx.Load($folder.Files)
            $ctx.Load($folder.Folders)
            $ctx.ExecuteQuery()

            foreach ($subFolder in $folder.Folders)
            {
                IterateFoldersRecursively $subFolder $ctx
            }

            $targetPath = "$($TargetPath)\$($folder.ServerRelativeUrl.Replace('/', '\'))"
            New-Item -Path $targetPath -ItemType Directory -Force

            foreach ($file in $files)
            {
                $client = new-object System.Net.WebClient
                $client.UseDefaultCredentials = $true
                $client.DownloadFile("$($siteUrl)$($file.ServerRelativeUrl)", "$($targetPath)\$($file.Name)")
            }
        }
    }
    $folder = $web.GetFolderByServerRelativeUrl($web.ServerRelativeUrl)
    $ctx.Load($folder)
    $ctx.ExecuteQuery()

    IterateFoldersRecursively $folder $ctx
}

Remember to implement some exception handling. I hope this is helpful for somebody with the same problem.

Lykanox
  • 31
  • 5