In my line of work, I often found myself in a situation where I need to create a new Intune demo tenant with content that I already prepared on a different tenant. I realized fast that I needed to automate this task considering is time consuming and … boring. Therefore, I created a small visual PowerShell Script that copies selected config and compliance policies from a source tenant to a destination tenant.

Prerequisites

To make the below script work, you would need

  • 2 Intune tenants. The source tenant has the content you want to copy. The destination tenant is preferably empty. If you are a MSFT partner you can create trail tenants on https://demos.microsoft.com
  • Global administrator on both tenants
  • The 2 icons used for Ok and Cancel . you need to copy them in the same folder with the script.

How it works

I included below a few screens I captured when using the tool.

The source tenant has existing configuration and compliance profiles as you can see below

The destination tenant is empty

Let’s run the script

Steps:

  1. Enter user for source tenant ( global admin)
  2. Click Connect. Enter password in the newly opened authentication window. Agree on the required permissions if needed
  3. Enter user for destination tenant
  4. Click Connect and enter password. Agree on the required permissions if needed
  5. Click Get Policies to fetch a list of configuration policies on the source tenant
  6. Select the policies that you want to copy
  7. Click Copy to replicate the selected config policies
  8. Click Get Policies and select the compliance policies you want to copy
  9. Click Copy to replicate the compliance policies
  10. Click Ok when done to terminate the script

The destination tenant now has new items, in our case the 3 config policies and one compliance policy that we selected

Script

The script is mostly based on Microsoft Intune PowerShell samples . I created the visual part ( not a UX designer, sorry 😀 ) and the logic

<#Some of the functions below are under Microsoft MIT License 
.COPYRIGHT
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
See LICENSE in the project root for license information.
#>

####################################################

Function Add-DeviceCompliancePolicy(){

<#
.SYNOPSIS
This function is used to add a device compliance policy using the Graph API REST interface
.DESCRIPTION
The function connects to the Graph API Interface and adds a device compliance policy
.EXAMPLE
Add-DeviceCompliancePolicy -JSON $JSON
Adds an iOS device compliance policy in Intune
.NOTES
NAME: Add-DeviceCompliancePolicy
#>

[cmdletbinding()]

param
(
    $JSON,
    $authToken
)

$graphApiVersion = "Beta"
$Resource = "deviceManagement/deviceCompliancePolicies"
    
    try {

        if($JSON -eq "" -or $JSON -eq $null){

        write-host "No JSON specified, please specify valid JSON for the iOS Policy..." -f Red

        }

        else {

        Test-JSON -JSON $JSON

        $uri = "https://graph.microsoft.com/$graphApiVersion/$($Resource)"
        Invoke-RestMethod -Uri $uri -Headers $authToken -Method Post -Body $JSON -ContentType "application/json"

        }

    }
    
    catch {

    $ex = $_.Exception
    $errorResponse = $ex.Response.GetResponseStream()
    $reader = New-Object System.IO.StreamReader($errorResponse)
    $reader.BaseStream.Position = 0
    $reader.DiscardBufferedData()
    $responseBody = $reader.ReadToEnd();
    Write-Host "Response content:`n$responseBody" -f Red
    Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)"
    write-host
    break

    }

}



