Removed support for AzureRM

Az module is required for Native Azure objects (Conditional access, Azure branding and MDM/MAM settings)
Fixed limit on Conditional Access objects
Remove properties before import (date etc.)
Added WIP policies
Added support for installing Intune module for user only
This commit is contained in:
Micke
2021-02-03 12:50:22 +11:00
parent bcc178ac99
commit b4c737dd6d
15 changed files with 340 additions and 140 deletions

View File

@@ -198,6 +198,16 @@ function Get-AppProtectionObjectType
{
"androidManagedAppProtections"
}
elseif($odataType -like "*mdmWindowsInformationProtectionPolicy*")
{
# Win 10 - With enrollment e.g. Intune enrolled Win 10 devices
"mdmWindowsInformationProtectionPolicies"
}
elseif($odataType -like "*windowsInformationProtectionPolicy*")
{
# Win 10 - Without enrollment e.g. MAM polices for Win 10
"WindowsInformationProtectionPolicies"
}
}
function Get-AppProtectionObjectForExport
@@ -257,10 +267,8 @@ function Import-AppProtection
if(($obj | GM -MemberType NoteProperty -Name "Apps"))
{
$apps = $obj.Apps
# Remove apps properties
Remove-ObjectProperty $obj "apps"
Remove-ObjectProperty $obj "apps@odata.context"
}
Start-PreImport $obj -RemoveProperties @("apps","apps@odata.context")
Write-Status "Import $($obj.displayName)"

View File

@@ -247,17 +247,7 @@ function Import-Application
{
param($obj)
Remove-ObjectProperty $obj "uploadState"
Remove-ObjectProperty $obj "publishingState"
Remove-ObjectProperty $obj "isAssigned"
Remove-ObjectProperty $obj "roleScopeTagIds"
Remove-ObjectProperty $obj "dependentAppCount"
Remove-ObjectProperty $obj "committedContentVersion"
Remove-ObjectProperty $obj "id"
Remove-ObjectProperty $obj "createdDateTime"
Remove-ObjectProperty $obj "lastModifiedDateTime"
Remove-ObjectProperty $obj "isFeatured"
Remove-ObjectProperty $obj "size"
Start-PreImport $obj -RemoveProperties @("uploadState","publishingState","isAssigned","roleScopeTagIds","dependentAppCount","committedContentVersion","id","isFeatured","size")
Write-Status "Import $($obj.displayName)"

View File

@@ -203,6 +203,8 @@ function Import-AutoPilot
Write-Status "Import $($obj.displayName)"
Start-PreImport $obj
Invoke-GraphRequest -Url "/deviceManagement/windowsAutopilotDeploymentProfiles" -Content (ConvertTo-Json $obj -Depth 5) -HttpMethod POST
}

View File

