diff --git a/Documentation/Strings-cs.json b/Documentation/Strings-cs.json
index 48352b0..0a5703c 100644
Binary files a/Documentation/Strings-cs.json and b/Documentation/Strings-cs.json differ
diff --git a/Documentation/Strings-de.json b/Documentation/Strings-de.json
index 868877f..7c78460 100644
Binary files a/Documentation/Strings-de.json and b/Documentation/Strings-de.json differ
diff --git a/Documentation/Strings-en.json b/Documentation/Strings-en.json
index bfc02a5..1866929 100644
Binary files a/Documentation/Strings-en.json and b/Documentation/Strings-en.json differ
diff --git a/Documentation/Strings-es.json b/Documentation/Strings-es.json
index d2d08c6..c2fb9ee 100644
Binary files a/Documentation/Strings-es.json and b/Documentation/Strings-es.json differ
diff --git a/Documentation/Strings-fr.json b/Documentation/Strings-fr.json
index 75a50c1..083b609 100644
Binary files a/Documentation/Strings-fr.json and b/Documentation/Strings-fr.json differ
diff --git a/Documentation/Strings-hu.json b/Documentation/Strings-hu.json
index a1095ec..cf0f366 100644
Binary files a/Documentation/Strings-hu.json and b/Documentation/Strings-hu.json differ
diff --git a/Documentation/Strings-it.json b/Documentation/Strings-it.json
index e333743..0e95829 100644
Binary files a/Documentation/Strings-it.json and b/Documentation/Strings-it.json differ
diff --git a/Documentation/Strings-ja.json b/Documentation/Strings-ja.json
index b280aad..cdf5eff 100644
Binary files a/Documentation/Strings-ja.json and b/Documentation/Strings-ja.json differ
diff --git a/Documentation/Strings-ko.json b/Documentation/Strings-ko.json
index ae3b733..a7260d8 100644
Binary files a/Documentation/Strings-ko.json and b/Documentation/Strings-ko.json differ
diff --git a/Documentation/Strings-nl.json b/Documentation/Strings-nl.json
index 99f475f..96a5817 100644
Binary files a/Documentation/Strings-nl.json and b/Documentation/Strings-nl.json differ
diff --git a/Documentation/Strings-pl.json b/Documentation/Strings-pl.json
index 53dff3b..771ccad 100644
Binary files a/Documentation/Strings-pl.json and b/Documentation/Strings-pl.json differ
diff --git a/Documentation/Strings-pt.json b/Documentation/Strings-pt.json
index bfc02a5..1866929 100644
Binary files a/Documentation/Strings-pt.json and b/Documentation/Strings-pt.json differ
diff --git a/Documentation/Strings-ru.json b/Documentation/Strings-ru.json
index fd57e77..d61d861 100644
Binary files a/Documentation/Strings-ru.json and b/Documentation/Strings-ru.json differ
diff --git a/Documentation/Strings-sv.json b/Documentation/Strings-sv.json
index 201808b..19f9677 100644
Binary files a/Documentation/Strings-sv.json and b/Documentation/Strings-sv.json differ
diff --git a/Documentation/Strings-tr.json b/Documentation/Strings-tr.json
index 6846c4e..316cd22 100644
Binary files a/Documentation/Strings-tr.json and b/Documentation/Strings-tr.json differ
diff --git a/Documentation/Strings-zh-chs.json b/Documentation/Strings-zh-chs.json
index bfc02a5..1866929 100644
Binary files a/Documentation/Strings-zh-chs.json and b/Documentation/Strings-zh-chs.json differ
diff --git a/Documentation/Strings-zh-cht.json b/Documentation/Strings-zh-cht.json
index bfc02a5..1866929 100644
Binary files a/Documentation/Strings-zh-cht.json and b/Documentation/Strings-zh-cht.json differ
diff --git a/Documentation/Strings-zh-hans.json b/Documentation/Strings-zh-hans.json
index 7f27b79..8123632 100644
Binary files a/Documentation/Strings-zh-hans.json and b/Documentation/Strings-zh-hans.json differ
diff --git a/Documentation/Strings-zh-hant.json b/Documentation/Strings-zh-hant.json
index 404e2bc..661e0bc 100644
Binary files a/Documentation/Strings-zh-hant.json and b/Documentation/Strings-zh-hant.json differ
diff --git a/Documentation/Strings-zh.json b/Documentation/Strings-zh.json
index bfc02a5..1866929 100644
Binary files a/Documentation/Strings-zh.json and b/Documentation/Strings-zh.json differ
diff --git a/Extensions/Documentation.psm1 b/Extensions/Documentation.psm1
index 00ce48a..2cdb46b 100644
--- a/Extensions/Documentation.psm1
+++ b/Extensions/Documentation.psm1
@@ -20,7 +20,7 @@ $global:documentationProviders = @()
function Get-ModuleVersion
{
- '1.0.4'
+ '1.0.5'
}
function Invoke-InitializeModule
@@ -57,6 +57,16 @@ function Invoke-ShowMainWindow
$global:spSubMenu.Children.Insert(0, $button)
}
+function Invoke-GraphObjectsChanged
+{
+ $btnDocument = $global:spSubMenu.Children | Where-Object { $_.Name -eq "btnDocument" }
+ $btnExport = $global:spSubMenu.Children | Where-Object { $_.Name -eq "btnExport" }
+ if($btnDocument -and $btnExport)
+ {
+ $btnDocument.Visibility = $btnExport.Visibility
+ }
+}
+
function Invoke-ViewActivated
{
if($global:currentViewObject.ViewInfo.ID -ne "IntuneGraphAPI") { return }
@@ -2889,7 +2899,22 @@ function Invoke-TranslateAssignments
{
if(($assignment.settings.PSObject.Properties | Where Name -eq $settingProp))
{
- $assignmentSettingProps.Add($settingProp, $assignment.settings.$settingProp)
+ if($settingProp -eq "useDeviceLicensing")
+ {
+ if($assignment.settings.$settingProp -eq $true)
+ {
+ $value = Get-LanguageString "SettingDetails.licenseTypeDevice"
+ }
+ else
+ {
+ $value = Get-LanguageString "SettingDetails.licenseTypeUser"
+ }
+ }
+ else
+ {
+ $value = $assignment.settings.$settingProp
+ }
+ $assignmentSettingProps.Add($settingProp, $value)
}
}
}
diff --git a/Extensions/DocumentationWord.psm1 b/Extensions/DocumentationWord.psm1
index a778f55..2f83954 100644
--- a/Extensions/DocumentationWord.psm1
+++ b/Extensions/DocumentationWord.psm1
@@ -3,7 +3,7 @@
#https://docs.microsoft.com/en-us/office/vba/api/overview/word
function Get-ModuleVersion
{
- '1.0.1'
+ '1.0.2'
}
function Invoke-InitializeModule
@@ -53,6 +53,10 @@ function Invoke-InitializeModule
Status="TableHeaders.status"
CombinedValueWithLabel="TableHeaders.value"
CombinedValue="TableHeaders.value"
+ useDeviceLicensing="TableHeaders.licenseType"
+ #filterMode="Filter mode" # Not in any sring file yet
+
+
}
}
diff --git a/Extensions/EndpointManager.psm1 b/Extensions/EndpointManager.psm1
index b086a72..5ffeb26 100644
--- a/Extensions/EndpointManager.psm1
+++ b/Extensions/EndpointManager.psm1
@@ -10,7 +10,7 @@ This module is for the Endpoint Manager/Intune View. It manages Export/Import/Co
#>
function Get-ModuleVersion
{
- '3.1.7'
+ '3.1.8'
}
function Invoke-InitializeModule
@@ -83,7 +83,7 @@ function Invoke-InitializeModule
Description = "Manages Intune environments. This view can be used for copying objects in an Intune environment. It can also be used for backing up an entire Intune environment and cloning the Intune environment into another tenant."
ID="IntuneGraphAPI"
ViewPanel = $viewPanel
- ItemChanged = { Show-GraphObjects; Write-Status ""}
+ ItemChanged = { Show-GraphObjects; Invoke-ModuleFunction "Invoke-GraphObjectsChanged"; Write-Status ""}
Deactivating = { Invoke-EMDeactivateView }
Activating = { Invoke-EMActivatingView }
Authentication = (Get-MSALAuthenticationObject)
@@ -172,9 +172,11 @@ function Invoke-InitializeModule
PostGetCommand = { Start-PostGetIntuneBranding @args }
PostExportCommand = { Start-PostExportIntuneBranding @args }
PreDeleteCommand = { Start-PreDeleteIntuneBranding @args }
+ PreUpdateCommand = { Start-PreUpdateIntuneBranding @args }
Permissons=@("DeviceManagementApps.ReadWrite.All")
Icon = "Branding"
SkipRemoveProperties = @('Id') # Id is removed by PreImport. Required for default profile
+ PropertiesToRemoveForUpdate = @('isDefaultProfile','disableClientTelemetry')
GroupId = "TenantAdmin"
})
@@ -212,10 +214,12 @@ function Invoke-InitializeModule
PreReplaceCommand = { Start-PreReplaceEnrollmentRestrictions @args } # Note: Uses same PreReplaceCommand as restrictions
PostReplaceCommand = { Start-PostReplaceEnrollmentRestrictions @args } # Note: Uses same PostReplaceCommand as restrictions
PreFilesImportCommand = { Start-PreFilesImportEnrollmentRestrictions @args } # Note: Uses same PreFilesImportCommand as restrictions
+ #PreUpdateCommand = { Start-PreUpdateEnrollmentRestrictions @args } # Note: Uses same PreUpdateCommand as restrictions
QUERYLIST = "`$filter=endsWith(id,'Windows10EnrollmentCompletionPageConfiguration')"
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
SkipRemoveProperties = @('Id')
AssignmentsType = "enrollmentConfigurationAssignments"
+ PropertiesToRemoveForUpdate = @('priority')
GroupId = "WinEnrollment"
})
@@ -231,6 +235,8 @@ function Invoke-InitializeModule
PreReplaceCommand = { Start-PreReplaceEnrollmentRestrictions @args }
PostReplaceCommand = { Start-PostReplaceEnrollmentRestrictions @args }
PreFilesImportCommand = { Start-PreFilesImportEnrollmentRestrictions @args }
+ #PreUpdateCommand = { Start-PreUpdateEnrollmentRestrictions @args }
+ PropertiesToRemoveForUpdate = @('priority')
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
SkipRemoveProperties = @('Id')
AssignmentsType = "enrollmentConfigurationAssignments"
@@ -292,6 +298,8 @@ function Invoke-InitializeModule
Icon="CustomAttributes"
GroupId = "CustomAttributes" # MacOS Settings
DetailExtension = { Add-ScriptExtensions @args }
+ PropertiesToRemoveForUpdate = @('customAttributeName','customAttributeType','displayName')
+ #PreUpdateCommand = { Start-PreUpdateMacCustomAttributes @args }
})
Add-ViewItem (New-Object PSObject -Property @{
@@ -316,8 +324,10 @@ function Invoke-InitializeModule
PreImportCommand = { Start-PreImportAppProtection @args }
PostImportCommand = { Start-PostImportAppProtection @args }
PreImportAssignmentsCommand = { Start-PreImportAssignmentsAppProtection @args }
+ PreUpdateCommand = { Start-PreUpdateAppProtection @args }
ExportFullObject = $true
PropertiesToRemove = @('exemptAppLockerFiles')
+ PropertiesToRemoveForUpdate = @("protectedAppLockerFiles","version") # ToDo: !!! Add support for protectedAppLockerFiles?
Permissons=@("DeviceManagementApps.ReadWrite.All")
Dependencies = @("Applications")
GroupId = "AppProtection"
@@ -334,6 +344,7 @@ function Invoke-InitializeModule
PreImportCommand = { Start-PreImportAppProtection @args }
PostImportCommand = { Start-PostImportAppProtection @args }
PreImportAssignmentsCommand = { Start-PreImportAssignmentsAppProtection @args }
+ PreUpdateCommand = { Start-PreUpdateAppConfigurationApp @args }
Permissons=@("DeviceManagementApps.ReadWrite.All")
Dependencies = @("Applications")
Icon = "AppConfiguration"
@@ -369,6 +380,7 @@ function Invoke-InitializeModule
Expand="categories,assignments" # ODataMetadata is set to minimal so assignments can't be autodetected
ODataMetadata="minimal" # categories property not supported with ODataMetadata full
PostFileImportCommand = { Start-PostFileImportApplications @args }
+ PreUpdateCommand = { Start-PreUpdateApplication @args }
GroupId = "Apps"
})
@@ -392,6 +404,7 @@ function Invoke-InitializeModule
Expand = "Items"
PreImportAssignmentsCommand = { Start-PreImportAssignmentsPolicySets @args }
PreImportCommand = { Start-PreImportPolicySets @args }
+ PreUpdateCommand = { Start-PreUpdatePolicySets @args }
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
ImportOrder = 2000 # Policy Sets reference other objects so make sure it is imported last
Dependencies = @("Applications","AppConfiguration","AppProtection","AutoPilot","EnrollmentRestrictions","EnrollmentStatusPage","DeviceConfiguration","AdministrativeTemplates","SettingsCatalog","CompliancePolicies")
@@ -407,6 +420,7 @@ function Invoke-InitializeModule
#ExportFullObject = $false
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
GroupId = "WinUpdatePolicies"
+ PropertiesToRemoveForUpdate = @('version','qualityUpdatesPauseStartDate','featureUpdatesPauseStartDate','qualityUpdatesWillBeRolledBack','featureUpdatesWillBeRolledBack')
})
Add-ViewItem (New-Object PSObject -Property @{
@@ -416,6 +430,8 @@ function Invoke-InitializeModule
API = "/deviceManagement/windowsFeatureUpdateProfiles"
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
GroupId = "WinFeatureUpdates"
+ PropertiesToRemoveForUpdate = @('deployableContentDisplayName','endOfSupportDate')
+ #PreUpdateCommand = { Start-PreUpdateFeatureUpdates @args }
})
Add-ViewItem (New-Object PSObject -Property @{
@@ -426,6 +442,7 @@ function Invoke-InitializeModule
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
Icon = "UpdatePolicies"
GroupId = "WinQualityUpdates"
+ PropertiesToRemoveForUpdate = @('releaseDateDisplayName','deployableContentDisplayName')
})
# Locations are not FULLY supported
@@ -459,6 +476,7 @@ function Invoke-InitializeModule
Expand="Settings"
Icon="DeviceConfiguration"
PostExportCommand = { Start-PostExportSettingsCatalog @args }
+ PreUpdateCommand = { Start-PreUpdateSettingsCatalog @args }
GroupId = "DeviceConfiguration"
})
@@ -474,6 +492,7 @@ function Invoke-InitializeModule
Permissons=@("DeviceManagementRBAC.ReadWrite.All")
ImportOrder = 20
#expand=roleassignments
+ PropertiesToRemoveForUpdate = @('isBuiltInRoleDefinition','isBuiltIn','roleAssignments') ### !!! ToDo: Add support for roleAssignments
GroupId = "TenantAdmin"
})
@@ -500,6 +519,7 @@ function Invoke-InitializeModule
PreImportCommand = { Start-PreImportNotifications @args }
PostFileImportCommand = { Start-PostFileImportNotifications @args }
PostCopyCommand = { Start-PostCopyNotifications @args }
+ PropertiesToRemoveForUpdate = @('defaultLocale','localizedNotificationMessages') ### !!! ToDo: Add support for localizedNotificationMessages
GroupId = "CompliancePolicies"
})
@@ -527,6 +547,7 @@ function Invoke-InitializeModule
ViewID = "IntuneGraphAPI"
API = "/deviceManagement/appleUserInitiatedEnrollmentProfiles"
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
+ PropertiesToRemoveForUpdate = @('platform')
GroupId = "AppleEnrollment"
})
@@ -538,6 +559,7 @@ function Invoke-InitializeModule
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
ImportOrder = 15
GroupId = "TenantAdmin"
+ PropertiesToRemoveForUpdate = @('platform')
})
Add-ViewItem (New-Object PSObject -Property @{
@@ -547,10 +569,13 @@ function Invoke-InitializeModule
QUERYLIST = "`$filter=isGlobalScript%20eq%20false" # Looks like filters are not working for deviceHealthScripts
API = "/deviceManagement/deviceHealthScripts"
PreDeleteCommand = { Start-PreDeleteDeviceHealthScripts @args }
+ PreImportCommand = { Start-PreImportDeviceHealthScripts @args }
+ PreUpdateCommand = { Start-PreUpdateDeviceHealthScripts @args }
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
GroupId = "EndpointAnalytics"
Icon = "Report"
AssignmentsType = "deviceHealthScriptAssignments"
+ PropertiesToRemoveForUpdate = @('version','isGlobalScript','highestAvailableVersion')
})
}
@@ -694,6 +719,7 @@ function Set-EMViewPanel
# ToDo: Move this to view view object
$txtFilter = $this.Parent.FindName("txtFilter")
if($txtFilter) { $txtFilter.Text = "" }
+
Show-GraphObjects
Write-Status ""
})
@@ -783,7 +809,7 @@ function Start-PostExportEndpointSecurity
param($obj, $objectType, $path)
$settings = Invoke-GraphRequest -Url "$($objectType.API)/$($obj.id)/settings"
- $settingsJson = "{ `"settings`": $((ConvertTo-Json $settings.value -Depth 10 ))`n}"
+ $settingsJson = "{ `"settings`": $((ConvertTo-Json $settings.value -Depth 20 ))`n}"
$fileName = "$path\$((Remove-InvalidFileNameChars (Get-GraphObjectName $obj $objectType)))_Settings.json"
$settingsJson | Out-File -LiteralPath $fileName -Force
}
@@ -796,7 +822,7 @@ function Start-PostFileImportEndpointSecurity
if($settings)
{
Start-GraphPreImport $settings
- Invoke-GraphRequest -Url "$($objectType.API)/$($obj.id)/updateSettings" -Body ($settings | ConvertTo-Json -Depth 10) -Method "POST"
+ Invoke-GraphRequest -Url "$($objectType.API)/$($obj.id)/updateSettings" -Body ($settings | ConvertTo-Json -Depth 20) -Method "POST"
}
}
@@ -824,7 +850,7 @@ function Start-PostCopyEndpointSecurity
if($settings)
{
$settingsObj = New-object PSObject @{ "Settings" = $settings.Value }
- Invoke-GraphRequest -Url "$($objectType.API)/$($objNew.id)/updateSettings" -Body ($settingsObj | ConvertTo-Json -Depth 10) -Method "POST"
+ Invoke-GraphRequest -Url "$($objectType.API)/$($objNew.id)/updateSettings" -Body ($settingsObj | ConvertTo-Json -Depth 20) -Method "POST"
}
}
@@ -861,7 +887,7 @@ function Start-PreUpdateEndpointSecurity
$tmpObj = [PSCustomObject]@{
settings = $curValues
}
- $json = ConvertTo-Json $tmpObj -Depth 10
+ $json = ConvertTo-Json $tmpObj -Depth 20
# Set all existing values to null
# Note: This will not remove them from the configured list just set them Not Configured
@@ -874,7 +900,7 @@ function Start-PreUpdateEndpointSecurity
}
Start-GraphPreImport $tmpObj.settings
- $json = ConvertTo-Json $tmpObj -Depth 10
+ $json = ConvertTo-Json $tmpObj -Depth 20
Invoke-GraphRequest -Url $strAPI -Content $json -HttpMethod "POST" | Out-Null
Remove-Property $obj "templateId"
@@ -897,7 +923,7 @@ function Start-PostFileImportDeviceConfiguration
$privacyObj = [PSCustomObject]@{
windowsPrivacyAccessControls = $tmpObj.privacyAccessControls
}
- $json = $privacyObj | ConvertTo-Json -Depth 10
+ $json = $privacyObj | ConvertTo-Json -Depth 20
$ret = Invoke-GraphRequest -Url "deviceManagement/deviceConfigurations('$($obj.Id)')/windowsPrivacyAccessControls" -Body $json -Method "POST"
}
}
@@ -914,7 +940,7 @@ function Start-PostCopyDeviceConfiguration
$privacyObj = [PSCustomObject]@{
windowsPrivacyAccessControls = $objCopyFrom.privacyAccessControls
}
- $json = $privacyObj | ConvertTo-Json -Depth 10
+ $json = $privacyObj | ConvertTo-Json -Depth 20
$ret = Invoke-GraphRequest -Url "deviceManagement/deviceConfigurations('$($objNew.Id)')/windowsPrivacyAccessControls" -Body $json -Method "POST"
}
}
@@ -949,7 +975,7 @@ function Start-PreUpdateCompliancePolicies
deviceComplianceScheduledActionForRules = $obj.scheduledActionsForRule
}
- $json = ConvertTo-Json $tmpObj -Depth 10
+ $json = ConvertTo-Json $tmpObj -Depth 20
Invoke-GraphRequest -Url $strAPI -Content $json -HttpMethod "POST" | Out-Null
Remove-Property $obj "scheduledActionsForRule"
@@ -994,7 +1020,7 @@ function Start-PreImportIntuneBranding
# Create a new profile with basic info
# Patch the profile with all the info
- $global:brandingClone = $obj | ConvertTo-Json -Depth 10 | ConvertFrom-Json
+ $global:brandingClone = $obj | ConvertTo-Json -Depth 20 | ConvertFrom-Json
foreach($prop in ($obj.PSObject.Properties | Where {$_.Name -notin @("profileName","profileDescription","roleScopeTagIds")})) #"customPrivacyMessage"
{
@@ -1014,7 +1040,7 @@ function Start-PostImportIntuneBranding
{
Remove-Property $global:brandingClone $prop
}
- $json = ($global:brandingClone | ConvertTo-Json -Depth 10)
+ $json = ($global:brandingClone | ConvertTo-Json -Depth 20)
$ret = Invoke-GraphRequest -Url "$($objectType.API)/$($obj.Id)" -Body $json -Method "PATCH"
}
@@ -1057,6 +1083,19 @@ function Start-PreDeleteIntuneBranding
}
}
+function Start-PreUpdateIntuneBranding
+{
+ param($obj, $objectType, $curObject, $fromObj)
+
+ if($curObject.Object.isDefaultProfile)
+ {
+ foreach($prop in @("profileName","isDefaultProfile","disableClientTelemetry","profileDescription"))
+ {
+ Remove-Property $obj $prop
+ }
+ }
+}
+
#endregion
#region Azure Branding functions
@@ -1305,7 +1344,7 @@ function Start-PostImportAppProtection
$tmp = $newObject."@odata.type".Split('.')[-1]
$objectClass = Get-GraphObjectClassName $tmp
- Invoke-GraphRequest -Url "/deviceAppManagement/$objectClass/$($obj.Id)/targetApps" -Content "{ apps: $(ConvertTo-Json $global:ImportObjectInfo.Apps -Depth 10)}" -HttpMethod POST | Out-Null
+ Invoke-GraphRequest -Url "/deviceAppManagement/$objectClass/$($obj.Id)/targetApps" -Content "{ apps: $(ConvertTo-Json $global:ImportObjectInfo.Apps -Depth 20)}" -HttpMethod POST | Out-Null
}
catch {}
}
@@ -1322,6 +1361,71 @@ function Start-PreImportAssignmentsAppProtection
@{"API"="/deviceAppManagement/$($global:ImportObjectClass)/$($obj.Id)/assign"}
}
}
+
+function Start-PreUpdateAppConfigurationApp
+{
+ param($obj, $objectType, $curObject, $fromObj)
+
+ if($obj.Apps)
+ {
+ try
+ {
+ Write-Log "Update App Configuruation Apps"
+
+ $json = [PSCustomObject]@{ apps = @($obj.Apps) } | ConvertTo-Json -Depth 10
+ $objectClass = 'targetedManagedAppConfigurations' #!!!Get-GraphObjectClassName $obj
+
+ Invoke-GraphRequest -Url "/deviceAppManagement/$objectClass/$($curObject.Object.Id)/targetApps" -Content $json -HttpMethod POST | Out-Null
+ }
+ catch {}
+ }
+
+ Remove-Property $obj "apps"
+}
+
+function Start-PreUpdateAppProtection
+{
+ param($obj, $objectType, $curObject, $fromObj)
+
+ if($curObject.Object.'@OData.Type' -eq "#microsoft.graph.windowsInformationProtectionPolicy")
+ {
+ $api = "/deviceAppManagement/windowsInformationProtectionPolicies/$($curObject.Object.Id)"
+ }
+ elseif($curObject.Object.'@OData.Type' -eq "#microsoft.graph.mdmWindowsInformationProtectionPolicy")
+ {
+ $api = "/deviceAppManagement/mdmWindowsInformationProtectionPolicies/$($curObject.Object.Id)"
+ }
+ elseif($curObject.Object.'@OData.Type' -eq "#microsoft.graph.iosManagedAppProtection")
+ {
+ $api = "/deviceAppManagement/iosManagedAppProtections/$($curObject.Object.Id)"
+ }
+ elseif($curObject.Object.'@OData.Type' -eq "#microsoft.graph.androidManagedAppProtection")
+ {
+ $api = "/deviceAppManagement/androidManagedAppProtections/$($curObject.Object.Id)"
+ }
+ else
+ {
+ return (Start-PreUpdateAppConfigurationApp $obj $objectType $curObject $fromObj)
+ }
+
+ if($obj.Apps)
+ {
+ try
+ {
+ Write-Log "Update App Protection Apps"
+
+ $json = [PSCustomObject]@{ apps = @($obj.Apps) } | ConvertTo-Json -Depth 10
+
+ Invoke-GraphRequest -Url "$api/targetApps" -Content $json -HttpMethod POST | Out-Null
+ }
+ catch {}
+
+ Remove-Property $obj "apps"
+ }
+
+ @{ "API" = $api }
+
+}
#endregion
#region App Configuration
@@ -1397,6 +1501,26 @@ function Start-PostFileImportApplications
Write-Log "Unsupported application type $appType. File will not be uploaded" 2
}
}
+
+function Start-PreUpdateApplication
+{
+ param($obj, $objectType, $curObject, $fromObj)
+
+ if($curObject.Object.'@OData.type' -eq "#microsoft.graph.windowsMobileMSI")
+ {
+ Remove-Property $obj "useDeviceContext"
+ }
+ elseif($curObject.Object.'@OData.type' -eq "#microsoft.graph.officeSuiteApp")
+ {
+ Remove-Property $obj "officeConfigurationXml"
+ Remove-Property $obj "officePlatformArchitecture"
+ Remove-Property $obj "developer"
+ Remove-Property $obj "owner"
+ Remove-Property $obj "publisher"
+ }
+
+ Remove-Property $obj "appStoreUrl"
+}
#endregion
#region Group Policy/Administrative Templates functions
@@ -1459,7 +1583,7 @@ function Import-GPOSetting
Start-GraphPreImport $setting
# Import each setting for the Administrative Template profile
- Invoke-GraphRequest -Url "/deviceManagement/groupPolicyConfigurations/$($obj.id)/definitionValues" -Content (ConvertTo-Json $setting -Depth 10) -HttpMethod POST | Out-Null
+ Invoke-GraphRequest -Url "/deviceManagement/groupPolicyConfigurations/$($obj.id)/definitionValues" -Content (ConvertTo-Json $setting -Depth 20) -HttpMethod POST | Out-Null
}
}
}
@@ -1471,7 +1595,7 @@ function Start-PostExportAdministrativeTemplate
# Collect and save all the settings of the Administrative Templates profile
$settings = Get-GPOObjectSettings $obj
$fileName = "$path\$((Remove-InvalidFileNameChars (Get-GraphObjectName $obj $objectType)))_Settings.json"
- ConvertTo-Json $settings -Depth 10 | Out-File -LiteralPath $fileName -Force
+ ConvertTo-Json $settings -Depth 20 | Out-File -LiteralPath $fileName -Force
}
function Start-PostCopyAdministrativeTemplate
@@ -1573,6 +1697,58 @@ function Start-PreImportPolicySets
}
}
+function Start-PreUpdatePolicySets
+{
+ param($obj, $objectType, $curObject, $fromObj)
+
+ Start-PreImportPolicySets $obj $objectType
+
+ $curObject = Get-GraphObject $curObject.Object $objectType
+
+ # Update ref object in the json
+ # Used when importing in a different environment
+ $jsonObj = ConvertTo-Json $obj -Depth 15
+ $updateObj = Update-JsonForEnvironment $jsonObj | ConvertFrom-Json
+
+ $addedItems = @()
+ $updatedItems = @()
+ $deletedItems = @()
+
+ foreach($item in $updateObj.items)
+ {
+ if(($curObject.Object.items | Where payloadId -eq $item.payloadId))
+ {
+ $updatedItems += $item
+ }
+ else
+ {
+ $addedItems += $item
+ }
+ }
+
+ foreach($item in $curObject.Object.items)
+ {
+ if(-not ($updateObj.Items | Where payloadId -eq $item.payloadId))
+ {
+ $deletedItems += $item.id
+ }
+ }
+
+ $updateItemObj = [PSCustomObject]@{
+ addedPolicySetItems = $addedItems
+ deletedPolicySetItems = $deletedItems
+ updatedPolicySetItems = $updatedItems
+ }
+
+ Write-Log "Update Policy Set items. Add: $($addedItems.Count), Update: $($updatedItems.Count), Delete: $($deletedItems.Count)"
+
+ $updateApi = "/deviceAppManagement/policySets/$($curObject.Object.Id)/update"
+ $json = $updateItemObj | ConvertTo-Json -Depth 15
+
+ Invoke-GraphRequest -Url $updateApi -HttpMethod "POST" -Content $json
+ Remove-Property $obj "items"
+}
+
function Update-EMPolicySetAssignment
{
param($assignment, $sourceObject, $newObject, $objectType)
@@ -1595,8 +1771,8 @@ function Update-EMPolicySetAssignment
$api = "/deviceAppManagement/policySets/$($assignment.SourceId)/update"
- $curItemClone = $curItem | ConvertTo-Json -Depth 10 | ConvertFrom-Json
- $newItem = $curItem | ConvertTo-Json -Depth 10 | ConvertFrom-Json
+ $curItemClone = $curItem | ConvertTo-Json -Depth 20 | ConvertFrom-Json
+ $newItem = $curItem | ConvertTo-Json -Depth 20 | ConvertFrom-Json
$newItem.payloadId = $newObject.Id
if($newItem.guidedDeploymentTags -is [String] -and [String]::IsNullOrEmpty($newItem.guidedDeploymentTags))
{
@@ -1617,7 +1793,7 @@ function Update-EMPolicySetAssignment
$update.Add('updatedPolicySetItems', @())
$update.Add('deletedPolicySetItems',@($curItemClone.Id))
- $json = $update | ConvertTo-Json -Depth 10
+ $json = $update | ConvertTo-Json -Depth 20
Write-Log "Update PolicySet $($psObj.displayName) - Replace: $((Get-GraphObjectName $newObject $objectType))"
@@ -1668,7 +1844,7 @@ function Start-PostExportRoleDefinitions
if($roleAssignmentsArr.Count -gt 0)
{
$tmpObj.RoleAssignments = $roleAssignmentsArr
- $tmpObj | ConvertTo-Json -Depth 10 | Out-File -LiteralPath $fileName
+ $tmpObj | ConvertTo-Json -Depth 20 | Out-File -LiteralPath $fileName
}
}
}
@@ -1711,7 +1887,7 @@ function Start-PostFileImportRoleDefinitions
}
# This will update GroupIds
- $json = Update-JsonForEnvironment (ConvertTo-Json $roleAssignmentObj -Depth 10)
+ $json = Update-JsonForEnvironment (ConvertTo-Json $roleAssignmentObj -Depth 20)
Write-Log "Import Role Assignments"
Invoke-GraphRequest -Url "/deviceManagement/roleAssignments" -Body $json -Method "POST"
@@ -1728,6 +1904,13 @@ function Start-PostExportSettingsCatalog
Add-EMAssignmentsToExportFile $obj $objectType $path
}
+function Start-PreUpdateSettingsCatalog
+{
+ param($obj, $objectType, $curObject, $fromObj)
+
+ @{"Method"="PUT"}
+}
+
#endregion
#region Notification functions
@@ -1749,7 +1932,7 @@ function Start-PostFileImportNotifications
foreach($localizedNotificationMessage in $tmpObj.localizedNotificationMessages)
{
Start-GraphPreImport $localizedNotificationMessage $objectType
- Invoke-GraphRequest -Url "$($objectType.API)/$($obj.id)/localizedNotificationMessages" -Body ($localizedNotificationMessage | ConvertTo-Json -Depth 10) -Method "POST"
+ Invoke-GraphRequest -Url "$($objectType.API)/$($obj.id)/localizedNotificationMessages" -Body ($localizedNotificationMessage | ConvertTo-Json -Depth 20) -Method "POST"
}
}
@@ -1760,7 +1943,7 @@ function Start-PostCopyNotifications
foreach($localizedNotificationMessage in $objCopyFrom.localizedNotificationMessages)
{
Start-GraphPreImport $localizedNotificationMessage $objectType
- Invoke-GraphRequest -Url "$($objectType.API)/$($objNew.id)/localizedNotificationMessages" -Body ($localizedNotificationMessage | ConvertTo-Json -Depth 10) -Method "POST"
+ Invoke-GraphRequest -Url "$($objectType.API)/$($objNew.id)/localizedNotificationMessages" -Body ($localizedNotificationMessage | ConvertTo-Json -Depth 20) -Method "POST"
}
}
#endregion
@@ -1851,7 +2034,7 @@ function Start-PostReplaceEnrollmentRestrictions
$priority = [PSCustomObject]@{
priority = $sourceObj.Priority
}
- $json = $priority | ConvertTo-Json -Depth 10
+ $json = $priority | ConvertTo-Json -Depth 20
Write-Log "Update priority for $($obj.displayName) to $($sourceObj.Priority)"
Invoke-GraphRequest $api -HttpMethod "POST" -Content $json
@@ -1864,6 +2047,13 @@ function Start-PreFilesImportEnrollmentRestrictions
$filesToImport | sort-object -property @{e={$_.Object.priority}}
}
+function Start-PreUpdateEnrollmentRestrictions
+{
+ param($obj, $objectType, $curObject, $fromObj)
+
+ Remove-Property $obj "priority"
+}
+
#endregion
#region ScopeTags
@@ -1916,12 +2106,32 @@ function Start-PreDeleteDeviceHealthScripts
{
param($obj, $objectType)
- if($obj.IsGlobal -eq $true)
+ if($obj.isGlobalScript -eq $true)
{
@{ "Delete" = $false }
}
}
+function Start-PreImportDeviceHealthScripts
+{
+ param($obj, $objectType, $file, $assignments)
+
+ if($obj.isGlobalScript -eq $true)
+ {
+ @{ "Import" = $false }
+ }
+}
+
+function Start-PreUpdateDeviceHealthScripts
+{
+ param($obj, $objectType, $curObject, $fromObj)
+
+ if($curObject.Object.isGlobalScript -eq $true)
+ {
+ @{ "Import" = $false }
+ }
+}
+
#endregion
#region Generic functions
@@ -1944,7 +2154,7 @@ function Save-EMDefaultPolicy
# Clean up from old version of the script that used the wrong name for Default policies
try { [IO.File]::Delete($oldFile) | Out-Null } Catch {}
}
- $obj | ConvertTo-Json -Depth 10 | Out-File -LiteralPath "$path\$((Remove-InvalidFileNameChars $fileName)).json"
+ $obj | ConvertTo-Json -Depth 20 | Out-File -LiteralPath "$path\$((Remove-InvalidFileNameChars $fileName)).json"
}
}
catch {}
@@ -2003,7 +2213,7 @@ function Add-EMAssignmentsToExportFile
{
$tmpObj.Assignments = $assignments
}
- ConvertTo-Json $tmpObj -Depth 10 | Out-File -LiteralPath $fileName -Force
+ ConvertTo-Json $tmpObj -Depth 20 | Out-File -LiteralPath $fileName -Force
}
}
@@ -2033,7 +2243,7 @@ function Add-EMAssignmentsToObject
Remove-Property $assignment.target $prop.Name
}
- $json = Update-JsonForEnvironment ($assignment | ConvertTo-Json -Depth 10)
+ $json = Update-JsonForEnvironment ($assignment | ConvertTo-Json -Depth 20)
Invoke-GraphRequest -Url $api -Body $json -Method "POST" | Out-Null
}
@{"Import"=$false}
@@ -2041,4 +2251,31 @@ function Add-EMAssignmentsToObject
#endregion
+#region Mac Custom Scripts
+
+function Start-PreUpdateMacCustomAttributes
+{
+ param($obj, $objectType, $curObject, $fromObj)
+
+ foreach($prop in @('customAttributeName','customAttributeType','displayName'))
+ {
+ Remove-Property $obj $prop
+ }
+}
+
+#endregion
+
+#region Mac Feature Updates
+function Start-PreUpdateFeatureUpdates
+{
+ param($obj, $objectType, $curObject, $fromObj)
+
+ foreach($prop in @('deployableContentDisplayName','endOfSupportDate'))
+ {
+ Remove-Property $obj $prop
+ }
+}
+#endregion
+
+
Export-ModuleMember -alias * -function *
\ No newline at end of file
diff --git a/Extensions/EndpointManagerInfo.psm1 b/Extensions/EndpointManagerInfo.psm1
index bf94e44..1109e8b 100644
--- a/Extensions/EndpointManagerInfo.psm1
+++ b/Extensions/EndpointManagerInfo.psm1
@@ -10,7 +10,7 @@ This module is for the Endpoint Info View. It shows read-only objects in Intune
#>
function Get-ModuleVersion
{
- '3.1.2'
+ '3.1.3'
}
function Invoke-InitializeModule
@@ -21,7 +21,7 @@ function Invoke-InitializeModule
Description = "Displays read-only information in Intune."
ID = "EMInfoGraphAPI"
ViewPanel = $viewPanel
- ItemChanged = { Show-GraphObjects; Write-Status ""}
+ ItemChanged = { Show-GraphObjects; Invoke-ModuleFunction "Invoke-GraphObjectsChanged"; Write-Status ""}
Activating = { Invoke-EMInfoActivatingView }
Authentication = (Get-MSALAuthenticationObject)
Authenticate = { Invoke-EMInfoAuthenticateToMSAL }
@@ -37,7 +37,7 @@ function Invoke-InitializeModule
Id = "BaselineTemplates"
ViewID = "EMInfoGraphAPI"
API = "/deviceManagement/templates"
- ShowButtons = @("View")
+ ShowButtons = @("Export","View")
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
Icon="EndpointSecurity"
})
@@ -48,7 +48,7 @@ function Invoke-InitializeModule
ViewID = "EMInfoGraphAPI"
ViewProperties = @("bindStatus", "lastAppSyncDateTime", "ownerUserPrincipalName")
API = "/deviceManagement/androidManagedStoreAccountEnterpriseSettings"
- ShowButtons = @("View")
+ ShowButtons = @("Export","View")
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
})
@@ -57,7 +57,7 @@ function Invoke-InitializeModule
Id = "AndroidEnrolmentProfiles"
ViewID = "EMInfoGraphAPI"
API = "deviceManagement/androidDeviceOwnerEnrollmentProfiles"
- ShowButtons = @("View")
+ ShowButtons = @("Export","View")
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
Icon = "AndroidCOWP"
})
@@ -68,7 +68,7 @@ function Invoke-InitializeModule
ViewID = "EMInfoGraphAPI"
ViewProperties = @("appleId", "state", "appleId", "id")
API = "/deviceAppManagement/vppTokens"
- ShowButtons = @("View")
+ ShowButtons = @("Export","View")
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
})
@@ -78,7 +78,7 @@ function Invoke-InitializeModule
ViewID = "EMInfoGraphAPI"
ViewProperties = @("tokenName", "appleIdentifier", "tokenExpirationDateTime", "id")
API = "/deviceManagement/depOnboardingSettings/?`$top=100"
- ShowButtons = @("View")
+ ShowButtons = @("Export","View")
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
})
diff --git a/Extensions/MSALAuthentication.psm1 b/Extensions/MSALAuthentication.psm1
index 77deae8..ea341be 100644
--- a/Extensions/MSALAuthentication.psm1
+++ b/Extensions/MSALAuthentication.psm1
@@ -10,7 +10,7 @@ This module manages Authentication for the application with MSAL. It is also res
#>
function Get-ModuleVersion
{
- '3.0.3'
+ '3.0.4'
}
$global:msalAuthenticator = $null
@@ -837,33 +837,57 @@ function Connect-MSALUser
function Disconnect-MSALUser
{
- param($user, [switch]$force)
+ param($user, [switch]$force, [switch]$PassThru)
+ $logout = $false
+ $userLoggedOut = $false
if(-not $user)
{
+ $logout = $true
if(-not $global:MSALToken.Account) { return }
$user = $global:MSALToken.Account # Logout current user
$global:MSALToken = $null
- Clear-MSALCurentUserVaiables # Only clear variables for current user
+ Clear-MSALCurentUserVaiables # Only clear variables for current user
+ $msg = "Do you want to remove the token from the cache?"
+ $title = "Remove token?"
+ }
+ else
+ {
+ $msg = "Are you sure you want to forget user $($user.UserName)?" #!!!
+ $title = "Forget user?"
}
# ToDo: Clear browser cache
if($user -and $global:MSALApp -and (Get-SettingValue "CacheMSALToken"))
{
- if($force -eq $true -or [System.Windows.MessageBox]::Show("Do you want to remove the token from the cache?", "Clear cache?", "YesNo", "Question") -eq "Yes")
+ if($force -eq $true -or [System.Windows.MessageBox]::Show($msg, $title, "YesNo", "Question") -eq "Yes")
{
try
{
[void]$global:MSALApp.RemoveAsync($user).GetAwaiter().GetResult()
+ if($logout -eq $false)
+ {
+ Write-Log "User $($user.UserName) removed from cache"
+ }
+ $userLoggedOut = $true
}
catch
{
- Write-LogError "Failed to remove token from cache" $_.Exception
+ Write-LogError "Failed to remove $($user.UserName) from cache" $_.Exception
}
}
}
- Get-MSALUserInfo
+
+ if($logout)
+ {
+ Get-MSALUserInfo
+ }
+
+ if($PassThru -eq $true)
+ {
+ $userLoggedOut
+ }
}
function Get-MSALProfileEllipse
@@ -1079,7 +1103,7 @@ function Get-MSALProfileEllipse
try
{
#########################################################################################################
- ### Build Profile Info forcurrent user
+ ### Build Profile Info for current user
#########################################################################################################
$global:grdProfileInfo = $null
@@ -1132,35 +1156,33 @@ function Get-MSALProfileEllipse
try
{
$grdAccount = [System.Windows.Controls.Grid]::new()
+
$cd = [System.Windows.Controls.ColumnDefinition]::new()
- $grdAccount.ColumnDefinitions.Add($cd)
+ $grdAccount.ColumnDefinitions.Add($cd) # Login
+
$cd = [System.Windows.Controls.ColumnDefinition]::new()
$cd.Width = [double]::NaN
- $grdAccount.ColumnDefinitions.Add($cd)
+ $grdAccount.ColumnDefinitions.Add($cd) # Forget
+
+ $grdLogin = [System.Windows.Controls.Grid]::new()
+ $cd = [System.Windows.Controls.ColumnDefinition]::new()
+ $grdLogin.ColumnDefinitions.Add($cd)
+ $cd = [System.Windows.Controls.ColumnDefinition]::new()
+ $cd.Width = [double]::NaN
+ $grdLogin.ColumnDefinitions.Add($cd)
$icon = Get-XamlObject ($global:AppRootFolder + "\Xaml\Icons\LoggedOnUser.xaml")
$icon.Width = 24
$icon.Height = 24
$icon.Margin = "0,0,5,0"
- $grdAccount.Children.Add($icon) | Out-Null
+ $grdLogin.Children.Add($icon) | Out-Null
$lbObj = [Windows.Markup.XamlReader]::Parse("$($account.UserName)$($account.HomeAccountId.TenantId)")
$lbObj.SetValue([System.Windows.Controls.Grid]::ColumnProperty,1)
- $grdAccount.Children.Add($lbObj) | Out-Null
-
- # Forget user
- # Cannot be added to Grid since that is for logging on with user
- # Need to rebuild the
- #$icon = Get-XamlObject ($global:AppRootFolder + "\Xaml\Icons\Trash.xaml")
- #$icon.Width = 24
- #$icon.Height = 24
- #$icon.Margin = "0,0,5,0"
- #$icon.SetValue([System.Windows.Controls.Grid]::ColumnProperty,1)
- #$icon.HorizontalAlignment = "Right"
- #$grdAccount.Children.Add($icon) | Out-Null
+ $grdLogin.Children.Add($lbObj) | Out-Null
$lnkButton = [System.Windows.Controls.Button]::new()
- $lnkButton.Content = $grdAccount
+ $lnkButton.Content = $grdLogin
$lnkButton.Style = $window.TryFindResource("LinkButton")
$lnkButton.Margin = "0,5,0,0"
$lnkButton.Cursor = "Hand"
@@ -1177,8 +1199,36 @@ function Get-MSALProfileEllipse
}
Write-Status ""
})
+
+ $grdAccount.Children.Add($lnkButton) | Out-Null
+
+ # Add Forget user icon
+ $icon = Get-XamlObject ($global:AppRootFolder + "\Xaml\Icons\Bin.xaml")
+ $icon.Width = 16
+ $icon.Height = 16
+ $icon.Margin = "5,5,0,0"
- AddGridObject $otherLogins $lnkButton
+ $lnkButton = [System.Windows.Controls.Button]::new()
+ $lnkButton.ToolTip = "Forget"
+ $lnkButton.Content = $icon
+ $lnkButton.Style = $window.TryFindResource("LinkButton")
+ $lnkButton.Margin = "0,5,0,0"
+ $lnkButton.Cursor = "Hand"
+ $lnkButton.Tag = $account
+ $lnkButton.SetValue([System.Windows.Controls.Grid]::ColumnProperty,1)
+ $lnkButton.add_Click({
+ Write-Status "Logging out $($this.Tag.UserName)"
+ if((Disconnect-MSALUser $this.Tag -PassThru))
+ {
+ $this.Parent.Parent.Children.Remove($this.Parent)
+ }
+
+ Write-Status ""
+ })
+
+ $grdAccount.Children.Add($lnkButton) | Out-Null
+
+ AddGridObject $otherLogins $grdAccount
}
catch {}
}
diff --git a/Extensions/MSGraph.psm1 b/Extensions/MSGraph.psm1
index 06b3cf2..657029c 100644
--- a/Extensions/MSGraph.psm1
+++ b/Extensions/MSGraph.psm1
@@ -10,7 +10,7 @@ This module manages Microsoft Grap fuctions like calling APIs, managing graph ob
#>
function Get-ModuleVersion
{
- '3.1.3'
+ '3.1.4'
}
$global:MSGraphGlobalApps = @(
@@ -40,7 +40,7 @@ function Invoke-InitializeModule
Value = "replace"
},
[PSCustomObject]@{
- Name = "Update (Experimental)"
+ Name = "Update (Preview)"
Value = "update"
}
)
@@ -1338,7 +1338,7 @@ function Import-GraphFile
try
{
# Clone the object to keep original values
- $objClone = $file.Object | ConvertTo-Json -Depth 10 | ConvertFrom-Json
+ $objClone = $file.Object | ConvertTo-Json -Depth 20 | ConvertFrom-Json
if($objectType.PreFileImportCommand)
{
@@ -1391,13 +1391,18 @@ function Reset-GraphObjet
$objectType = $fileObj.ObjectType
# Clone the object before removing properties
- $obj = $fileObj.Object | ConvertTo-Json -Depth 10 | ConvertFrom-Json
+ $obj = $fileObj.Object | ConvertTo-Json -Depth 20 | ConvertFrom-Json
Start-GraphPreImport $obj $objectType
Remove-Property $obj "Assignments"
Remove-Property $obj "isAssigned"
if($global:cbImportType.SelectedValue -eq "update")
{
+ foreach($prop in $objectType.PropertiesToRemoveForUpdate)
+ {
+ Remove-Property $obj $prop
+ }
+
$params = @{}
$strAPI = (?? $objectType.APIPATCH $objectType.API) + "/$($curObject.Object.Id)"
$method = "PATCH"
@@ -1409,7 +1414,7 @@ function Reset-GraphObjet
if($ret.ContainsKey("Import") -and $ret["Import"] -eq $false)
{
# Import handled manually
- return $false
+ return $true
}
if($ret.ContainsKey("API"))
@@ -1429,7 +1434,7 @@ function Reset-GraphObjet
}
}
- $json = ConvertTo-Json $obj -Depth 10
+ $json = ConvertTo-Json $obj -Depth 15
if($true) #$global:MigrationTableCacheId -ne $global:Organization.Id)
{
# Call Update-JsonForEnvironment before importing the object
@@ -1527,7 +1532,7 @@ function Import-GraphObjectAssignment
if(($assignments | measure).Count -eq 0) { return }
$preConfig = $null
- $clonedAssignments = $assignments | ConvertTo-Json -Depth 10 | ConvertFrom-Json
+ $clonedAssignments = $assignments | ConvertTo-Json -Depth 20 | ConvertFrom-Json
if($objectType.PreImportAssignmentsCommand)
{
@@ -1575,7 +1580,7 @@ function Import-GraphObjectAssignment
$htAssignments = @{}
$htAssignments.Add((?? $objectType.AssignmentsType "assignments"), @($ObjectAssignments))
- $json = $htAssignments | ConvertTo-Json -Depth 10
+ $json = $htAssignments | ConvertTo-Json -Depth 20
if($CopyAssignments -ne $true)
{
$json = Update-JsonForEnvironment $json
@@ -2139,8 +2144,7 @@ function Export-GraphObject
Remove-Property $obj "Assignments"
}
- #$obj | ConvertTo-Json -Depth 10 | Out-File ([IO.Path]::Combine($exportFolder, (Remove-InvalidFileNameChars "$((Get-GraphObjectName $obj $objectType)).json")))
- $obj | ConvertTo-Json -Depth 10 | Out-File -LiteralPath ([IO.Path]::Combine($exportFolder, (Remove-InvalidFileNameChars "$((Get-GraphObjectName $obj $objectType)).json")))
+ $obj | ConvertTo-Json -Depth 20 | Out-File -LiteralPath ([IO.Path]::Combine($exportFolder, (Remove-InvalidFileNameChars "$((Get-GraphObjectName $obj $objectType)).json"))) -Force
if($objectType.PostExportCommand)
{
@@ -2186,7 +2190,7 @@ function Import-GraphObject
Write-Log "Import $($objectType.Title) object $((Get-GraphObjectName $obj $objectType))"
# Clone the object before removing properties
- $objClone = $obj | ConvertTo-Json -Depth 10 | ConvertFrom-Json
+ $objClone = $obj | ConvertTo-Json -Depth 20 | ConvertFrom-Json
Start-GraphPreImport $obj $objectType
diff --git a/README.md b/README.md
index 3785451..d58393e 100644
--- a/README.md
+++ b/README.md
@@ -39,17 +39,27 @@ The script can import the exported json files in multiple ways.
* **Always import:** The script will try to import the file. It will not check if it exists.
This is the default behavior
+
* **Skip if object exists:** The script will look if there is an existing object with the same name and type. It will not import the file if existing object is detected
+
* **Replace (Preview):** If a existing object is detected, the script will
+
* Import the file without assignments
* Copy assignments from the existing object
* Run PostReplace commands - Priority will be set for Enrollment Restrictions etc.
* Update PolicySets object(s) to use the new imported object (detected by policySet assignments)
* Delete the original object
-* **Update (Experimental):** This will update the existing object.
- Note: This is not fully implemented yet. It only works on a few object types
+
+* **Update (Preview):** This will update the existing object.
+
+ Update does not support all the properties that import does and object types behaves differently during update e.g. Settings for Endpoint Security objects will not be cleared. There is no API for removing settings only adding. If a settings does not in the import file, the existing setting will be set to Not Configured. Settings Catalog replaces the whole settings property during update.
+
+ This has been tested with all supported object types *except* Import Scripts (Shell), Android OEM Config and Apple Enrollment Types.
+
+
+ Each application type works differently. Update functionality has been tested on Win32, Windows MSI LoB, iOS Store, Microsoft Store and Microsoft 365 (Windows and MacOS).
-**WARNING:** Use Replace with caution! Replace will delete the existing object after the imported object is updated but could cause issues in the environment if something in the process goes wrong. Verify the process in a test environment before using this!
+**WARNING:** Use Replace with caution! Replace will delete the existing object after a new object is imported and the assignments are copied, but it could cause issues in the environment if something in the process goes wrong. Replacing single objects can break references e.g. replacing an Application can break AutoPilot profiles, App Protection and App Configuration policies. Verify the process in a test environment before using this!
**Recommendation:** Backup all policies before running Replace/Update.
diff --git a/ReleaseNotes.md b/ReleaseNotes.md
index e3aa204..7fb74d9 100644
--- a/ReleaseNotes.md
+++ b/ReleaseNotes.md
@@ -1,5 +1,18 @@
# Release Notes
+## 3.1.8 - 2021-07-18
+
+**New features**
+
+- Forget cached users - Forget a user by clicking on the bin icon in the user information. This will remove the user from the cached file. It will not remove it from the browser cache.
+- Update existing profiles during import is moved to preview.
+ **Important:** See the Import section in the [Readme](README.md#Import) file for more information
+ This is based on the feature request in [Issue 17](https://github.com/Micke-K/IntuneManagement/issues/17)
+
+**Fixes**
+
+* Fixed a bug when exporting Settings Catalog. When exporting settings based on key/value pairs, some parts were not converted to json objects. Import worked but not the update. Depth parameter was increased in the ConvertTo-Json functions.
+
## 3.1.7 - 2021-07-12
**New features**
diff --git a/Xaml/Icons/Bin.xaml b/Xaml/Icons/Bin.xaml
new file mode 100644
index 0000000..7beab1a
--- /dev/null
+++ b/Xaml/Icons/Bin.xaml
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file