Function Add-DeviceConfigurationPolicy(){

<#
.SYNOPSIS
This function is used to add an device configuration policy using the Graph API REST interface
.DESCRIPTION
The function connects to the Graph API Interface and adds a device configuration policy
.EXAMPLE
Add-DeviceConfigurationPolicy -JSON $JSON
Adds a device configuration policy in Intune
.NOTES
NAME: Add-DeviceConfigurationPolicy
#>

[cmdletbinding()]

param
(
    $JSON, 
    $authToken
)

$graphApiVersion = "Beta"
$DCP_resource = "deviceManagement/deviceConfigurations"
Write-Verbose "Resource: $DCP_resource"

    try {

        if($JSON -eq "" -or $JSON -eq $null){

        write-host "No JSON specified, please specify valid JSON for the Device Configuration Policy..." -f Red

        }

        else {

        Test-JSON -JSON $JSON

        $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)"
        Invoke-RestMethod -Uri $uri -Headers $authToken -Method Post -Body $JSON -ContentType "application/json"

        }

    }
    
    catch {

    $ex = $_.Exception
    $errorResponse = $ex.Response.GetResponseStream()
    $reader = New-Object System.IO.StreamReader($errorResponse)
    $reader.BaseStream.Position = 0
    $reader.DiscardBufferedData()
    $responseBody = $reader.ReadToEnd();
    Write-Host "Response content:`n$responseBody" -f Red
    Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)"
    write-host
    break

    }

}


Function Test-JSON(){

<#
.SYNOPSIS
This function is used to test if the JSON passed to a REST Post request is valid
.DESCRIPTION
The function tests if the JSON passed to the REST Post is valid
.EXAMPLE
Test-JSON -JSON $JSON
Test if the JSON is valid before calling the Graph REST interface
.NOTES
NAME: Test-AuthHeader
#>

param (

$JSON

)

    try {

    $TestJSON = ConvertFrom-Json $JSON -ErrorAction Stop
    $validJson = $true

    }

    catch {

    $validJson = $false
    $_.Exception

    }

    if (!$validJson){
    
    Write-Host "Provided JSON isn't in valid JSON format" -f Red
    break
    }
}



