Smb.ps1


Function ExecuteOnSmbShareWithCreds([ScriptBlock]$scriptblock, [PSCredential]$smbCred, [string]$share, [string[]]$arguments)
{
    # Use this function when the code in the scriptblock is all Powershell.
    $name = "CtxMapping"

    LogIt "ExecuteOnSmbShareWithCreds as $smbCred on share $share with args $arguments"

    $err = ""
    $drive = New-PSDrive -Name $name -PSProvider "FileSystem" -Root $share -Credential $smbCred -Scope Global -ErrorVariable "err"
    if (!$drive) {
        throw "Failed to map share $share error: $err"
    }
    try {
        LogIt "Operating on $($drive.Name) with $arguments"
        $output = & $scriptblock -SharePath "$($name):" -Arguments $arguments
    }
    finally {
        $null = Remove-PSDrive -Name $name
    }
    return $output
}


Function ExecuteOnSmbShareAsUser([ScriptBlock]$scriptblock, [string]$user, [string]$password, [string]$share, [string[]]$arguments)
{
    LogIt "ExecuteOnSmbShareAsUser as $user on share $share with args $arguments"
    $smbCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, (ConvertTo-SecureString -String "$password" -AsPlainText -Force)
    return ExecuteOnSmbShareWithCreds $scriptblock $smbCred $share $arguments
}


Function ExecuteOnMappedShareAsUser([ScriptBlock]$scriptblock, [string]$user, [string]$password, [string]$share, [string[]]$arguments)
{
    # Use this function when the code in the scriptblock is not all Powershell.
    LogIt "ExecuteOnMappedShareAsUser as $user on share $share with args $arguments"

    $err = ""

    try {
        $parameters = @{
            RemotePath = $share
            LocalPath = "*"
            ErrorVariable = "err"
        }
        if ($user -And $password) {
            $parameters["UserName"] = $user
            $parameters["Password"] = $password
        }
        $drive = New-SmbMapping @parameters
        if (!$drive) {
            throw "Failed to map drive for $share error: $err"
        }
        LogIt "Operating on $($drive.LocalPath) with $arguments"
        $output = & $scriptblock -SharePath $drive.LocalPath -Arguments $arguments
    }
    finally {
        $null = Remove-SmbMapping -RemotePath $share -Force
    }
    return $output
}


class SmbConfig {

    [string]$DiskExtension
    [string]$UserAndDomain
    [string]$ShareUnc
    [string]$ExportFilePath
    [string]$FileOnShare
    [hashtable]$DiskFormats = @{
        VhdDiskFormat = "vhd"
        VhdxDiskFormat = "vhdx"
        VmdkDiskFormat = "vmdk"
        VmdkSparseDiskFormat = "vmdk"
        QCow2DiskFormat = "qcow"
        RawDiskFormat = "raw"
    }

    SmbConfig([psobject]$object) {
        $this.DiskExtension = $this.DiskFormats[$object.SmbDiskFormat]
        $this.UserAndDomain = "$($object.SmbUserDomain)\$($object.SmbUserName)"

        if ($object.SmbPort) {
            $this.ShareUnc = "\\$($object.SmbHost):$($object.SmbPort)\$($object.SmbShare)"
        } else {
            $this.ShareUnc = "\\$($object.SmbHost)\$($object.SmbShare)"
        }
        if ($object.SmbPath) {
            $this.ExportFilePath = Join-Path -Path $object.SmbPath -ChildPath "$($object.SmbDiskName).$($this.DiskExtension)"
        } else {
            $this.ExportFilePath = "$($object.SmbDiskName).$($this.DiskExtension)"
        }
        $this.FileOnShare = Join-Path -Path $this.ShareUnc -ChildPath $this.ExportFilePath
    }
}