2

I created az Azure file share where I would like to store a few SharePoint provisioning files, templates and xml's. Files are copied to the share and ready to use.

I am aware of the Get-AzureStorageFileContent command that can be used to retrieve single files, but I need to see this share as share, as the files are referenced from withing the the PnP provisioning template like:

  <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="webparts\head.xml"/>

This works fine when I run the script local or from network share. So, my question is, how can I either use the UNC path or map it as network drive?

According to the documentation, I should be able to use it as smb share, but when I try to connect, I get this error:

New-SmbMapping : Cannot connect to CIM server. The specified service does not exist as an installed service.

New-PSDrive doesn't exist in Azure Powershell. I found this as a module in Azure, but I stopped installing dependencies when one of them required to update .Net in Azure.

Can someone please give me an end-to-end guide, how can I achieve a real file share functionality with Azure File Share?

Edit: and acceptable workaround would be if I could copy all files from the share to current temporary folder, because from there I could access them with $env:TEMP .

Ivan Glasenberg
  • 29,865
  • 2
  • 44
  • 60
vilmarci
  • 451
  • 10
  • 31

2 Answers2

3

Update: recursively copy all the files and folders to $env:temp

Code in the powershell runbook:

function Get-AzureFiles
{
param([string]$filesharename = 'testfolder', #replace with your own fileshare name
      [string]$username = 'your account name',
      [string]$password = 'your account key', 
      [string]$destination=$env:TEMP+"\", #note there is a slash at the end
      [string]$path="")

      $temp = $env:TEMP

      # get the context
      $context = New-AzureStorageContext -StorageAccountName $username -StorageAccountKey $password

      # get all files and directories
      if($path -eq "")
      {
      $content = Get-AzureStorageFile -ShareName $filesharename -Context $context
      }
      else
      {
      $content = Get-AzureStorageFile -ShareName $filesharename -Context $context -Path $path | Get-AzureStorageFile
      }

      if(!(test-path $destination))
        {
        mkdir $destination
        }

      foreach($c in $content)
      {
        $p = $c.uri.LocalPath -replace "$($c.share.name)/" ,''
        #write-host "the value p is: $p"

        #if it's a directory in fileshare
        if($c.gettype().name -eq "CloudFileDirectory")
        {
           # Write-Host "$($c.share.name) is a directory"
            $destination =$temp + $c.uri.PathAndQuery -replace "/","\"

            #create the folder locally
            if(!(test-path $destination))
            {
            mkdir $destination
            #write-host "the new directory $destination is created locally."
            }

            #define the folder path in fileshare
            $path = ($c.uri.localpath -replace "/$filesharename/" , "") -replace "/","\"

            Get-AzureFiles -destination $destination -path $path

        }
        #if it's a file
        elseif($c.gettype().name -eq "CloudFile")
        {         
         $s = $temp + $c.uri.PathAndQuery -replace "/","\"
         #Write-Output "downloading --- $s"

         $d1 = $c.uri.PathAndQuery -replace "/","\"
         $d1 = $d1.remove($d1.LastIndexOf("\")+1)

         $destination =$temp + $d1



            #create the folder locally
            if(!(test-path $destination))
            {
            mkdir $destination
            #write-host "the new directory $destination is created locally."
            }
         $path_temp = $c.uri.PathAndQuery -replace "/$filesharename/",""

         Get-AzureStorageFileContent -ShareName $filesharename -Path $path_temp  -Destination $destination -Context $context        
        }
      }
}


function do-test
{
get-AzureFiles

# you can operate the files copied to $env:temp
dir $env:TEMP\testfolder
dir $env:TEMP\testfolder\t1
dir $env:TEMP\testfolder\t1\t1sub
}

do-test

Test result:

enter image description here

My fileshare structure in azure portal:

enter image description here

Ivan Glasenberg
  • 29,865
  • 2
  • 44
  • 60
  • Thanks, this works good with files in the root. Is there any chance to get everything, files, folder recursively? – vilmarci Jan 10 '19 at 13:41
  • I'm working on this, and will let you know when any updates :) – Ivan Glasenberg Jan 10 '19 at 13:52
  • @vilmarci, I have updated my answer, recursively copy all the files and folders in fileshare. If it works for you, please help mark it as an answer. Thanks:) – Ivan Glasenberg Jan 11 '19 at 08:41
  • Thank you for helping. The folders are created, but no files (except the ones in the root) are copied. I see an error message after every folder: `ERROR: New-AzureStorageContext : Invalid length for a Base-64 char array or string.` I enabled the outputs in your code, I never see the the "downloading ..." part. – vilmarci Jan 11 '19 at 11:25
  • Found it: in this line `Get-AzureFiles -destination $destination -path $path` you also need to pass the context and the file share name. Also, it has difficulties, when the path contains spaces and encoded to %20, these should be decoded, but I can manage that from this point. Otherwise it is perfect, thank you very much. – vilmarci Jan 11 '19 at 16:48
0

It looks like the error you received is related to permissions on the DNS server, this Thread provides the below solution:

add these two roles: DnsAdmins and WinRMRemoteWMIUsers__ on the DNS Server/DC. then the following on the DNS server:

*1. Open Computer Management Console. Right click WMI Control (under Services and Applications) and click property. 2. In the newly open Window, click on Security tab.

  1. Expand Root tree, and then click on the node CIMV2, and click the button security
  2. In the newly open Window, click the button Advanced.
  3. In the newly open Window, click the button Add under the permission tab.
  4. In the newly open Window, click on “select a principal”, then search and add the group WinRMRemoteWMIUsers__ as the principal, then click ok.
  5. In the applies to, choose “this namespace and subnamespace”.
  6. For the permission, check on “Execute Methods”, “Enable Accounts” and “Remote Enable”
  7. Click OK three times.
  8. Then navigate to the node Root – Microsoft – Windows – DNS. Do the same things, add permission for WinRMRemoteWMIUsers.
  9. Restart service “Windows Management Instrumentation.
  10. Check whether the issue is fixed.*

This is the full MS official documentation which provides steps to attach a drive locally as well