function Get-AuthToken {

<#
.SYNOPSIS
This function is used to authenticate with the Graph API REST interface
.DESCRIPTION
The function authenticate with the Graph API Interface with the tenant name
.EXAMPLE
Get-AuthToken
Authenticates you with the Graph API interface
.NOTES
NAME: Get-AuthToken
#>

[cmdletbinding()]

param
(
    [Parameter(Mandatory=$true)]
    $User
)

$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User

$tenant = $userUpn.Host

Write-Host "Checking for AzureAD module..."

    $AadModule = Get-Module -Name "AzureAD" -ListAvailable

    if ($AadModule -eq $null) {

        Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview"
        $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable

    }

    if ($AadModule -eq $null) {
        write-host
        write-host "AzureAD Powershell module not installed..." -f Red
        write-host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow
        write-host "Script can't continue..." -f Red
        write-host
        exit
    }

# Getting path to ActiveDirectory Assemblies
# If the module count is greater than 1 find the latest version

    if($AadModule.count -gt 1){

        $Latest_Version = ($AadModule | select version | Sort-Object)[-1]

        $aadModule = $AadModule | ? { $_.version -eq $Latest_Version.version }

            # Checking if there are multiple versions of the same module found

            if($AadModule.count -gt 1){

            $aadModule = $AadModule | select -Unique

            }

        $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
        $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"

    }

    else {

        $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
        $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"

    }

[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null

[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null

$clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547"

$redirectUri = "urn:ietf:wg:oauth:2.0:oob"

$resourceAppIdURI = "https://graph.microsoft.com"

$authority = "https://login.microsoftonline.com/$Tenant"

    try {

    $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority

    # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx
    # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession

    $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto"

    $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId")

    $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result

        # If the accesstoken is valid then create the authentication header

        if($authResult.AccessToken){

        # Creating header for Authorization token

        $authHeader = @{
            'Content-Type'='application/json'
            'Authorization'="Bearer " + $authResult.AccessToken
            'ExpiresOn'=$authResult.ExpiresOn
            }

        return $authHeader
        }

        else {

        Write-Host
        Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red
        Write-Host
        break
        }
    }

    catch {

    write-host $_.Exception.Message -f Red
    write-host $_.Exception.ItemName -f Red
    write-host
    break
    }
}

####################################################

Function Get-DeviceConfigurationPolicy(){

<#
.SYNOPSIS
This function is used to get device configuration policies from the Graph API REST interface
.DESCRIPTION
The function connects to the Graph API Interface and gets any device configuration policies
.EXAMPLE
Get-DeviceConfigurationPolicy
Returns any device configuration policies configured in Intune
.NOTES
NAME: Get-DeviceConfigurationPolicy
#>

[cmdletbinding()]

$graphApiVersion = "Beta"
$DCP_resource = "deviceManagement/deviceConfigurations"
    
    try {
    
    $uri = "https://graph.microsoft.com/$graphApiVersion/$($DCP_resource)"
    (Invoke-RestMethod -Uri $uri -Headers $authToken -Method Get).Value
    
    }
    
    catch {

    $ex = $_.Exception
    $errorResponse = $ex.Response.GetResponseStream()
    $reader = New-Object System.IO.StreamReader($errorResponse)
    $reader.BaseStream.Position = 0
    $reader.DiscardBufferedData()
    $responseBody = $reader.ReadToEnd();
    Write-Host "Response content:`n$responseBody" -f Red
    Write-Error "Request to $Uri failed with HTTP Status $($ex.Response.StatusCode) $($ex.Response.StatusDescription)"
    write-host
    break
    }
}

####################################################

Function Export-JSONData(){

<#
.SYNOPSIS
This function is used to export JSON data returned from Graph
.DESCRIPTION
This function is used to export JSON data returned from Graph
.EXAMPLE
Export-JSONData -JSON $JSON
Export the JSON inputted on the function
.NOTES
NAME: Export-JSONData
#>

param (

$JSON,
$ExportPath

)

    try {

        if($JSON -eq "" -or $JSON -eq $null){

        write-host "No JSON specified, please specify valid JSON..." -f Red

        }

        elseif(!$ExportPath){

        write-host "No export path parameter set, please provide a path to export the file" -f Red

        }

        elseif(!(Test-Path $ExportPath)){

        write-host "$ExportPath doesn't exist, can't export JSON Data" -f Red

        }

        else {

        $JSON1 = ConvertTo-Json $JSON -Depth 5

        $JSON_Convert = $JSON1 | ConvertFrom-Json

        $displayName = $JSON_Convert.displayName

        # Updating display name to follow file naming conventions - https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
        $DisplayName = $DisplayName -replace '\<|\>|:|"|/|\\|\||\?|\*', "_"
        $Properties = ($JSON_Convert | Get-Member | ? { $_.MemberType -eq "NoteProperty" }).Name
            $FileName_CSV = "$DisplayName" + "_" + $(get-date -f dd-MM-yyyy-H-mm-ss) + ".csv"
            $FileName_JSON = "$DisplayName" + "_" + $(get-date -f dd-MM-yyyy-H-mm-ss) + ".json"
            $Object = New-Object System.Object
                foreach($Property in $Properties){

                $Object | Add-Member -MemberType NoteProperty -Name $Property -Value $JSON_Convert.$Property
                }

            write-host "Export Path:" "$ExportPath"

            $Object | Export-Csv -LiteralPath "$ExportPath\$FileName_CSV" -Delimiter "," -NoTypeInformation -Append
            $JSON1 | Set-Content -LiteralPath "$ExportPath\$FileName_JSON"
            write-host "CSV created in $ExportPath\$FileName_CSV..." -f cyan
            write-host "JSON created in $ExportPath\$FileName_JSON..." -f cyan
        }
    }

    catch {
    $_.Exception
    }
}


function ConnectSource {
$srcuser=$User1Text.Text
$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $srcuser
$global:SourceAuthToken = Get-AuthToken -User $userUpn
if ($global:SourceAuthToken){ 
 $ConnPic1.Image = $okimg
 }
}

function ConnectDest {
$destuser=$User2Text.Text
$userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $destuser
$global:DestAuthToken = Get-AuthToken -User $userUpn
if ($global:DestAuthToken){ 
 $ConnPic2.Image = $okimg
 }
}

Function Copy-Config-Policy {
 foreach ($selpol in $ConfPolListBox.SelectedItems )
    {
    foreach ($CPol in $global:sourcepolicies)
        {
        if($selpol -eq $CPol.displayName) {
            $copyCPStatus.Text = "Copying $selpol"

            $cleanPol = $CPol | Select-Object -Property * -ExcludeProperty id,createdDateTime,lastModifiedDateTime,version,supportsScopeTags
            $pol = ConvertTo-Json $cleanPol -Depth 5
            #$pol
            Add-DeviceConfigurationPolicy -JSON $pol -authToken $global:DestAuthToken
            }
        }
    }
}
Function Copy-Compliance-Policy {
 

 foreach ($selpol in $ComplPolListBox.SelectedItems )
    {
    foreach ($CPol in $global:scplpolicies)
        {
        if($selpol -eq $CPol.displayName) {
            $copyCPStatus1.Text = "Copying $selpol"

            $cleanPol = $CPol | Select-Object -Property * -ExcludeProperty id,createdDateTime,lastModifiedDateTime,version
            $scheduledActionsForRule = '"scheduledActionsForRule":[{"ruleName":"PasswordRequired","scheduledActionConfigurations":[{"actionType":"block","gracePeriodHours":0,"notificationTemplateId":"","notificationMessageCCList":[]}]}]'

            $pol = ConvertTo-Json $cleanPol -Depth 5
            $pol = $pol.trimend("}")
            $pol = $pol.TrimEnd() + "," + "`r`n"
            $pol = $pol + $scheduledActionsForRule + "`r`n" + "}"
            Add-DeviceCompliancePolicy -JSON $pol -authToken $global:DestAuthToken
            }
        }
    }
}

Function Get-Compliance-Policies {
if ($global:ComplPolImported -eq $false){
    $uri = "https://graph.microsoft.com/beta/deviceManagement/deviceCompliancePolicies"
    $global:scplpolicies= (Invoke-RestMethod -Uri $uri -Headers $global:SourceAuthToken -Method Get).Value

    foreach ( $scpol in $global:scplpolicies) 
        {
        [void] $ComplPolListBox.Items.Add($scpol.displayName)
        }
    }

    $global:ComplPolImported = $true
}

Function Get-Config-Policies {
if ($global:ConfPolImported -eq $false){
    $uri = "https://graph.microsoft.com/beta/deviceManagement/deviceConfigurations"
    $global:sourcepolicies= (Invoke-RestMethod -Uri $uri -Headers $global:SourceAuthToken -Method Get).Value

    foreach ( $spol in $global:sourcepolicies) 
        {
        [void] $ConfPolListBox.Items.Add($spol.displayName)
        }
    }
    $global:ConfPolImported = $true
}

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

Import-Module -Name AzureAD -ErrorAction Stop
Import-Module -Name PSIntuneAuth -ErrorAction Stop



########
#Start Clean - remove everything 
########
Remove-Variable * -ErrorAction SilentlyContinue; Remove-Module *; $error.Clear(); Clear-Host

#######
# Set global variables
#######
$global:ConfPolImported = $false
$global:ComplPolImported = $false

##############################
### Form & OK & Cancel Buttons
##############################

[System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object System.Windows.Forms.Form
$Form.width = 1000
$Form.height = 800
$Form.backcolor = [System.Drawing.Color]::White
$Form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::Fixed3D
$Form.Text = "Replicate Tenant"
$Form.Font = New-Object System.Drawing.Font("Verdana",10,[System.Drawing.FontStyle]::Bold)
$Form.maximumsize = New-Object System.Drawing.Size(1000,800)
#$Form.startposition = "centerscreen"
$Form.StartPosition ="WindowsDefaultLocation"
$Form.KeyPreview = $false
$Form.Add_KeyDown({if ($_.KeyCode -eq "Enter") {}})
$Form.Add_KeyDown({if ($_.KeyCode -eq "Escape") 
    {$Form.Close()}})

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(430,720)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = 'OK'
$OKButton.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$Form.AcceptButton = $OKButton
$Form.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(530,720)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = 'Cancel'
$CancelButton.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$Form.CancelButton = $CancelButton
$Form.Controls.Add($CancelButton)

######################################
## Set ok and cancel pictures
######################################

$inv = (Get-Variable MyInvocation).Value
$dirpath = Split-Path $inv.MyCommand.Path

$cancelimgfile = "cancel.png"
$okimgfile = "ok.png"
$cancelimg = [System.Drawing.Image]::Fromfile("$dirpath\$cancelimgfile")
$okimg = [System.Drawing.Image]::Fromfile("$dirpath\$okimgfile")

#####################################
## Connect Source tenant setup
#####################################

$ConnPic1= New-Object System.Windows.Forms.PictureBox 
$ConnPic1.Location = New-Object System.Drawing.Point (310,75)
$ConnPic1.Width = 32
$ConnPic1.Height = 32
$ConnPic1.Image = $cancelimg
$Form.Controls.Add($ConnPic1)

$Conn1Button = new-object System.Windows.Forms.Button
$Conn1Button.Location = new-object System.Drawing.Size(310,47)
$Conn1Button.Size = new-object System.Drawing.Size(65,25)
$Conn1Button.Text = "Connect"
$Conn1Button.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Bold)
$Conn1Button.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
#$Conn1Button.Add_MouseHover({$Conn1Button.backcolor = [System.Drawing.Color]::Azure})
#$Conn1Button.Add_MouseLeave({$Conn1Button.backcolor = [System.Drawing.Color]::CornflowerBlue})
$Conn1Button.Add_Click({ConnectSource})
$Form.Controls.Add($Conn1Button)


$SourceLabel = New-Object System.Windows.Forms.Label
$SourceLabel.Location = New-Object System.Drawing.Size(20,20)
$SourceLabel.Size = New-Object System.Drawing.Size(130,20)
$SourceLabel.Text = "Source Tenant"
$Form.Controls.Add($SourceLabel)

$User1Label = New-Object System.Windows.Forms.Label
$User1Label.Location = New-Object System.Drawing.Size(5,55)
$User1Label.Size = New-Object System.Drawing.Size(80,20)
$User1Label.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)
$User1Label.Text = "Enter User"
$Form.Controls.Add($User1Label)

$User1Text = New-Object System.Windows.Forms.TextBox
$User1Text.Location = New-Object System.Drawing.Size(100,50)
$User1Text.Size = New-Object System.Drawing.Size(200,20)
$user1text.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)
$Form.Controls.Add($User1Text)

