diff --git a/Extensions/AppProtection.psm1 b/Extensions/AppProtection.psm1
index 4a3e463..7fedeff 100644
--- a/Extensions/AppProtection.psm1
+++ b/Extensions/AppProtection.psm1
@@ -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)"
diff --git a/Extensions/Apps.psm1 b/Extensions/Apps.psm1
index 2619986..52b15b1 100644
--- a/Extensions/Apps.psm1
+++ b/Extensions/Apps.psm1
@@ -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)"
diff --git a/Extensions/AutoPilot.psm1 b/Extensions/AutoPilot.psm1
index 3db94d1..20c4409 100644
--- a/Extensions/AutoPilot.psm1
+++ b/Extensions/AutoPilot.psm1
@@ -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
}
diff --git a/Extensions/AzureNative.psm1 b/Extensions/AzureNative.psm1
index 553fd72..9f61227 100644
--- a/Extensions/AzureNative.psm1
+++ b/Extensions/AzureNative.psm1
@@ -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"))
{
diff --git a/Extensions/Branding.psm1 b/Extensions/Branding.psm1
index ec20ce4..70120fa 100644
--- a/Extensions/Branding.psm1
+++ b/Extensions/Branding.psm1
@@ -188,7 +188,7 @@ function Import-IntuneBranding
{
param($obj)
- Remove-ObjectProperty $obj "@odata.context"
+ Start-PreImport $obj -RemoveProperties @("@odata.context")
$newObject = @"
{
diff --git a/Extensions/CompliancePolicies.psm1 b/Extensions/CompliancePolicies.psm1
index 29a66bc..fa2a53b 100644
--- a/Extensions/CompliancePolicies.psm1
+++ b/Extensions/CompliancePolicies.psm1
@@ -201,6 +201,8 @@ function Import-CompliancePolicy
{
param($obj)
+ Start-PreImport $obj
+
$json = ConvertTo-Json $obj -Depth 5
$json = $json.Trim().TrimEnd('}').Trim()
$json += @"
diff --git a/Extensions/ConditionalAccess.psm1 b/Extensions/ConditionalAccess.psm1
index d4aeec2..e285d1c 100644
--- a/Extensions/ConditionalAccess.psm1
+++ b/Extensions/ConditionalAccess.psm1
@@ -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)
diff --git a/Extensions/ConfigurationItems.psm1 b/Extensions/ConfigurationItems.psm1
index cff05cd..7443aa0 100644
--- a/Extensions/ConfigurationItems.psm1
+++ b/Extensions/ConfigurationItems.psm1
@@ -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
}
diff --git a/Extensions/EnrollmentStatusPage.psm1 b/Extensions/EnrollmentStatusPage.psm1
index 8b0f730..0c85d51 100644
--- a/Extensions/EnrollmentStatusPage.psm1
+++ b/Extensions/EnrollmentStatusPage.psm1
@@ -222,6 +222,8 @@ function Import-ESP
{
param($obj)
+ Start-PreImport $obj
+
if($obj.id -like "*_default*")
{
Write-Status "Update $($obj.displayName)"
diff --git a/Extensions/GroupPolicy.psm1 b/Extensions/GroupPolicy.psm1
index 543c0e4..5211b1a 100644
--- a/Extensions/GroupPolicy.psm1
+++ b/Extensions/GroupPolicy.psm1
@@ -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
}
diff --git a/Extensions/MSGraphIntune.psm1 b/Extensions/MSGraphIntune.psm1
index fa0b866..51095af 100644
--- a/Extensions/MSGraphIntune.psm1
+++ b/Extensions/MSGraphIntune.psm1
@@ -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")
- {
- try
- {
- Install-Module -Name Microsoft.Graph.Intune -Force -ErrorAction SilentlyContinue
- }
- 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")
+ $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
}
- else
+
+ $params = @{}
+ if($ret -eq "No")
{
- return
+ $params.Add("Scope", "CurrentUser")
+ }
+
+ try
+ {
+ 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
}
}
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 @{
@@ -178,7 +189,6 @@ $xmlStr = @"
-
@@ -1575,4 +1585,30 @@ function Get-GraphAssignmentsObject
}
$tmpAssignments
-}
\ No newline at end of file
+}
+
+#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
diff --git a/Extensions/PowerShellScripts.psm1 b/Extensions/PowerShellScripts.psm1
index 15c98d0..6bd6976 100644
--- a/Extensions/PowerShellScripts.psm1
+++ b/Extensions/PowerShellScripts.psm1
@@ -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)"
diff --git a/Extensions/TermsAndConditions.psm1 b/Extensions/TermsAndConditions.psm1
index 5e6eccb..2a99949 100644
--- a/Extensions/TermsAndConditions.psm1
+++ b/Extensions/TermsAndConditions.psm1
@@ -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
}
diff --git a/PSExtensionsHost.ps1 b/PSExtensionsHost.ps1
index bff1711..b906d8e 100644
--- a/PSExtensionsHost.ps1
+++ b/PSExtensionsHost.ps1
@@ -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 = ""
+ }
+
$xaml = @"
@@ -544,8 +550,13 @@ function global:Add-SettingValue
+
+
+ $descriptionInfo
+
+
@@ -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"
- }
- else
- {
- Write-Warning "Failed to load module $file"
- }
- }
+{
+ Import-AllModules
}
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
diff --git a/README.md b/README.md
index fe95646..7e92918 100644
--- a/README.md
+++ b/README.md
@@ -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