@@ -1,6 +1,82 @@
#Requires -module Az.Accounts
function Invoke-InitializeModule
{
if(-not $global:AzToken)
{
# Only allow re-logging if it failed the first time
$global:AuthenticatedToAzure = $false
}
#!!! - Used for testing login
#Disconnect-AzAccount -Username admin@delematelab2.onmicrosoft.com
}
function Connect-AzureNative
{
<#
.SYNOPSIS
Tries to connect to Azure with existing token
Uses Connect-AZAccount if no token found in cache
#>
param($user)
Write-Log "Authenticate to Azure (Az module). Try from cache with user $user"
$Context = (Get-AzContext -ListAvailable | Where { $_.Account.Id -eq $user } | select -first 1)
if (-not $Context)
{
$user | Clip # Copy login id to clipboard
# Run Connect-AZAccount in a separate runspace or it will hang
$Runspace = [runspacefactory]::CreateRunspace()
$PowerShell = [powershell]::Create()
$PowerShell.Runspace = $Runspace
$Runspace.Open()
$PowerShell.AddScript({Connect-AZAccount})
$PowerShell.Invoke()
[System.Windows.Forms.Application]::DoEvents()
$Context = (Get-AzContext -ListAvailable | Where { $_.Account.Id -eq $user } | select -first 1)
}
$global:AzToken = ""
try
{
$Resource = '74658136-14ec-4630-ad9b-26e160ff0fc6'
$global:AzToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id, $null, "Never", $null, $Resource)
}
catch
{
Write-LogError "Failed to authenticate with Instance.AuthenticationFactory.Authenticate" $_.Exception
}
if(-not $global:AzToken)
{
Write-Log "Failed to authenticate" 3
}
else
{
Write-Log "Authenticated as $($global:AzToken.UserId)"
}
$global:AuthenticatedToAzure = $true
Set-MainTitle
}
# Invoke-AzureNativeRequest is based on the following project
# https://github.com/JustinGrote/Az.PortalAPI/tree/master/Az.PortalAPI
#
# Azure functions are based on: ???
#
# Some small changes:
# - Get-AzContext is based on the same user as Intune user
# - Renamed Invoke-Request to Invoke-AzureNativeRequest
# - Added support for HTTP Method PATCH
# - Added support for paging with nextLink (Lazy solution...not fully tested but looks like it is working)
# - Removed Token parameter. Created the Connect-AzureNative to get token
# - Removed Context parameter
function Invoke-AzureNativeRequest {
<#
.SYNOPSIS
@@ -19,7 +95,7 @@ function Invoke-AzureNativeRequest {
$Body,
#Specify the HTTP Method you wish to use. Defaults to GET
[ValidateSet("GET","POST","OPTIONS","DELETE", "PATCH", "PUT")]
[ValidateSet("GET","POST","OPTIONS","DELETE","PATCH")]
$Method = "GET",
#The base URI for the Portal API. Typically you don't need to change this
@@ -29,101 +105,76 @@ function Invoke-AzureNativeRequest {
#The request ID for the session. You can generate one with [guid]::NewGuid().guid.
#Typically you only specify this if you're trying to retry an operation and don't want to duplicate the request, such as for a POST operation
$requestID = [guid]::NewGuid().guid
$requestID = [guid]::NewGuid().guid,
[switch]$allowPaging
)
if(-not $global:AzToken -and $global:AuthenticatedToAzure -eq $false)
{
Connect-AzureNative $global:me.userPrincipalName
}
if(-not $global:AzToken)
{
return
}
#Combine the BaseURI and Target
[String]$ApiAction = $Target.TrimStart('/')
if ($Action)
{
if ($Action) {
$ApiAction = $ApiAction + '/' + $Action
}
if($global:tokresponse -and [DateTimeOffset]::Now.ToUnixTimeSeconds() -gt $global:tokresponse.expires_on)
$uriStr = "$baseURI$ApiAction"
if($allowPaging)
{
$global:tokresponse = $null
$uri = [Uri]::New("$uriStr&nextLink=null")
}
else
{
$uri = [Uri]::New($baseURI,$ApiAction)
}
$Context = Get-AzureRmContext
if(-not $context -or -not $global:tokresponse)
if(-not $global:AzToken.AccessToken.tostring())
{
if($Context)
{
if($global:Me -and $global:Organization)
{
$refreshToken = ($Context.TokenCache.ReadItems() | Where { $_.DisplayableId -eq $global:Me.userPrincipalName -and $_.TenantId -eq $global:Organization.Id }).RefreshToken
if($refreshToken -and $refreshToken.ExpiresOn -lt (Get-Date))
{
# Expired...force login
# $refreshToken = $null
}
}
}
if(-not $refreshToken)
{
$user = Connect-AzureRmAccount
if(-not $user) { return }
$Context = Get-AzureRmContext
if(-not $Context) { return }
}
}
#
if(-not $global:tokresponse)
{
$refreshToken = $null # Fore read again in case of login
if($global:Me -and $global:Organization)
{
$refreshToken = ($Context.TokenCache.ReadItems() | Where { $_.DisplayableId -eq $global:Me.userPrincipalName -and $_.TenantId -eq $global:Organization.Id }).RefreshToken
}
# Make sure we are using the same user as Intune login
if(-not $refreshToken)
{
[System.Windows.MessageBox]::Show("Failed to find login token for AzureRM", "Invalid AzureRM login!", "OK", "Error")
return $global:tokresponse
}
$curToken = $Context.TokenCache.ReadItems() | Where { $_.DisplayableId -eq $global:Me.userPrincipalName -and $_.TenantId -eq $global:Organization.Id }
$tenantid = $curToken.TenantId
$refreshToken = $curToken.RefreshToken
$loginUrl = "https://login.windows.net/$tenantid/oauth2/token"
$bodyTmp = "grant_type=refresh_token&refresh_token=$($refreshToken)" #&resource=74658136-14ec-4630-ad9b-26e160ff0fc6"
$response = Invoke-RestMethod $loginUrl -Method POST -Body $bodyTmp -ContentType 'application/x-www-form-urlencoded'
$global:tokresponse = Invoke-RestMethod $loginUrl -Method POST -Body ($bodyTmp + "&resource=74658136-14ec-4630-ad9b-26e160ff0fc6")
if(-not $global:tokresponse) { return }
Write-Log "No access token available" 3
return
}
$InvokeRestMethodParams = @{
Uri = [Uri]::New($baseURI,$ApiAction)
Uri = $uri
Method = $Method
Header = [ordered]@{
Authorization = 'Bearer ' + $global:tokresponse.access_token
Authorization = 'Bearer ' + $global:AzToken.AccessToken.tostring()
'Content-Type' = 'application/json'
'x-ms-client-request-id' = $requestID
'Host' = $baseURI.Host
'Origin' = $requestOrigin
'Origin' = 'https://iam.hosting.portal.azure.net'
}
Body = $Body
}
try
$max = 100
$cur = 0
$retObj = Invoke-RestMethod @InvokeRestMethodParams
if(($retObj | GM -MemberType NoteProperty -Name "nextLink"))
{
Invoke-RestMethod @InvokeRestMethodParams
if($? -eq $false)
while($retObj.nextLink)
{
throw $global:error[0]
# Get more objects
$InvokeRestMethodParams["Uri"] = [Uri]::New($uriStr + "&nextLink=" + $retObj.nextLink)
$retObj = Invoke-RestMethod @InvokeRestMethodParams
if($cur -ge $max) { break }
$cur++ # Loop gets stuck if nextLink=null is added to the command line so make sure it doesn't hang forever
}
}
}
catch
{
Write-LogError "Failed to invoke Invoke-RestMethod for Azure" $_.Exception
}
$retObj
}
function Get-AzureNativeObjects
@@ -135,10 +186,11 @@ function Get-AzureNativeObjects
$property,
[Array]
$exclude,
$SortProperty = "")
$SortProperty = "",
[switch]$allowPaging)
$objects = @()
$nativeObjects =Invoke-AzureNativeRequest $Target
$nativeObjects = Invoke-AzureNativeRequest $Target -allowPaging:($allowPaging -eq $true)
if(($nativeObjects | GM -Name "items"))
{

View File

@@ -188,7 +188,7 @@ function Import-IntuneBranding
{
param($obj)
Remove-ObjectProperty $obj "@odata.context"
Start-PreImport $obj -RemoveProperties @("@odata.context")
$newObject = @"
{

View File

@@ -201,6 +201,8 @@ function Import-CompliancePolicy
{
param($obj)
Start-PreImport $obj
$json = ConvertTo-Json $obj -Depth 5
$json = $json.Trim().TrimEnd('}').Trim()
$json += @"

View File

@@ -105,7 +105,7 @@ function Get-ConditionalAccess
function Get-ConditionalAccessObjects
{
#https://main.iam.ad.ext.azure.com/api/Policies/Policies?top=10&nextLink=null&appId=&includeBaseline=true
Get-AzureNativeObjects "Policies/Policies?top=10&nextLink=null&appId=&includeBaseline=true" -property @('policyName')
Get-AzureNativeObjects "Policies/Policies?top=10&appId=&includeBaseline=true" -property @('policyName') -allowPaging
}
function Get-ConditionalAccessObject
@@ -214,6 +214,8 @@ function Import-ConditionalAccess
{
param($obj)
Start-PreImport $obj
$json = Update-JsonForEnvironment $json
if($obj.baselineType -eq 0)

View File

@@ -206,14 +206,10 @@ function Import-DeviceConfiguration
{
param($obj)
if(($obj | GM -MemberType NoteProperty -Name "supportsScopeTags"))
{
# Remove read-only property
$obj.PSObject.Properties.Remove('supportsScopeTags')
}
Write-Status "Import $($obj.displayName)"
Start-PreImport $obj
Invoke-GraphRequest -Url "/deviceManagement/deviceConfigurations" -Content (ConvertTo-Json $obj -Depth 5) -HttpMethod POST
}

View File

@@ -222,6 +222,8 @@ function Import-ESP
{
param($obj)
Start-PreImport $obj
if($obj.id -like "*_default*")
{
Write-Status "Update $($obj.displayName)"

View File

@@ -261,6 +261,8 @@ function Import-GPOSetting
Write-Status "Import $($obj.displayName)"
Start-PreImport $obj
# Import Administrative Template profile
$response = Invoke-GraphRequest -Url "/deviceManagement/groupPolicyConfigurations" -Content (ConvertTo-Json $obj -Depth 5) -HttpMethod POST
@@ -268,6 +270,8 @@ function Import-GPOSetting
{
foreach($setting in $settings)
{
Start-PreImport $setting
# Import each setting for the Administrative Template profile
$response2 = Invoke-GraphRequest -Url "/deviceManagement/groupPolicyConfigurations/$($response.id)/definitionValues" -Content (ConvertTo-Json $setting -Depth 5) -HttpMethod POST
}

View File

@@ -3,33 +3,34 @@ function Invoke-InitializeModule
$module = Get-Module -Name Microsoft.Graph.Intune -ListAvailable
if(-not $module)
{
$ret = [System.Windows.MessageBox]::Show("Intune PowerShell module not found!`n`nDo you want to install it?`n`nYes = Install intune module (Requires admin or it will fail)`nNo = Contune without module (No Azure modules will be loaded)`nCancel = Quit", "Error", "YesNoCancel", "Error")
if($ret -eq "Yes")
$ret = [System.Windows.MessageBox]::Show("Intune PowerShell module not found!`n`nDo you want to install it as admin?`n`nYes = Install intune module as Admin (Requires admin or it will fail)`nNo = Install module for current user`nCancel = Quit", "Error", "YesNoCancel", "Error")
if($ret -eq "Cancel")
{
exit
}
$params = @{}
if($ret -eq "No")
{
$params.Add("Scope", "CurrentUser")
}
try
{
Install-Module -Name Microsoft.Graph.Intune -Force -ErrorAction SilentlyContinue
Install-Module -Name Microsoft.Graph.Intune -Force -ErrorAction SilentlyContinue @params
}
catch {}
if(-not (Get-Module -Name Microsoft.Graph.Intune -ListAvailable -Refresh))
{
[System.Windows.MessageBox]::Show("Failed to install Intune PowerShell module!`n`nRestart this as admin and try again`nor`nStart PowerShell as admin and run:`nInstall-Module -Name Microsoft.Graph.Intune", "Error", "OK", "Error")
exit
}
}
elseif($ret -eq "Cancel")
{
exit
}
else
{
return
}
}
if(-not $global:authentication)
{
if((Get-Command Connect-MSGraph))
if((Get-Command Connect-MSGraph -ErrorAction SilentlyContinue))
{
$global:authentication = Connect-MSGraph -PassThru
}
@@ -41,6 +42,7 @@ function Invoke-InitializeModule
return
}
Write-Log "Get current user"
$global:Me = Invoke-GraphRequest "ME"
if(-not $global:Me)
@@ -48,6 +50,8 @@ function Invoke-InitializeModule
[System.Windows.MessageBox]::Show("Failed to get information about current logged on Azure user!`n`nVerify connection and try again`n`nNo Intune modules will be imported!", "Error", "OK", "Error")
return
}
Write-Log "Get organization info"
$global:Organization = (Invoke-GraphRequest "Organization").Value
$global:graphURL = "https://graph.microsoft.com/beta"
@@ -59,6 +63,8 @@ function Invoke-InitializeModule
Values = @()
})
Write-Log "Add settings and menu items"
Add-SettingsObject (New-Object PSObject -Property @{
Title = "Root folder"
Key = "IntuneRootFolder"
@@ -76,6 +82,7 @@ function Invoke-InitializeModule
Key = "AddObjectType"
Type = "Boolean"
DefaultValue = $true
Description = "Default setting for adding object type to the export folder"
}) "IntuneAzure"
Add-SettingsObject (New-Object PSObject -Property @{
@@ -83,6 +90,7 @@ function Invoke-InitializeModule
Key = "AddCompanyName"
Type = "Boolean"
DefaultValue = $true
Description = "Default setting for adding company name to the export folder"
}) "IntuneAzure"
Add-SettingsObject (New-Object PSObject -Property @{
@@ -90,6 +98,7 @@ function Invoke-InitializeModule
Key = "ExportIntuneAssignments"
Type = "Boolean"
DefaultValue = $true
Description = "Default setting for exporting assignments"
}) "IntuneAzure"
Add-SettingsObject (New-Object PSObject -Property @{
@@ -97,6 +106,7 @@ function Invoke-InitializeModule
Key = "CreateIntuneGroupOnImport"
Type = "Boolean"
DefaultValue = $true
Description = "Default setting for creating groups during import"
}) "IntuneAzure"
Add-SettingsObject (New-Object PSObject -Property @{
@@ -104,6 +114,7 @@ function Invoke-InitializeModule
Key = "ConvertIntuneSyncedGroupOnImport"
Type = "Boolean"
DefaultValue = $true
Description = "Convert AD synched groups to Azure AD group during import if the group does not exist"
}) "IntuneAzure"
Add-SettingsObject (New-Object PSObject -Property @{
@@ -179,7 +190,6 @@ $xmlStr = @"
</StackPanel>
<CheckBox Grid.Column='1' Grid.Row='1' Name='chkAddObjectType' VerticalAlignment="Center" IsEnabled="false" IsChecked="true" />
<StackPanel Orientation="Horizontal" Grid.Row='2' Margin="0,0,5,0">
<Label Content="Add company name to path" />
<Rectangle Style="{DynamicResource InfoIcon}" ToolTip="This will add the company name in Azure to the export path" />
@@ -1576,3 +1586,29 @@ function Get-GraphAssignmentsObject
$tmpAssignments
}
#region Policy Functions
function Start-PreImport
{
param($obj, $removeProperties = @())
foreach($removeProp in @('lastModifiedDateTime','createdDateTime','supportsScopeTags','id'))
{
if($removeProperties -notcontains $removeProp)
{
$removeProperties += $removeProp
}
}
foreach($prop in $removeProperties)
{
if(($obj | GM -MemberType NoteProperty -Name $prop))
{
Write-Log "Remove property $prop"
$obj.PSObject.Properties.Remove($prop)
}
}
}
#endregion

View File

@@ -243,11 +243,7 @@ function Import-PowerShellScript
{
param($obj)
Remove-ObjectProperty $obj "id"
Remove-ObjectProperty $obj "createdDateTime"
Remove-ObjectProperty $obj "lastModifiedDateTime"
Remove-ObjectProperty $obj "assignments@odata.context"
Remove-ObjectProperty $obj "assignments"
Start-PreImport $obj -RemoveProperties @("id","assignments@odata.context","assignments")
Write-Status "Import $($obj.displayName)"

View File

@@ -210,6 +210,8 @@ function Import-TermsAndCondition
Write-Status "Import $($obj.displayName)"
Start-PreImport $obj
Invoke-GraphRequest -Url "/deviceManagement/termsAndConditions" -Content (ConvertTo-Json $obj -Depth 5) -HttpMethod POST
}

View File

@@ -97,7 +97,7 @@ function global:Write-LogError
{
param($Text, $Exception)
if($Text)
if($Text -and $Exception.message)
{
$Text += " Exception: $($Exception.message)"
}
@@ -532,6 +532,12 @@ function global:Add-SettingValue
$settingObj = Add-SettingTextBox $id $value
}
$descriptionInfo = ""
if($settingValue.Description)
{
$descriptionInfo = "<Rectangle Style=`"{DynamicResource InfoIcon}`" ToolTip=`"$($settingValue.Description)`" Margin=`"5,0,0,0`" />"
}
$xaml = @"
<Border Margin="0,5,0,0" $wpfNS>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
@@ -544,8 +550,13 @@ function global:Add-SettingValue
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Margin="5,0,5,0">
<TextBlock Text="$($settingValue.Title)" VerticalAlignment="Center"/>
$descriptionInfo
</StackPanel>
<!--
<TextBlock Text="$($settingValue.Title)" VerticalAlignment="Center" Margin="5,0,0,0" />
-->
<Border Grid.Column="2" Name="border_$($id)" />
</Grid>
@@ -873,15 +884,23 @@ function global:Add-MenuItem
function global:Invoke-ModuleFunction
{
param($funtion)
param($function)
Write-Log "Trigger function $function"
foreach($module in $global:loadedModules)
{
# Get command with ExportedFunctions instead of Get-Command
$cmd = $module.ExportedFunctions[$funtion]
$cmd = $module.ExportedFunctions[$function]
if($cmd)
{
Write-Log "Trigger $function in $($module.Name)"
Invoke-Command -ScriptBlock $cmd.ScriptBlock
}
else
{
#Write-Log "$function not found in $($module.Name)" 2
}
}
}
@@ -905,6 +924,12 @@ function global:Initialize-Menu
Script = [ScriptBlock]{ Show-AboutDialog }
})
Add-MenuItem (New-Object PSObject -Property @{
Title = 'Reload'
MenuID = "General"
ShowForm = $false
Script = [ScriptBlock]{ Start-Reload }
})
Add-MenuItem (New-Object PSObject -Property @{
Title = 'Exit'
@@ -956,6 +981,38 @@ public static extern IntPtr GetConsoleWindow();
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
function global:Set-MainTitle
{
if(-not $global:window) { return }
Write-Log "Set main title"
$mainTitle = $title
try
{
if($global:Me.userPrincipalName)
{
$IntuneId = $global:Me.userPrincipalName
$mainTitle += " - IntuneGraph: $($global:Me.userPrincipalName)"
}
}
catch {}
try
{
$ctx = Get-AzContext -ErrorAction SilentlyContinue
if($ctx.Account.Id)
{
$azureADId = $ctx.Account.Id
$mainTitle += " - AzureAD: $($ctx.Account.Id)"
}
}
catch {}
$global:window.Title = $mainTitle
}
function Show-Console
{
$consolePtr = [Console.Window]::GetConsoleWindow()
@@ -984,6 +1041,68 @@ function Hide-Console
[Console.Window]::ShowWindow($consolePtr, 0)
}
#endregion
#region Module functions
function Import-AllModules
{
foreach($file in (Get-Item -path "$modulesPath\*.psm1"))
{
$module = Import-Module $file -PassThru -Force -ErrorAction SilentlyContinue
if($module)
{
$global:loadedModules += $module
Write-Host "Module $($module.Name) loaded successfully"
}
else
{
Write-Warning "Failed to load module $file"
}
}
}
function Start-Reload
{
if([System.Windows.MessageBox]::Show("Are you sure you want to reload all modules and settings?", "Exit?", "YesNo", "Question") -eq "No")
{
return
}
Write-Status "Reloading modules"
$global:menuObjects = @()
$tmpList = @()
$spMenu.Children.Clear()
foreach($tmpModule in $global:loadedModules)
{
Remove-Module $tmpModule
$module = Import-Module $tmpModule.Path -PassThru -Force -ErrorAction SilentlyContinue
if($module)
{
$tmpList += $module
Write-Host "Module $($module.Name) loaded successfully"
}
else
{
Write-Warning "Failed to load module $file"
}
}
$global:loadedModules = $tmpList
Add-DefaultSettings
Invoke-ModuleFunction "Invoke-InitializeModule"
Initialize-Menu
Write-Status ""
}
#endregion
#####################################################################################################
@@ -1113,25 +1232,14 @@ $global:menuObjects = @()
# Load all modules in the Modules folder
$modulesPath = [IO.Path]::GetDirectoryName($PSCommandPath) + "\Extensions"
if(Test-Path $modulesPath)
{
foreach($file in (Get-Item -path "$modulesPath\*.psm1"))
{
$module = Import-Module $file -PassThru -Force -ErrorAction SilentlyContinue
if($module)
{
$global:loadedModules += $module
Write-Host "Module $($module.Name) loaded successfully"
Import-AllModules
}
else
{
Write-Warning "Failed to load module $file"
}
}
}
else
{
Write-Warning "Modules folder $modulesPath not wound. Aborting..." 3
Write-Warning "Modules folder $modulesPath not found. Aborting..." 3
exit 1
}
@@ -1149,6 +1257,8 @@ if($ShowConsoleWindow -ne $true)
Hide-Console
}
Set-MainTitle
# Show main window
# Workaround for ISE crash
# https://gist.github.com/altrive/6227237

View File

@@ -57,8 +57,6 @@ The script will create a group if it is missing in the destination environment.
Download [Microsoft.WindowsAPICodePack](https://www.nuget.org/packages/WindowsAPICodePack-Core) and [Microsoft.WindowsAPICodePack.Shell](https://www.nuget.org/packages/WindowsAPICodePack-Shell) and copy the DLLs into the script folder to get a nicer folder dialog.
If you want to test co-management and/or sync with on-prem AD, you can download [DeleMate](http://delemate.com). This tool can install anything from an AD-only environment to a complete SCCM environment in a quick and easy way. If you have a public domain registered, you can then install the AD domain with that name and add that domain to a test Azure environment and then configure AAD Sync and co-managment.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details