######################################
## Get Conf Policies Setup
######################################
$ConfPolListBox = New-Object System.Windows.Forms.Listbox
$ConfPolListBox.Location = New-Object System.Drawing.Point(40,170)
$ConfPolListBox.Size = New-Object System.Drawing.Size(360,20)
$ConfPolListBox.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)

$ConfPolListBox.SelectionMode = 'MultiExtended'
$ConfPolListBox.Height = 70
$Form.Controls.Add($ConfPolListBox)

$GPButton = new-object System.Windows.Forms.Button
$GPButton.Location = new-object System.Drawing.Size(40,142)
$GPButton.Size = new-object System.Drawing.Size(95,25)
$GPButton.Text = "Get Policies"
$GPButton.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)
$GPButton.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
$GPButton.Add_Click({Get-Config-Policies})
$Form.Controls.Add($GPButton)

$CopyCPButton = New-Object System.Windows.Forms.Button
$CopyCPButton.Location = New-Object System.Drawing.Size (420, 170)
$CopyCPButton.Size = New-Object System.Drawing.Size(75,25)
$CopyCPButton.Text = "Copy"
$CopyCPButton.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)
$CopyCPButton.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
$CopyCPButton.Add_Click({Copy-Config-Policy})
$Form.Controls.Add($CopyCPButton)

