3.9.3
This commit is contained in:
@@ -20,7 +20,7 @@ $global:documentationProviders = @()
|
||||
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'2.0.2'
|
||||
'2.0.3'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -228,6 +228,7 @@ function Get-ObjectDocumentation
|
||||
$script:applicabilityRules = @()
|
||||
$script:objectAssignments = @()
|
||||
$script:objectScripts = @()
|
||||
$script:admxCategories = $null
|
||||
|
||||
$script:ObjectTypeFullTable = @{} # Hash table with objects that should be documented in a single table eg ScopeTags
|
||||
|
||||
@@ -384,6 +385,7 @@ function Invoke-ObjectDocumentation
|
||||
$global:catRecommendedSettings = $null
|
||||
$global:intentCategoryDefs = $null
|
||||
$global:cfgCategories = $null
|
||||
$script:admxCategories = $null
|
||||
|
||||
$script:DocumentationLanguage = "en"
|
||||
$script:objectSeparator = [System.Environment]::NewLine
|
||||
@@ -879,7 +881,8 @@ function Invoke-TranslateADMXObject
|
||||
{
|
||||
if(-not $definitionValue.definition -and $definitionValues.'definition@odata.bind')
|
||||
{
|
||||
$definition = Invoke-GraphRequest -Url $definitionValue.'definition@odata.bind' -ODataMetadata "minimal" @params
|
||||
$url = $definitionValue.'definition@odata.bind' -replace $global:graphURL, ("https://$((?? $global:MSALGraphEnvironment "graph.microsoft.com"))/beta")
|
||||
$definition = Invoke-GraphRequest -Url $url -ODataMetadata "minimal" @params
|
||||
if($definition)
|
||||
{
|
||||
$definitionValue | Add-Member -MemberType NoteProperty -Name "definition" -Value $definition
|
||||
@@ -1924,7 +1927,8 @@ function Get-LanguageString
|
||||
|
||||
if(-not $script:languageStrings)
|
||||
{
|
||||
$fileContent = Get-Content ($global:AppRootFolder + "\Documentation\Strings-$($script:DocumentationLanguage).json") -Encoding UTF8
|
||||
$lng = ?? $script:DocumentationLanguage "en"
|
||||
$fileContent = Get-Content ($global:AppRootFolder + "\Documentation\Strings-$($lng).json") -Encoding UTF8
|
||||
$script:languageStrings = $fileContent | ConvertFrom-Json
|
||||
}
|
||||
|
||||
@@ -4432,7 +4436,7 @@ function local:Invoke-StartDocumentatiom
|
||||
# Add each object to the documentation
|
||||
foreach($curGroupId in ($sourceList.ObjectType | Select GroupID -Unique).GroupID)
|
||||
{
|
||||
# New object group e.g. Script, Tennant, Device Configuration
|
||||
# New object group e.g. Script, Tenant, Device Configuration
|
||||
# A group matches a menu item in the protal but can contain multiple object types
|
||||
if($global:cbDocumentationType.SelectedItem.NewObjectGroup)
|
||||
{
|
||||
@@ -5040,4 +5044,19 @@ function Set-TableObjects
|
||||
{
|
||||
$script:ObjectTypeFullTable.Add($objectInfo.ObjectType.Id, $objectInfo)
|
||||
}
|
||||
}
|
||||
|
||||
function Get-PolicyTypeName
|
||||
{
|
||||
param($type, $default = $null)
|
||||
|
||||
$categoryObj = Get-TranslationFiles $type
|
||||
|
||||
if($null -eq $categoryObj) { return $default }
|
||||
|
||||
$lngStr = Get-LanguageString "PolicyType.$($categoryObj.PolicyTypeLanguageId)"
|
||||
|
||||
if($lngStr) { return $lngStr }
|
||||
|
||||
return $defult
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.0.0'
|
||||
'1.0.1'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -374,7 +374,7 @@ function Invoke-HTMLProcessItem
|
||||
$isFilterAssignment = $false
|
||||
foreach($assignment in $documentedObj.Assignments)
|
||||
{
|
||||
if(($assignment.target.PSObject.Properties | Where Name -eq "deviceAndAppManagementAssignmentFilterType"))
|
||||
if(($assignment.PSObject.Properties | Where Name -eq "FilterMode"))
|
||||
{
|
||||
$isFilterAssignment = $true
|
||||
break
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.1.0'
|
||||
'1.1.1'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -331,7 +331,7 @@ function Invoke-MDProcessItem
|
||||
$isFilterAssignment = $false
|
||||
foreach($assignment in $documentedObj.Assignments)
|
||||
{
|
||||
if(($assignment.target.PSObject.Properties | Where Name -eq "deviceAndAppManagementAssignmentFilterType"))
|
||||
if(($assignment.PSObject.Properties | Where Name -eq "FilterMode"))
|
||||
{
|
||||
$isFilterAssignment = $true
|
||||
break
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#https://docs.microsoft.com/en-us/office/vba/api/overview/word
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.5.0'
|
||||
'1.6.0'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -600,7 +600,7 @@ function Invoke-WordProcessItem
|
||||
$isFilterAssignment = $false
|
||||
foreach($assignment in $documentedObj.Assignments)
|
||||
{
|
||||
if(($assignment.target.PSObject.Properties | Where Name -eq "deviceAndAppManagementAssignmentFilterType"))
|
||||
if(($assignment.PSObject.Properties | Where Name -eq "FilterMode"))
|
||||
{
|
||||
$isFilterAssignment = $true
|
||||
break
|
||||
@@ -752,7 +752,7 @@ function Add-DocTableItems
|
||||
|
||||
$range = $script:doc.application.selection.range
|
||||
|
||||
$script:docTable = $script:doc.Tables.Add($range, ($items.Count + 1), $properties.Count, [Microsoft.Office.Interop.Word.WdDefaultTableBehavior]::wdWord9TableBehavior, [Microsoft.Office.Interop.Word.WdAutoFitBehavior]::wdAutoFitWindow)
|
||||
$script:docTable = $script:doc.Tables.Add($range, (($items | measure).Count + 1), $properties.Count, [Microsoft.Office.Interop.Word.WdDefaultTableBehavior]::wdWord9TableBehavior, [Microsoft.Office.Interop.Word.WdAutoFitBehavior]::wdAutoFitWindow)
|
||||
$script:docTable.ApplyStyleHeadingRows = $true
|
||||
Set-DocObjectStyle $script:docTable $global:txtWordTableStyle.Text | Out-null
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ This module is for the Endpoint Manager/Intune View. It manages Export/Import/Co
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.9.2'
|
||||
'3.9.3'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -703,6 +703,7 @@ function Invoke-InitializeModule
|
||||
ExpandAssignmentsList = $false
|
||||
PreFilesImportCommand = { Start-PreFilesImportADMXFiles @args }
|
||||
PreImportCommand = { Start-PreImportADMXFiles @args }
|
||||
PostImportCommand = { Start-PostImportADMXFiles @args }
|
||||
PreDeleteCommand = { Start-PreDeleteADMXFiles @args }
|
||||
ViewProperties = @("fileName","status","Id")
|
||||
PropertiesToRemove = @("languageCodes","targetPrefix","targetNamespace","policyType","revision","status","uploadDateTime")
|
||||
@@ -848,6 +849,8 @@ function Invoke-EMSaveSettings
|
||||
function Invoke-GraphAuthenticationUpdated
|
||||
{
|
||||
Set-EMUIStatus
|
||||
|
||||
$script:CustomADMXDefinitions = $null
|
||||
}
|
||||
|
||||
function Set-EMUIStatus
|
||||
@@ -2023,10 +2026,9 @@ function local:Start-ImportApp
|
||||
|
||||
if((Get-SettingValue "EMSaveEncryptionFile") -eq $true)
|
||||
{
|
||||
#$fileEncryptionInfo = $fileEncryptionInfo | where { $null -ne $_.fileEncryptionInfo }
|
||||
if($fileEncryptionInfo)
|
||||
{
|
||||
$jsonEncryptionInfo = $fileEncryptionInfo.fileEncryptionInfo | ConvertTo-Json -Depth 10
|
||||
$jsonEncryptionInfo = $fileEncryptionInfo | ConvertTo-Json -Depth 10
|
||||
|
||||
$pkgPath = Get-SettingValue "EMIntuneAppDownloadFolder" (Get-SettingValue "EMIntuneAppPackages")
|
||||
if($pkgPath -and [IO.Directory]::Exists($pkgPath))
|
||||
@@ -2144,11 +2146,11 @@ function Add-DetailExtensionApplications
|
||||
$dlgSave.FileName = ($obj.FileName + ".encrypted")
|
||||
if($dlgSave.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK -and $dlgSave.Filename)
|
||||
{
|
||||
Start-DownloadAppContent $obj $dlgSave.FileName
|
||||
$contentFileObj = Start-DownloadAppContent $obj $dlgSave.FileName
|
||||
|
||||
if([IO.File]::Exists($dlgSave.FileName))
|
||||
{
|
||||
$fullPath = $pkgPath + "\$($obj.displayName)_$($obj.id)_$($obj.committedContentVersion).json"
|
||||
$fullPath = Find-AppEncryptionFile $obj $contentFileObj $pkgPath
|
||||
if([IO.File]::Exists($fullPath) -eq $false)
|
||||
{
|
||||
if(([System.Windows.MessageBox]::Show("Could not find decryption file for $($obj.displayName)`nApp Id: $($obj.id)`nContent version $($obj.committedContentVersion)`n`nDo you want to browse for the file?", "Encryption file not found", "YesNo", "Warning")) -eq "Yes")
|
||||
@@ -2170,8 +2172,16 @@ function Add-DetailExtensionApplications
|
||||
{
|
||||
Write-Status "Decrypting file"
|
||||
$encryptionInfo = ConvertFrom-Json (Get-Content -Path $fullPath -Raw)
|
||||
if($encryptionInfo.fileEncryptionInfo)
|
||||
{
|
||||
$encryptionInfo = $encryptionInfo.fileEncryptionInfo
|
||||
}
|
||||
$destination = $pkgPath + "\$($obj.FileName)"
|
||||
Start-DecryptFile $dlgSave.Filename $destination $encryptionInfo.encryptionKey $encryptionInfo.initializationVector
|
||||
try { [IO.File]::Delete($dlgSave.Filename) }
|
||||
catch {
|
||||
Write-LogError "Failed to delete exported encrypted file" $_.Exception
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2188,7 +2198,28 @@ function Add-DetailExtensionApplications
|
||||
{
|
||||
$tmp.Children.Insert($index, $btnDownload)
|
||||
}
|
||||
}
|
||||
|
||||
function Find-AppEncryptionFile
|
||||
{
|
||||
param($obj, $contentFileObj, $rootFolders)
|
||||
|
||||
$search = @()
|
||||
$search += "$($obj.displayName)_$($obj.id)_$($obj.committedContentVersion)"
|
||||
$search += "$([IO.Path]::GetFileNameWithoutExtension($obj.fileName))_$($contentFileObj.size)"
|
||||
$search += "$($obj.displayName)_$($contentFileObj.size)"
|
||||
|
||||
foreach($rootFolder in $rootFolders)
|
||||
{
|
||||
foreach($searchName in $search)
|
||||
{
|
||||
$fullName = ($rootFolder + "\$($searchName).json")
|
||||
if([IO.File]::Exists($fullName))
|
||||
{
|
||||
return $fullName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Start-PreImportAssignmentsApplications
|
||||
@@ -2278,7 +2309,7 @@ function Start-PostExportApplications
|
||||
Save-Setting "Intune" "ExportAppFile" $global:chkExportApplicationFile.IsChecked
|
||||
if($global:chkExportApplicationFile.IsChecked)
|
||||
{
|
||||
$encryptioSource = Get-SettingValue "EMIntuneAppDownloadFolder" (Get-SettingValue "EMIntuneAppPackages")
|
||||
$encryptionSource = Get-SettingValue "EMIntuneAppDownloadFolder" (Get-SettingValue "EMIntuneAppPackages")
|
||||
$pkgPath = $path
|
||||
|
||||
if($pkgPath)
|
||||
@@ -2286,27 +2317,32 @@ function Start-PostExportApplications
|
||||
Write-Status "Download file"
|
||||
|
||||
$exportFile = $pkgPath + "\$($obj.FileName).encrypted"
|
||||
$encryptionFile = $encryptioSource + "\$($obj.displayName)_$($obj.id)_$($obj.committedContentVersion).json"
|
||||
$contentFileObj = Start-DownloadAppContent $obj $exportFile -GetContentFileInfoOnly
|
||||
$encryptionFile = Find-AppEncryptionFile $obj $contentFileObj $encryptionSource
|
||||
if($encryptionFile -and [IO.File]::Exists($encryptionFile))
|
||||
{
|
||||
Start-DownloadAppContent $obj $exportFile
|
||||
Start-DownloadFile $contentFileObj.azureStorageUri $exportFile
|
||||
|
||||
if([IO.File]::Exists($exportFile))
|
||||
{
|
||||
Write-Status "Decrypting file"
|
||||
$encryptionInfo = ConvertFrom-Json (Get-Content -Path $encryptionFile -Raw)
|
||||
if($encryptionInfo.fileEncryptionInfo)
|
||||
{
|
||||
$encryptionInfo = $encryptionInfo.fileEncryptionInfo
|
||||
}
|
||||
$destination = $pkgPath + "\$($obj.FileName)"
|
||||
Start-DecryptFile $exportFile $destination $encryptionInfo.encryptionKey $encryptionInfo.initializationVector
|
||||
}
|
||||
|
||||
try { [IO.File]::Delete($exportFile) }
|
||||
catch {
|
||||
Write-LogError "Filed to delete exported encrypted file" $_.Exception
|
||||
Write-LogError "Failed to delete exported encrypted file" $_.Exception
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Log "Cound not file encryption file `"$($obj.displayName)_$($obj.id)_$($obj.committedContentVersion).json`""
|
||||
Write-Log "Cound not file encryption file"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2537,7 +2573,7 @@ function Get-GPOObjectSettings
|
||||
"definition@odata.bind" = "$($global:graphURL)/deviceManagement/groupPolicyDefinitions('$($definitionValue.definition.id)')"
|
||||
}
|
||||
|
||||
if($GPOObj.policyConfigurationIngestionType -eq "Custom")
|
||||
if($definitionValue.definition.categoryPath)
|
||||
{
|
||||
$obj.Add("#Definition_Id", $definitionValue.definition.id)
|
||||
$obj.Add("#Definition_displayName", $definitionValue.definition.displayName)
|
||||
@@ -2555,7 +2591,7 @@ function Get-GPOObjectSettings
|
||||
# Add presentation@odata.bind property that links the value to the presentation object
|
||||
$presentationValue | Add-Member -MemberType NoteProperty -Name "presentation@odata.bind" -Value "$($global:graphURL)/deviceManagement/groupPolicyDefinitions('$($definitionValue.definition.id)')/presentations('$($presentationValue.presentation.id)')"
|
||||
|
||||
if($GPOObj.policyConfigurationIngestionType -eq "Custom")
|
||||
if($definitionValue.definition.categoryPath)
|
||||
{
|
||||
$presentationValue | Add-Member -MemberType NoteProperty -Name "#Presentation_Id" -Value $presentationValue.presentation.id
|
||||
$presentationValue | Add-Member -MemberType NoteProperty -Name "#Presentation_Label" -Value $presentationValue.presentation.label
|
||||
@@ -2579,15 +2615,15 @@ function Get-GPOObjectSettings
|
||||
|
||||
function Import-GPOSetting
|
||||
{
|
||||
param($obj, $settings, [switch]$CustomADMX)
|
||||
param($obj, $settings)
|
||||
|
||||
if($obj)
|
||||
{
|
||||
Write-Status "Import settings for $($obj.displayName)"
|
||||
|
||||
$isCustomADMX = $CustomADMX -eq $true
|
||||
$hasCustomADMX = $null -ne ($settings | Where { $null -ne $_.'#Definition_categoryPath' })
|
||||
|
||||
if($isCustomADMX)
|
||||
if($hasCustomADMX)
|
||||
{
|
||||
Write-Status "Import custom ADMX settings"
|
||||
if(-not $script:CustomADMXDefinitions)
|
||||
@@ -2606,7 +2642,12 @@ function Import-GPOSetting
|
||||
Category = $tmpCat
|
||||
Presentations = $null
|
||||
}
|
||||
$script:CustomADMXDefinitions.Add($key, $val)
|
||||
try {
|
||||
$script:CustomADMXDefinitions.Add($key, $val)
|
||||
}
|
||||
catch {
|
||||
Write-Log "Failed to add '$($tmpDef.displayName)' in category '$($tmpDef.categoryPath)' of class $($tmpDef.classType)" 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2615,7 +2656,7 @@ function Import-GPOSetting
|
||||
|
||||
foreach($setting in $settings)
|
||||
{
|
||||
if($isCustomADMX -and $script:CustomADMXDefinitions -is [HashTable] -and $script:CustomADMXDefinitions.Count -gt 0)
|
||||
if($setting.'#Definition_categoryPath' -and $script:CustomADMXDefinitions -is [HashTable] -and $script:CustomADMXDefinitions.Count -gt 0)
|
||||
{
|
||||
$defVal = $null
|
||||
$key = ($setting.'#Definition_displayName' + $setting.'#Definition_categoryPath' + $setting.'#Definition_classType').ToLower()
|
||||
@@ -2670,7 +2711,7 @@ function Import-GPOSetting
|
||||
Write-Log "Settings might not be available if imported in another environment" 3
|
||||
}
|
||||
}
|
||||
elseif($isCustomADMX)
|
||||
elseif($setting.'#Definition_categoryPath')
|
||||
{
|
||||
Write-Log "Custom AMDX settings cannot be imported without ADMX file imported. Definitions not found" 2
|
||||
continue
|
||||
@@ -2678,7 +2719,7 @@ function Import-GPOSetting
|
||||
|
||||
Start-GraphPreImport $setting
|
||||
|
||||
if($true) #$isCustomADMX)
|
||||
if($true)
|
||||
{
|
||||
foreach($tmpProp in (($setting.PSObject.Properties | Where Name -like "#*").Name))
|
||||
{
|
||||
@@ -2743,7 +2784,7 @@ function Start-PostFileImportAdministrativeTemplate
|
||||
{
|
||||
$tmpObj = Get-GraphObjectFromFile $file
|
||||
|
||||
Import-GPOSetting $obj $settings -CustomADMX:($tmpObj.policyConfigurationIngestionType -eq "Custom")
|
||||
Import-GPOSetting $obj $settings
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3468,6 +3509,8 @@ function Add-EMAssignmentsToExportFile
|
||||
{
|
||||
param($obj, $objectType, $path, $Url = "")
|
||||
|
||||
if($global:chkExportAssignments.IsChecked -ne $true) { return }
|
||||
|
||||
$fileName = (Get-GraphObjectName $obj $objectType)
|
||||
if((Get-SettingValue "AddIDToExportFile") -eq $true -and $obj.Id)
|
||||
{
|
||||
@@ -3811,6 +3854,13 @@ function Start-PreImportADMXFiles
|
||||
$obj.defaultLanguageCode = ""
|
||||
}
|
||||
|
||||
function Start-PostImportADMXFiles
|
||||
{
|
||||
param($obj, $objectType, $file)
|
||||
|
||||
$script:CustomADMXDefinitions = $null
|
||||
}
|
||||
|
||||
function Start-PreDeleteADMXFiles
|
||||
{
|
||||
param($obj, $objectType)
|
||||
|
||||
@@ -10,7 +10,7 @@ This module manages Application objects in Intune e.g. uploading application fil
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.9.2'
|
||||
'3.9.3'
|
||||
}
|
||||
|
||||
#########################################################################################
|
||||
@@ -718,7 +718,7 @@ function Start-DecryptFile
|
||||
|
||||
function Start-DownloadAppContent
|
||||
{
|
||||
param($obj, $destinationFile)
|
||||
param($obj, $destinationFile, [switch]$GetContentFileInfoOnly)
|
||||
# Not use but kept for reference. File can be download but it will be encrypted
|
||||
|
||||
if([IO.File]::Exists($destinationFile))
|
||||
@@ -756,5 +756,17 @@ function Start-DownloadAppContent
|
||||
}
|
||||
}
|
||||
}
|
||||
Start-DownloadFile $contentFile.azureStorageUri $destinationFile
|
||||
|
||||
if($contentFile.azureStorageUri)
|
||||
{
|
||||
if($GetContentFileInfoOnly -ne $true)
|
||||
{
|
||||
Start-DownloadFile $contentFile.azureStorageUri $destinationFile
|
||||
}
|
||||
return $contentFile
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Log "Could not find file object for app $($obj.displayName) ($($appId))" 2
|
||||
}
|
||||
}
|
||||
329
Extensions/IntuneFilterUsage.psm1
Normal file
329
Extensions/IntuneFilterUsage.psm1
Normal file
@@ -0,0 +1,329 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Module for listing Intune assignment filter usage
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
.NOTES
|
||||
Author: Mikael Karlsson
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.0.0'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
{
|
||||
Add-EMToolsViewItem (New-Object PSObject -Property @{
|
||||
Title = "Intune Filter Usage"
|
||||
Id = "IntuneFilterUsage"
|
||||
ViewID = "EMTools"
|
||||
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
|
||||
Icon="DeviceConfiguration"
|
||||
ShowViewItem = { Show-IntuneToolsFilterUsage }
|
||||
})
|
||||
}
|
||||
|
||||
function Show-IntuneToolsFilterUsage
|
||||
{
|
||||
if(-not $script:frmIntuneFilterUsage)
|
||||
{
|
||||
$script:frmIntuneFilterUsage = Get-XamlObject ($global:AppRootFolder + "\Xaml\IntuneToolsFiterUsage.xaml") #-AddVariables
|
||||
|
||||
if(-not $script:frmIntuneFilterUsage) { return }
|
||||
|
||||
Add-XamlEvent $script:frmIntuneFilterUsage "btnGetIntuneFilterUsage" "add_click" ({
|
||||
Write-Status "Get Intune Filter Usage"
|
||||
Get-EMIntuneFilterUsage
|
||||
Write-Status ""
|
||||
})
|
||||
|
||||
Add-XamlEvent $script:frmIntuneFilterUsage "btnIntuneFilterUsageCopy" "add_click" ({
|
||||
$dgValues = Get-DataGridValues ($script:frmIntuneFilterUsage.FindName("dgIntuneFilterUsage"))
|
||||
$dgValues | ConvertTo-Csv -NoTypeInformation | Set-Clipboard
|
||||
})
|
||||
|
||||
Add-XamlEvent $script:frmIntuneFilterUsage "btnIntuneFilterUsagesSave" "add_click" ({
|
||||
|
||||
$dlgSave = New-Object -Typename System.Windows.Forms.SaveFileDialog
|
||||
$dlgSave.FileName = $obj.FileName
|
||||
$dlgSave.DefaultExt = "*.csv"
|
||||
$dlgSave.Filter = "CSV (*.csv)|*.csv|All files (*.*)| *.*"
|
||||
if($dlgSave.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK -and $dlgSave.Filename)
|
||||
{
|
||||
$dgValues = Get-DataGridValues ($script:frmIntuneFilterUsage.FindName("dgIntuneFilterUsage"))
|
||||
$dgValues | ConvertTo-Csv -NoTypeInformation | Out-File -LiteralPath $dlgSave.Filename -Encoding UTF8 -Force
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
$global:grdToolsMain.Children.Clear()
|
||||
$global:grdToolsMain.Children.Add($frmIntuneFilterUsage)
|
||||
}
|
||||
|
||||
function Get-DataGridValues_old
|
||||
{
|
||||
param($dataGrid)
|
||||
|
||||
$dgColumns = $dataGrid.Columns
|
||||
#$dgColumns = Get-XamlProperty $script:frmIntuneFilterUsage "dgIntuneFilterUsage" "Columns"
|
||||
|
||||
$properties = @()
|
||||
|
||||
foreach($tmpCol in $dgColumns)
|
||||
{
|
||||
$propName = $tmpCol.Binding.Path.Path
|
||||
$properties += @{n=$tmpCol.Header;e=([Scriptblock]::Create("`$_.$propName"))}
|
||||
}
|
||||
|
||||
($script:objFilterUsage | Select -Property $properties)
|
||||
}
|
||||
|
||||
function Get-EMIntuneFilterUsage
|
||||
{
|
||||
param($rootDir)
|
||||
|
||||
Write-Status "Gather Intune Filter Information"
|
||||
|
||||
Set-XamlProperty $script:frmIntuneFilterUsage "dgIntuneFilterUsage" "ItemsSource" $null
|
||||
|
||||
$objectType = Get-GraphObjectType "AssignmentFilters"
|
||||
|
||||
$loadedGroups = @{}
|
||||
$loadedGroups.Add("adadadad-808e-44e2-905a-0b7873a8a531","All Devices")
|
||||
$loadedGroups.Add("acacacac-9df4-4c7d-9d50-4ef0226f57a9","All Users")
|
||||
|
||||
$script:objFilters = (Invoke-GraphRequest -Url $objectType.API).Value
|
||||
|
||||
$script:objFilterUsage = @()
|
||||
$groupIDs = @()
|
||||
|
||||
foreach($filter in $script:objFilters)
|
||||
{
|
||||
Write-Status "Get payloads for filter $($filter.displayName)"
|
||||
|
||||
$payloads = (Invoke-GraphRequest -Url "$($objectType.API)/$($filter.ID)/payloads").value
|
||||
|
||||
$batchObjs = @()
|
||||
foreach($payload in $payloads)
|
||||
{
|
||||
$guid = (New-Guid).Guid
|
||||
|
||||
$payloadsObj = @{
|
||||
Payload = $payload
|
||||
ID = $guid
|
||||
Requests = @()
|
||||
}
|
||||
|
||||
if($groupIDs -notcontains $payload.groupId)
|
||||
{
|
||||
$groupIDs += $payload.groupId
|
||||
}
|
||||
|
||||
$batchObjs += $payloadsObj
|
||||
|
||||
if($payload.payloadType -eq "win32app")
|
||||
{
|
||||
$payloadsObj.Requests += [ordered]@{
|
||||
id = "$($guid)_deviceHealthScripts"
|
||||
method = "GET"
|
||||
url = "/deviceManagement/deviceHealthScripts/$($payload.payloadId)/?`$select=displayName,isGlobalScript"
|
||||
headers = @{"x-ms-command-name"="AssignmentFilterPayloadProxy_resolvePayloadNames_BatchItem"}
|
||||
}
|
||||
}
|
||||
elseif($payload.payloadType -eq "application")
|
||||
{
|
||||
$payloadsObj.Requests += [ordered]@{
|
||||
id = "$($guid)_mobileApps"
|
||||
method = "GET"
|
||||
url = "//deviceAppManagement/mobileApps/$($payload.payloadId)/?`$select=displayName"
|
||||
headers = @{"x-ms-command-name"="AssignmentFilterPayloadProxy_resolvePayloadNames_BatchItem"}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$payloadsObj.Requests += [ordered]@{
|
||||
id = "$($guid)_deviceCompliancePolicies"
|
||||
method = "GET"
|
||||
url = "/deviceManagement/deviceCompliancePolicies/$($payload.payloadId)/?`$select=displayName"
|
||||
headers = @{"x-ms-command-name"="AssignmentFilterPayloadProxy_resolvePayloadNames_BatchItem"}
|
||||
}
|
||||
|
||||
$payloadsObj.Requests += [ordered]@{
|
||||
id = "$($guid)_deviceConfigurations"
|
||||
method = "GET"
|
||||
url = "/deviceManagement/deviceConfigurations/$($payload.payloadId)/?`$select=displayName"
|
||||
headers = @{"x-ms-command-name"="AssignmentFilterPayloadProxy_resolvePayloadNames_BatchItem"}
|
||||
}
|
||||
|
||||
$payloadsObj.Requests += [ordered]@{
|
||||
id = "$($guid)_mobileAppConfigurations"
|
||||
method = "GET"
|
||||
url = "/deviceAppManagement/mobileAppConfigurations/$($payload.payloadId)/?`$select=displayName"
|
||||
headers = @{"x-ms-command-name"="AssignmentFilterPayloadProxy_resolvePayloadNames_BatchItem"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($batchObjs.Count -gt 0)
|
||||
{
|
||||
$objName = Get-GraphObjectName $filter $objectType
|
||||
$responses = Invoke-GraphBatchRequest $batchObjs.Requests $objName -SkipWarnings
|
||||
<#
|
||||
$batchObj = [ordered]@{
|
||||
requests = @($batchObjs.Requests)
|
||||
}
|
||||
|
||||
$responses = (Invoke-GraphRequest -Url "`$batch" -Body ($batchObj | ConvertTo-Json -Depth 50 -Compress) -Method "POST").responses
|
||||
#>
|
||||
foreach($response in ($responses | Where Status -eq 200))
|
||||
{
|
||||
$payload = ($batchObjs | Where { $response.id -like "$($_.ID)*"}).Payload
|
||||
|
||||
if($payload.assignmentFilterType -eq "Include")
|
||||
{
|
||||
$filterType = "Include"
|
||||
}
|
||||
else
|
||||
{
|
||||
$filterType = "Exclude"
|
||||
}
|
||||
|
||||
$typeStr = $null
|
||||
if($payload.payloadType -eq "application")
|
||||
{
|
||||
$typeStr = Get-LanguageString "AppType.windowsClassicApp"
|
||||
}
|
||||
elseif($payload.payloadType -eq "win32app")
|
||||
{
|
||||
$typeStr = "Proactive Remediations"
|
||||
}
|
||||
else
|
||||
{
|
||||
$typeStr = (Get-PolicyTypeName $response.body.'@odata.type' $payload.payloadType)
|
||||
}
|
||||
|
||||
if(-not $typeStr) { $typeStr = $payload.payloadType}
|
||||
|
||||
$script:objFilterUsage += [PSCustomObject]@{
|
||||
FiterObject = $filter
|
||||
PayloadObject = $payload
|
||||
FilterName = $filter.displayName
|
||||
PolicyName = $response.body.displayName
|
||||
Type = $response.body.'@odata.type'
|
||||
PayloadType = $typeStr
|
||||
Mode = $filterType
|
||||
GroupID = $payload.groupId
|
||||
GroupName = $payload.groupId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($groupIDs.Count -gt 0)
|
||||
{
|
||||
$guid = (New-Guid).Guid
|
||||
$groupObjs = @()
|
||||
$x = 1
|
||||
foreach($groupID in $groupIDs)
|
||||
{
|
||||
if($loadedGroups.ContainsKey($groupID)) { continue }
|
||||
$groupObjs += [ordered]@{
|
||||
id= "$($guid)_$x"
|
||||
method="GET"
|
||||
url="/groups/$($groupID)/?`$select=displayName,id"
|
||||
headers = @{"x-ms-command-name"="AssignmentFilterPayloadProxy_resolvePayloadGroupAssignments_BatchItem"}
|
||||
}
|
||||
$x++
|
||||
}
|
||||
|
||||
if($groupObjs.Count -gt 0)
|
||||
{
|
||||
$responses = Invoke-GraphBatchRequest $groupObjs "Groups"
|
||||
<#
|
||||
$batchObj = [ordered]@{
|
||||
requests = @($groupObjs)
|
||||
}
|
||||
|
||||
$responses = (Invoke-GraphRequest -Url "`$batch" -Body ($batchObj | ConvertTo-Json -Depth 50 -Compress) -Method "POST").responses
|
||||
#>
|
||||
foreach($response in ($responses | Where Status -eq 200))
|
||||
{
|
||||
if($response.body.displayName -and $response.body.id -and $loadedGroups.ContainsKey($response.body.id) -eq $false)
|
||||
{
|
||||
$loadedGroups.Add($response.body.id, $response.body.displayName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($groupID in $loadedGroups.Keys)
|
||||
{
|
||||
$filterObj = $script:objFilterUsage | WHere GroupID -eq $groupID
|
||||
if($filterObj -and $loadedGroups[$groupID])
|
||||
{
|
||||
$filterObj.GroupName = $loadedGroups[$groupID]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Add-XamlEvent $script:frmIntuneFilterUsage "txtIntuneFilterUsageFilter" "Add_LostFocus" ({
|
||||
Invoke-IntueFilterUsageBoxChanged $this
|
||||
})
|
||||
|
||||
Add-XamlEvent $script:frmIntuneFilterUsage "txtIntuneFilterUsageFilter" "Add_GotFocus" ({
|
||||
if($this.Tag -eq "1" -and $this.Text -eq "Filter") { $this.Text = "" }
|
||||
Invoke-IntueFilterUsageBoxChanged $this ($script:frmIntuneFilterUsage.FindName("dgIntuneFilterUsage"))
|
||||
})
|
||||
|
||||
Add-XamlEvent $script:frmIntuneFilterUsage "txtIntuneFilterUsageFilter" "Add_TextChanged" ({
|
||||
Invoke-IntueFilterUsageBoxChanged $this ($script:frmIntuneFilterUsage.FindName("dgIntuneFilterUsage"))
|
||||
})
|
||||
|
||||
Invoke-IntueFilterUsageBoxChanged ($script:frmIntuneFilterUsage.FindName("txtIntuneFilterUsageFilter")) ($script:frmIntuneFilterUsage.FindName("dgIntuneFilterUsage"))
|
||||
|
||||
$ocList = [System.Collections.ObjectModel.ObservableCollection[object]]::new(@($script:objFilterUsage))
|
||||
|
||||
Set-XamlProperty $script:frmIntuneFilterUsage "dgIntuneFilterUsage" "ItemsSource" ([System.Windows.Data.CollectionViewSource]::GetDefaultView($ocList))
|
||||
}
|
||||
|
||||
function Invoke-IntueFilterUsageBoxChanged
|
||||
{
|
||||
param($txtBox, $dgObject)
|
||||
|
||||
$filter = $null
|
||||
|
||||
if($txtBox.Text.Trim() -eq "" -and $txtBox.IsFocused -eq $false)
|
||||
{
|
||||
$txtBox.FontStyle = "Italic"
|
||||
$txtBox.Tag = 1
|
||||
$txtBox.Text = "Filter"
|
||||
$txtBox.Foreground="Lightgray"
|
||||
}
|
||||
elseif($txtBox.Tag -eq "1" -and $txtBox.Text -eq "Filter" -and $txtBox.IsFocused -eq $false)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$txtBox.FontStyle = "Normal"
|
||||
$txtBox.Tag = $null
|
||||
$txtBox.Foreground="Black"
|
||||
$txtBox.Background="White"
|
||||
|
||||
if($txtBox.Text)
|
||||
{
|
||||
$filter = {
|
||||
param ($item)
|
||||
|
||||
return ($item.FilterName -match [regex]::Escape($txtBox.Text) -or $item.PolicyName -match [regex]::Escape($txtBox.Text) -or $item.GroupName -match [regex]::Escape($txtBox.Text) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($dgObject.ItemsSource -is [System.Windows.Data.ListCollectionView] -and $txtBox.IsFocused -eq $true)
|
||||
{
|
||||
# This causes odd behaviour with focus e.g. and item has to be clicked twice to be selected
|
||||
$dgObject.ItemsSource.Filter = $filter
|
||||
#$dgObject.ItemsSource.Refresh()
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ This module manages Authentication for the application with MSAL. It is also res
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.9.2'
|
||||
'3.9.3'
|
||||
}
|
||||
|
||||
$global:msalAuthenticator = $null
|
||||
@@ -770,7 +770,7 @@ function Get-MSALApp
|
||||
[void] $appBuilder.WithClientName("CloudAPIPowerShellManagement")
|
||||
[void] $appBuilder.WithClientVersion($PSVersionTable.PSVersion)
|
||||
|
||||
Add-MSALProxy $appBuilder
|
||||
Add-MSALProxy $appBuilder
|
||||
|
||||
# Ceck if correct version...
|
||||
#$appBuilder.WithMultiCloudSupport($true)
|
||||
@@ -1148,7 +1148,7 @@ function Connect-MSALUser
|
||||
#########################################################################################################
|
||||
try
|
||||
{
|
||||
Write-Log "Get tennant list"
|
||||
Write-Log "Get tenant list"
|
||||
|
||||
# Can we reuse the app used for login?
|
||||
$appBuilder = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($global:appObj.ClientID)
|
||||
|
||||
@@ -10,7 +10,7 @@ This module manages Microsoft Grap fuctions like calling APIs, managing graph ob
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.9.2'
|
||||
'3.9.3'
|
||||
}
|
||||
|
||||
$global:MSGraphGlobalApps = @(
|
||||
@@ -278,6 +278,7 @@ function Invoke-GraphAuthenticationUpdated
|
||||
$global:MigrationTableCacheId = $null
|
||||
$global:LoadedDependencyObjects = $null
|
||||
$global:migFileObj = $null
|
||||
$global:AADObjectCache = $null
|
||||
}
|
||||
|
||||
function Invoke-SettingsUpdated
|
||||
@@ -2719,7 +2720,7 @@ function Add-GroupMigrationObject
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
Write-Log "No group found with ID $($groupId). It might be deleted." 2
|
||||
}
|
||||
}
|
||||
@@ -2738,7 +2739,7 @@ function Add-GraphMigrationObject
|
||||
|
||||
# Check if object is already processed
|
||||
$graphObj = Get-GraphMigrationObject $objId
|
||||
if(-not $graphObj)
|
||||
if(-not $graphObj -and ($global:AADObjectCache.ContainsKey($objId) -eq $false))
|
||||
{
|
||||
# Get object info
|
||||
$graphObj = Invoke-GraphRequest "$($grapAPI)/$objId" -ODataMetadata "none" -NoError
|
||||
@@ -2764,7 +2765,8 @@ function Add-GraphMigrationObject
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Log "No $objTypeName found with ID $($groupId). It might be deleted." 2
|
||||
if($global:AADObjectCache.ContainsKey($objId) -eq $false) { $global:AADObjectCache.Add($objId, $null) }
|
||||
Write-Log "No $objTypeName found with ID $($objId). It might be deleted." 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3198,7 +3200,7 @@ function Export-GraphObject
|
||||
[IO.Directory]::CreateDirectory($exportFolder) | Out-Null
|
||||
}
|
||||
|
||||
if($chkExportAssignments.IsChecked -ne $true -and $obj.Assignments)
|
||||
if($global:chkExportAssignments.IsChecked -ne $true -and $obj.Assignments)
|
||||
{
|
||||
Remove-Property $obj "Assignments"
|
||||
}
|
||||
@@ -3436,10 +3438,9 @@ function Get-GraphBatchObjects
|
||||
{
|
||||
param($objects, $txtNameFilter)
|
||||
|
||||
$curBatch = 1
|
||||
$batchResults = @()
|
||||
$batchArr = @()
|
||||
$batchTotal = 0
|
||||
$skipped = 0
|
||||
$objectType = $null
|
||||
|
||||
foreach($obj in $objects)
|
||||
@@ -3449,7 +3450,7 @@ function Get-GraphBatchObjects
|
||||
|
||||
if($objName -and $txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
|
||||
{
|
||||
$batchTotal++
|
||||
$skipped++
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3460,31 +3461,74 @@ function Get-GraphBatchObjects
|
||||
url = (Get-GraphObject $obj.Object $obj.ObjectType -GetAPI)
|
||||
headers = @{"Accept"="application/json;odata.metadata=$ometadata"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($batchArr.Count -eq 0) { return }
|
||||
|
||||
if($batchArr.Count -eq 20 -or ($batchTotal + $batchArr.Count -eq $objects.Count))
|
||||
$batchResults = (Invoke-GraphBatchRequest $batchArr $objectType.Title).body
|
||||
|
||||
if($batchResults.Count -ne ($objects.Count - $skipped))
|
||||
{
|
||||
Write-Log "Not all batch objects returned. Expected $($objects.Count - $skipped) but only got $($batchResults.Count)"
|
||||
}
|
||||
|
||||
if($objectType -and $batchResults.Count -gt 0)
|
||||
{
|
||||
$batchResultsTmp = $batchResults
|
||||
$batchResults = Add-GraphObjectProperties $batchResultsTmp $objectType -property $objectType.ViewProperties
|
||||
|
||||
$curObj = 1
|
||||
foreach($obj in $batchResults)
|
||||
{
|
||||
if($obj.Object -and $obj.ObjectType.PostGetCommand)
|
||||
{
|
||||
Write-Status "Run PostGetCommand - $((Get-GraphObjectName $obj.Object $obj.ObjectType)) ($($curObj)/$(@($batchResults).Count))" -Force
|
||||
& $obj.ObjectType.PostGetCommand $obj $obj.ObjectType
|
||||
}
|
||||
$curObj++
|
||||
}
|
||||
}
|
||||
$batchResults
|
||||
}
|
||||
|
||||
function Invoke-GraphBatchRequest
|
||||
{
|
||||
param($batchObjects, $batchType, [switch]$SkipWarnings, [switch]$IncludedFailed)
|
||||
|
||||
$batchArr = @()
|
||||
$batchResults = @()
|
||||
$batchTotal = 0
|
||||
$curBatch = 1
|
||||
|
||||
foreach($obj in $batchObjects)
|
||||
{
|
||||
$batchArr += $obj
|
||||
|
||||
if($batchArr.Count -eq 20 -or (($batchTotal + $batchArr.Count) -eq $batchObjects.Count))
|
||||
{
|
||||
$batchObj = [PSCustomObject]@{
|
||||
requests = $batchArr
|
||||
}
|
||||
requests = @($batchArr)
|
||||
}
|
||||
|
||||
Write-Status "Get batch $curBatch $batchType" -Force
|
||||
|
||||
Write-Status "Get batch $curBatch $($obj.ObjectType.Title)" -Force
|
||||
$batchTotal += $batchArr.Count
|
||||
$json = $batchObj | ConvertTo-Json -Depth 50
|
||||
|
||||
$maxRetryCount = 10
|
||||
$curRetry = 0
|
||||
|
||||
do
|
||||
{
|
||||
{
|
||||
$retry = $false
|
||||
$retryArr = @()
|
||||
$retryAfter = 0
|
||||
$tmpResults = Invoke-GraphRequest -Url "`$batch" -Content $json -HttpMethod "POST" -Batch #-Url $api -property $obj.ObjectType.ViewProperties -objectType $obj.ObjectType -
|
||||
$tmpResults = Invoke-GraphRequest -Url "`$batch" -Body $json -Method "POST"
|
||||
|
||||
foreach($batchResult in ($tmpResults.responses | Sort -Property Id))
|
||||
{
|
||||
if($batchResult.Status -ne "200" -or -not $batchResult.body)
|
||||
{
|
||||
if($batchResult.Status -ge 300 -or -not $batchResult.body)
|
||||
{
|
||||
$reqObj = $batchObj.requests | where id -eq $batchResult.Id
|
||||
if($batchResult.Status -eq 429 -and $reqObj)
|
||||
{
|
||||
@@ -3500,11 +3544,19 @@ function Get-GraphBatchObjects
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Log "Batch result $($batchResult.Status) for URL $($reqObj.URL). Skipping..." 2
|
||||
if($SkipWarnings -ne $true)
|
||||
{
|
||||
Write-Log "Batch result $($batchResult.Status) for URL $($reqObj.URL). Skipping..." 2
|
||||
}
|
||||
|
||||
if($IncludedFailed -eq $true)
|
||||
{
|
||||
$batchResults += $batchResult
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
$batchResults += $batchResult.body
|
||||
$batchResults += $batchResult
|
||||
}
|
||||
|
||||
if($retryArr.Count -gt 0)
|
||||
@@ -3521,7 +3573,7 @@ function Get-GraphBatchObjects
|
||||
$retry = $true
|
||||
$tmpBatchObj = [PSCustomObject]@{
|
||||
requests = $retryArr
|
||||
}
|
||||
}
|
||||
$json = $tmpBatchObj | ConvertTo-Json -Depth 50
|
||||
Start-Sleep -Seconds $retryAfter
|
||||
}
|
||||
@@ -3533,27 +3585,11 @@ function Get-GraphBatchObjects
|
||||
}
|
||||
}
|
||||
|
||||
if($batchResults.Count -ne $objects.Count)
|
||||
if($batchResults.Count -ne $batchObjects.Count -and $SkipWarnings -ne $true)
|
||||
{
|
||||
Write-Log "Not all batch objects returned. Expected $($objects.Count) but only got $($batchResults.Count)"
|
||||
Write-Log "Not all batch objects returned. Expected $($batchObjects.Count) but only got $($batchResults.Count)" 2
|
||||
}
|
||||
|
||||
if($objectType -and $batchResults.Count -gt 0)
|
||||
{
|
||||
$batchResultsTmp = $batchResults
|
||||
$batchResults = Add-GraphObjectProperties $batchResultsTmp $objectType -property $objectType.ViewProperties
|
||||
|
||||
$curObj = 1
|
||||
foreach($obj in $batchResults)
|
||||
{
|
||||
if($obj.Object -and $obj.ObjectType.PostGetCommand)
|
||||
{
|
||||
Write-Status "Get full info - $((Get-GraphObjectName $obj.Object $obj.ObjectType)) ($($curObj)/$(@($batchResults).Count))" -Force
|
||||
& $obj.ObjectType.PostGetCommand $obj $obj.ObjectType
|
||||
}
|
||||
$curObj++
|
||||
}
|
||||
}
|
||||
$batchResults
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user