$copyCPStatus = New-Object System.Windows.Forms.Label
$copyCPStatus.Location = New-Object System.Drawing.Size (510,170)
$copyCPStatus.Size = New-Object System.Drawing.Size(200,25)
$copyCPStatus.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)
$copyCPStatus.Text = "NotCopied"
$Form.Controls.Add($copyCPStatus)

###################################################
# Get Compliance Policies 
###################################################
$ComplPolListBox

$ComplPolListBox = New-Object System.Windows.Forms.Listbox
$ComplPolListBox.Location = New-Object System.Drawing.Point(40,300)
$ComplPolListBox.Size = New-Object System.Drawing.Size(360,20)
$ComplPolListBox.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)

$ComplPolListBox.SelectionMode = 'MultiExtended'
$ComplPolListBox.Height = 70
$Form.Controls.Add($ComplPolListBox)

$GPButton1 = new-object System.Windows.Forms.Button
$GPButton1.Location = new-object System.Drawing.Size(40,272)
$GPButton1.Size = new-object System.Drawing.Size(95,25)
$GPButton1.Text = "Get Policies"
$GPButton1.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)
$GPButton1.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
$GPButton1.Add_Click({Get-Compliance-Policies})
$Form.Controls.Add($GPButton1)

$CopyCPButton1 = New-Object System.Windows.Forms.Button
$CopyCPButton1.Location = New-Object System.Drawing.Size (420, 300)
$CopyCPButton1.Size = New-Object System.Drawing.Size(75,25)
$CopyCPButton1.Text = "Copy"
$CopyCPButton1.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)
$CopyCPButton1.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
$CopyCPButton1.Add_Click({Copy-Compliance-Policy})
$Form.Controls.Add($CopyCPButton1)

$copyCPStatus1 = New-Object System.Windows.Forms.Label
$copyCPStatus1.Location = New-Object System.Drawing.Size (510,300)
$copyCPStatus1.Size = New-Object System.Drawing.Size(200,25)
$copyCPStatus1.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)
$copyCPStatus1.Text = "NotCopied"
$Form.Controls.Add($copyCPStatus1)

####################################################
# Connect Destination tenant setup 
####################################################
$ConnPic2= New-Object System.Windows.Forms.PictureBox 
$ConnPic2.Location = New-Object System.Drawing.Point (910,75)
$ConnPic2.Width = 32
$ConnPic2.Height = 32
$ConnPic2.Image = $cancelimg
$Form.Controls.Add($ConnPic2)

$Conn2Button = new-object System.Windows.Forms.Button
$Conn2Button.Location = new-object System.Drawing.Size(910,47)
$Conn2Button.Size = new-object System.Drawing.Size(65,25)
$Conn2Button.Text = "Connect"
$Conn2Button.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Bold)
$Conn2Button.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
$Conn2Button.Add_Click({ConnectDest})
$Form.Controls.Add($Conn2Button)

$DestLabel = New-Object System.Windows.Forms.Label
$DestLabel.Location = New-Object System.Drawing.Size(620,20)
$DestLabel.Size = New-Object System.Drawing.Size(170,20)
$DestLabel.Text = "Destination Tenant"
$Form.Controls.Add($DestLabel)

$User2Label = New-Object System.Windows.Forms.Label
$User2Label.Location = New-Object System.Drawing.Size(605,55)
$User2Label.Size = New-Object System.Drawing.Size(80,20)
$User2Label.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)
$User2Label.Text = "Enter User"
$Form.Controls.Add($User2Label)

$User2Text = New-Object System.Windows.Forms.TextBox
$User2Text.Location = New-Object System.Drawing.Size(700,50)
$User2Text.Size = New-Object System.Drawing.Size(200,20)
$user2text.Font = New-Object System.Drawing.Font("Verdana",8,[System.Drawing.FontStyle]::Regular)
$Form.Controls.Add($User2Text)


$Form.Add_Shown({$Form.Activate()})
$result = $Form.ShowDialog()