This commit is contained in:
Mikael Karlsson
2021-09-04 10:19:42 +10:00
parent 95bd8fc07c
commit 58abeeb9bd
37 changed files with 882 additions and 136 deletions

View File

@@ -11,7 +11,7 @@ Objects can be compared based on Properties or Documentatation info.
function Get-ModuleVersion
{
'1.0.6'
'1.0.7'
}
function Invoke-InitializeModule
@@ -399,8 +399,9 @@ function Invoke-BulkCompareNamedObjects
}
else
{
# Add objects that are exported but deleted
Write-Log "Object '$((Get-GraphObjectName $graphObj.Object $graphObj.ObjectType))' with id $($graphObj.Object.Id) has no matching object with the compate pattern" 2
$sourceObj = Get-GraphObject $graphObj.Object $graphObj.ObjectType
# Add objects that are exported but deleted/not imported etc.
Write-Log "Object '$((Get-GraphObjectName $graphObj.Object $graphObj.ObjectType))' with id $($graphObj.Object.Id) has no matching object with the compare pattern" 2
$compareProperties = @([PSCustomObject]@{
Object1Value = (Get-GraphObjectName $graphObj.Object $graphObj.ObjectType)
Object2Value = $null
@@ -828,7 +829,15 @@ function Compare-Objects
$script:compareProperties = @()
if($global:cbCompareType.SelectedItem.Compare)
if($obj1.'@OData.Type' -eq "#microsoft.graph.deviceManagementConfigurationPolicy" -or
$obj1.'@OData.Type' -eq "#microsoft.graph.deviceManagementIntent" -or
$obj1.'@OData.Type' -eq "#microsoft.graph.groupPolicyConfiguration")
{
# Always use documentation for Settings Catalog, Endpoint Security and Administrative Template policies
# These use Graph API for docummentation and all properties will be documented
$compareResult = Compare-ObjectsBasedonDocumentation $obj1 $obj2 $objectType
}
elseif($global:cbCompareType.SelectedItem.Compare)
{
$compareResult = & $global:cbCompareType.SelectedItem.Compare $obj1 $obj2 $objectType
}

View File

@@ -20,7 +20,7 @@ $global:documentationProviders = @()
function Get-ModuleVersion
{
'1.0.6'
'1.0.7'
}
function Invoke-InitializeModule
@@ -443,6 +443,10 @@ function Get-ObjectTypeString
elseif($objTypeId -eq "TenantAdmin")
{
return (Get-LanguageString "Titles.tenantAdmin")
}
elseif($objTypeId -eq "Azure")
{
return "Azure"
}
}
@@ -1600,10 +1604,14 @@ function Invoke-VerifyCondition
return $false
}
if($expression.value -eq $null)
if($expression.operator -eq "null")
{
$tmpRet = $null -eq $tmpProp.Value
}
elseif($null -eq $expression.value)
{
# Value not specified. Check if the property is set
$tmpRet = $tmpProp.Value -ne $null
$tmpRet = $null -ne $tmpProp.Value
}
elseif($expression.operator -eq "ne")
{
@@ -1737,7 +1745,7 @@ function Invoke-TranslateSection
{
$value = Get-LanguageString $prop.value
Add-PropertyInfo $prop $value $rawValue
Add-PropertyInfo $prop $value $rawValue $rawValue
}
}
elseif([String]::IsNullOrEmpty($prop.entityKey) -eq $false)
@@ -1791,6 +1799,7 @@ function Invoke-TranslateSection
{
$value = $cert.displayName
}
$rawValue = $value
}
}
elseif($prop.dataType -eq 200) # Multi option based on boolean value
@@ -2063,7 +2072,7 @@ function Get-PropertyInfo
$categoryStr = Get-Category $prop.category
}
if(!$jsonValue -and $rawValue -ne $null -and "$($rawValue)" -ne "")
if(!$jsonValue -and $null -ne $rawValue -and "$($rawValue)" -ne "")
{
$jsonValue = $rawValue | ConvertTo-Json -Depth 10 -Compress
}
@@ -2436,7 +2445,7 @@ function Invoke-TranslateOption
Value=$optionValue
}
Add-PropertyInfo $prop $optionValue -originalValue $propValue
Add-PropertyInfo $prop $optionValue $propValue
if($SkipOptionChildren -ne $true)
{
Invoke-ChildSections (Get-CustomChildObject $obj $prop) $option
@@ -3138,6 +3147,8 @@ function Show-DocumentationForm
{
foreach($groupId in ($objectTypes | Select GroupId -Unique).GroupId)
{
if(-not $groupId) { continue }
#$script:DocumentationLanguage = ?? $global:cbDocumentationLanguage.SelectedValue "en"
$script:DocumentationLanguage = "en"
$groupName = Get-ObjectTypeString -ObjectType $groupId
@@ -3375,9 +3386,24 @@ function Show-DocumentationForm
}
$tmpCurObjectType = $null
$tmpCurObjectGroup = $null
$allObjectTypeObjects = @()
foreach($tmpObj in ($sourceList))
{
$obj = Get-GraphObject $tmpObj.Object $tmpObj.ObjectType
if($allObjectTypeObjects.Count -gt 0 -and $tmpCurObjectGroup -ne $tmpObj.ObjectType.GroupId -and $tmpCurObjectType -ne $tmpObj.ObjectType.Id)
{
if($global:cbDocumentationType.SelectedItem.ProcessAllObjects)
{
& $global:cbDocumentationType.SelectedItem.ProcessAllObjects $allObjectTypeObjects
$allObjectTypeObjects = @()
}
else
{
Write-Log "ProcessAllObjects not defined. $tmpCurObjectType will not be documented" 3
}
}
$obj = Get-GraphObject $tmpObj.Object $tmpObj.ObjectType
if($obj)
{
@@ -3398,19 +3424,35 @@ function Show-DocumentationForm
{
# The provider takes care of all the processing
Write-Status "Run CustomProcess for $($global:cbDocumentationType.SelectedItem.Name)"
& $global:cbDocumentationType.SelectedItem.CustomProcess $obj $documentedObj
continue
$ret = & $global:cbDocumentationType.SelectedItem.CustomProcess $obj $documentedObj
if($ret -is [boolean] -and $ret -eq $true) { continue }
}
if($tmpCurObjectType -ne $obj.ObjectType.GroupId)
if($tmpCurObjectGroup -ne $obj.ObjectType.GroupId)
{
# A group matches a menu item in the protal but can contain multiple object types
# New object group e.g. Script, Tennant, Device Configuration
if($global:cbDocumentationType.SelectedItem.NewObjectGroup)
{
Write-Status "Run NewObjectGroup for $($global:cbDocumentationType.SelectedItem.Name)"
$ret = & $global:cbDocumentationType.SelectedItem.NewObjectGroup $obj $documentedObj
if($ret -is [boolean] -and $ret -eq $true) { continue }
}
$tmpCurObjectGroup = $obj.ObjectType.GroupId
}
if($tmpCurObjectType -ne $obj.ObjectType.Id)
{
# New object type e.g Administrative Template, VPN profile etc.
if($global:cbDocumentationType.SelectedItem.NewObjectType)
{
Write-Status "Run NewObjectType for $($global:cbDocumentationType.SelectedItem.Name)"
& $global:cbDocumentationType.SelectedItem.NewObjectType $obj $documentedObj
$ret = & $global:cbDocumentationType.SelectedItem.NewObjectType $obj $documentedObj
if($ret -is [boolean] -and $ret -eq $true) { continue }
}
$tmpCurObjectType = $obj.ObjectType.GroupId
}
$tmpCurObjectType = $obj.ObjectType.Id
$allObjectTypeObjects = @()
}
if($documentedObj)
{
@@ -3435,15 +3477,16 @@ function Show-DocumentationForm
$filteredSettings = @()
foreach($item in $documentedObj.Settings)
{
if(-not ($item.PSObject.Properties | Where Name -eq RawValue) -or $documentedObj.UpdateFilteredObject -eq $false)
if(-not ($item.PSObject.Properties | Where Name -eq "RawValue") -or $documentedObj.UpdateFilteredObject -eq $false)
{
$filteredSettings = $documentedObj.Settings
break
}
if($global:chkSkipNotConfigured.IsChecked -and (([String]::IsNullOrEmpty($item.RawValue) -or ("$($item.RawValue)" -eq "notConfigured"))))
if($global:chkSkipNotConfigured.IsChecked -and (($item.RawValue -isnot [array] -and ([String]::IsNullOrEmpty($item.RawValue) -or ("$($item.RawValue)" -eq "notConfigured"))) -or ($item.RawValue -is [array] -and ($item.RawValue | measure).Count -eq 0)))
{
# Skip unconfigured items e.g. properties with null values
# Note: This could removed configured properties if RawValue is not specified
continue
}
elseif($global:chkSkipNotConfigured.IsChecked -and $documentedObj.UnconfiguredProperties -and ($documentedObj.UnconfiguredProperties | Where EntityKey -eq $item.EntityKey))
@@ -3472,7 +3515,7 @@ function Show-DocumentationForm
}
}
if($updateNotConfigured -and ($item.RawValue -eq $null -or "$($item.RawValue)" -eq "" -or "$($item.RawValue)" -eq "notConfigured") -and [String]::IsNullOrEmpty($item.Value))
if($updateNotConfigured -and (($item.RawValue -isnot [array] -and ($null -eq $item.RawValue -or "$($item.RawValue)" -eq "" -or "$($item.RawValue)" -eq "notConfigured") -and [String]::IsNullOrEmpty($item.Value)) -or ($item.RawValue -is [array] -and ($item.RawValue | measure).Count -eq 0)))
{
$item.Value = $notConfiguredText
}
@@ -3489,12 +3532,36 @@ function Show-DocumentationForm
$documentedObj | Add-Member Noteproperty -Name "FilteredSettings" -Value $filteredSettings -Force
& $global:cbDocumentationType.SelectedItem.Process $obj.Object $obj.ObjectType $documentedObj
if($obj.ObjectType.DocumentAll -eq $true)
{
$allObjectTypeObjects += [PSCustomObject]@{
Object = $obj
DocumentationObject = $documentedObj
}
}
else
{
& $global:cbDocumentationType.SelectedItem.Process $obj.Object $obj.ObjectType $documentedObj
}
}
}
}
}
if($allObjectTypeObjects.Count -gt 0)
{
if($global:cbDocumentationType.SelectedItem.ProcessAllObjects)
{
& $global:cbDocumentationType.SelectedItem.ProcessAllObjects $allObjectTypeObjects
$allObjectTypeObjects = @()
}
else
{
Write-Log "ProcessAllObjects not defined. $tmpCurObjectType will not be documented" 3
}
}
if($global:cbDocumentationType.SelectedItem.PostProcess)
{
Write-Status "Run PostProcess for $($global:cbDocumentationType.SelectedItem.Name)"

View File

@@ -10,7 +10,7 @@ This module will also document some objects based on PowerShell functions
function Get-ModuleVersion
{
'1.0.4'
'1.0.5'
}
function Invoke-InitializeModule
@@ -306,6 +306,20 @@ function Add-CDDocumentCustomProfileValue
}
}
}
elseif($obj.'@OData.Type' -like "#microsoft.graph.windows10VpnConfiguration")
{
if($prop.EntityKey -eq "enableSplitTunneling" -and $prop.enabled -eq $false)
{
# SplitTunneling settings are moved to another file
return $false
}
elseif($prop.EntityKey -eq "eapXml" -and $obj.eapXml)
{
$propValue = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($obj.eapXml))
Add-PropertyInfo $prop $propValue -originalValue $propValue
return $false
}
}
}
<#
@@ -638,6 +652,11 @@ function Add-CDDocumentCustomProfileProperty
$obj | Add-Member Noteproperty -Name "useMicrosoftSearchAsDefault" -Value ($obj.excludedApps.bing -eq $false)
if($obj.officeConfigurationXml)
{
$xmlConfig = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($obj.officeConfigurationXml))
$obj | Add-Member Noteproperty -Name "MSAppsConfigXml" -Value $xmlConfig
}
$retValue = $true
}
elseif($obj.'@OData.Type' -like "#microsoft.graph.windowsWifiEnterpriseEAPConfiguration")
@@ -1037,6 +1056,12 @@ function Add-CDDocumentCustomProfileProperty
$obj | Add-Member Noteproperty -Name "returnCodes" -Value ($returnCodes -join $objSeparator) -Force
$obj | Add-Member Noteproperty -Name "win10Release" -Value (Get-LanguageString "MinimumOperatingSystem.Windows.V10Release.release$($obj.minimumSupportedWindowsRelease)") -Force
}
elseif($obj.'@OData.Type' -eq "#microsoft.graph.deviceHealthScript")
{
$obj | Add-Member Noteproperty -Name "detectionScriptAdded" -Value (-not [String]::IsNullOrEmpty($obj.detectionScriptContent))
$obj | Add-Member Noteproperty -Name "remediationScriptAdded" -Value (-not [String]::IsNullOrEmpty($obj.remediationScriptContent))
$obj | Add-Member Noteproperty -Name "useLoggedOnCredentials" -Value ($obj.runAsAccount -ne "system")
}
if(($obj.PSObject.Properties | where Name -eq "securityRequireSafetyNetAttestationBasicIntegrity") -and
($obj.PSObject.Properties | where Name -eq "securityRequireSafetyNetAttestationCertifiedDevice"))

View File

@@ -3,7 +3,7 @@
#https://docs.microsoft.com/en-us/office/vba/api/overview/word
function Get-ModuleVersion
{
'1.0.3'
'1.0.4'
}
function Invoke-InitializeModule
@@ -27,9 +27,10 @@ function Invoke-InitializeModule
OutputOptions = (Add-WordOptionsControl)
Activate = { Invoke-WordActivate @args }
PreProcess = { Invoke-WordPreProcessItems @args }
NewObjectType = { Invoke-WordNewObjectType @args }
NewObjectGroup = { Invoke-WordNewObjectGroup @args }
Process = { Invoke-WordProcessItem @args }
PostProcess = { Invoke-WordPostProcessItems @args }
ProcessAllObjects = { Invoke-WordProcessAllObjects @args }
})
$script:columnHeaders = @{
@@ -389,7 +390,7 @@ function Set-WordContentControlText
}
}
function Invoke-WordNewObjectType
function Invoke-WordNewObjectGroup
{
param($obj, $documentedObj)
@@ -408,7 +409,7 @@ function Invoke-WordProcessItem
Add-DocText $objName $global:txtWordHeader2Style.Text
$script:doc.Application.Selection.TypeParagraph()
$script:doc.Application.Selection.TypeParagraph()
try
{
@@ -517,6 +518,45 @@ function Invoke-WordProcessItem
}
}
function Invoke-WordProcessAllObjects
{
param($allObjectTypeObjects)
if(($allObjectTypeObjects | measure).Count -eq 0) { return }
$tmpObj = $allObjectTypeObjects | Select -First 1
if(-not $tmpObj) { return }
$objectType = $tmpObj.Object.ObjectType
if($objectType.Id -eq "ScopeTags")
{
$objTypeName = Get-LanguageString "SettingDetails.scopeTags"
Add-DocText $objTypeName $global:txtWordHeader2Style.Text
$script:doc.Application.Selection.TypeParagraph()
$items = @()
$nameLabel = Get-LanguageString "Inputs.displayNameLabel"
$descriptionLable = Get-LanguageString "TableHeaders.description"
foreach($obj in $allObjectTypeObjects.Object.Object)
{
$items += [PSCustomObject]@{
$nameLabel = $obj.displayName
ID = $obj.Id
$descriptionLable = $obj.Description
}
}
$items = $items | Sort -Property $nameLabel
$properties = @($nameLabel,"id",$descriptionLable)
Add-DocTableItems $tmpObj.Object.Object $tmpObj.Object.ObjectType $items $properties -captionOverride (Get-LanguageString "SettingDetails.scopeTags")
}
}
function Invoke-WordTranslateColumnHeader
{
param($columnName)
@@ -529,6 +569,13 @@ function Invoke-WordTranslateColumnHeader
(?? $lngText $columnName)
}
function Invoke-WordCustomProcessItems
{
param($obj, $documentedObj)
}
function Set-WordColumnHeaderLanguageId
{
param($columnName, $lngId)
@@ -547,7 +594,7 @@ function Set-WordColumnHeaderLanguageId
function Add-DocTableItems
{
param($obj, $objectType, $items, $properties, $lngId, [switch]$AddCategories, [switch]$AddSubcategories)
param($obj, $objectType, $items, $properties, $lngId, [switch]$AddCategories, [switch]$AddSubcategories, $captionOverride)
$tblHeaderStyle = $global:txtWordTableHeaderStyle.Text
$tblCategoryStyle = $global:txtWordCategoryHeaderStyle.Text
@@ -559,7 +606,11 @@ function Add-DocTableItems
$script:docTable.ApplyStyleHeadingRows = $true
Set-DocObjectStyle $script:docTable $global:txtWordTableStyle.Text
if($lngId)
if($captionOverride)
{
$caption = $captionOverride
}
elseif($lngId)
{
$caption = "$((Get-LanguageString $lngId)) - $((Get-GraphObjectName $obj $objectType))"
}

View File

@@ -10,7 +10,7 @@ This module is for the Endpoint Manager/Intune View. It manages Export/Import/Co
#>
function Get-ModuleVersion
{
'3.1.9'
'3.1.10'
}
function Invoke-InitializeModule
@@ -106,9 +106,8 @@ function Invoke-InitializeModule
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
PropertiesToRemove = @("privacyAccessControls")
PostFileImportCommand = { Start-PostFileImportDeviceConfiguration @args }
PreCopyCommand = { Start-PreCopyDeviceConfiguration @args }
PostCopyCommand = { Start-PostCopyDeviceConfiguration @args }
PostExportCommand = { Start-PostExportDeviceConfiguration @args }
PostGetCommand = { Start-PostGetDeviceConfiguration @args }
GroupId = "DeviceConfiguration"
})
@@ -204,6 +203,7 @@ function Invoke-InitializeModule
Permissons=@("Organization.ReadWrite.All")
Icon = "Branding"
SkipRemoveProperties = @('Id')
GroupId = "Azure"
})
Add-ViewItem (New-Object PSObject -Property @{
@@ -510,6 +510,7 @@ function Invoke-InitializeModule
Permissons=@("DeviceManagementRBAC.ReadWrite.All")
PostExportCommand = { Start-PostExportScopeTags @args }
ImportOrder = 10
DocumentAll = $true
GroupId = "TenantAdmin"
})
@@ -954,17 +955,17 @@ function Start-PostCopyDeviceConfiguration
}
}
function Start-PreCopyDeviceConfiguration
function Start-PostGetDeviceConfiguration
{
param($obj, $objectType, $newName)
if(($obj.omaSettings | measure).Count -gt 0)
param($obj, $objectType)
if(($obj.Object.omaSettings | measure).Count -gt 0)
{
foreach($omaSetting in ($obj.omaSettings | Where isEncrypted -eq $true))
foreach($omaSetting in ($obj.Object.omaSettings | Where isEncrypted -eq $true))
{
if($omaSetting.isEncrypted -eq $false) { continue }
$xmlValue = Invoke-GraphRequest -Url "/deviceManagement/deviceConfigurations/$($obj.Id)/getOmaSettingPlainTextValue(secretReferenceValueId='$($omaSetting.secretReferenceValueId)')"
$xmlValue = Invoke-GraphRequest -Url "/deviceManagement/deviceConfigurations/$($obj.Object.Id)/getOmaSettingPlainTextValue(secretReferenceValueId='$($omaSetting.secretReferenceValueId)')"
if($xmlValue.Value)
{
$omaSetting.isEncrypted = $false
@@ -982,49 +983,7 @@ function Start-PreCopyDeviceConfiguration
}
}
}
}
$false
}
function Start-PostExportDeviceConfiguration
{
param($obj, $objectType, $path)
$fileName = "$path\$((Remove-InvalidFileNameChars (Get-GraphObjectName $obj $objectType))).json"
if(($obj.omaSettings | measure).Count -gt 0)
{
$updated = $false
foreach($omaSetting in @(($obj.omaSettings | Where isEncrypted -eq $true)))
{
if($omaSetting.isEncrypted -eq $false) { continue }
# Get decrypted value and mark OMA-URI setting as not encrypted
$xmlValue = Invoke-GraphRequest -Url "/deviceManagement/deviceConfigurations/$($obj.Id)/getOmaSettingPlainTextValue(secretReferenceValueId='$($omaSetting.secretReferenceValueId)')"
if($xmlValue.Value)
{
$omaSetting.isEncrypted = $false
$omaSetting.secretReferenceValueId = $null
if($omaSetting.'@odata.type' -eq "#microsoft.graph.omaSettingStringXml" -or
$omaSetting.'value@odata.type' -eq "#Binary")
{
$Bytes = [System.Text.Encoding]::UTF8.GetBytes($xmlValue.Value)
$omaSetting.value = [Convert]::ToBase64String($bytes)
}
else
{
$omaSetting.value = $xmlValue.Value
}
$updated = $true
}
}
if($updated)
{
$obj | ConvertTo-Json -Depth 20 | Out-File -LiteralPath $fileName -Force
}
}
}
}
#endregion
@@ -1251,6 +1210,22 @@ function Add-ScriptExtensions
{
$tmp.Children.Insert($index, $btnDownload)
}
$btnDownload = New-Object System.Windows.Controls.Button
$btnDownload.Content = 'Edit'
$btnDownload.Name = 'btnEdit'
$btnDownload.Margin = "0,0,5,0"
$btnDownload.Width = "100"
$btnDownload.Add_Click({
Invoke-EditScript
})
$tmp = $form.FindName($buttonPanel)
if($tmp)
{
$tmp.Children.Insert($index, $btnDownload)
}
}
function Add-ScriptExportExtensions
@@ -1280,7 +1255,7 @@ function Start-PostExportScripts
{
Write-Log "Export script $($obj.FileName)"
$fileName = [IO.Path]::Combine($exportPath, $obj.FileName)
[System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($obj.scriptContent)) | Out-File -LiteralPath $fileName -Force
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($obj.scriptContent)) | Out-File -LiteralPath $fileName -Force
}
}
@@ -1306,6 +1281,87 @@ function Invoke-DownloadScript
}
}
function Invoke-EditScript
{
if(-not $global:dgObjects.SelectedItem.Object.id) { return }
$obj = (Get-GraphObject $global:dgObjects.SelectedItem $global:curObjectType)
Write-Status ""
if(-not $obj.Object.scriptContent) { return }
$script:currentScriptObject = $obj
$script:editForm = Get-XamlObject ($global:AppRootFolder + "\Xaml\EditScriptDialog.xaml")
if(-not $script:editForm) { return }
Set-XamlProperty $script:editForm "txtEditScriptTitle" "Text" "Edit: $($obj.Object.displayName)"
$scriptText = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($obj.Object.scriptContent))
Set-XamlProperty $script:editForm "txtScriptText" "Text" $scriptText
$script:currentModal = $null
if($global:grdModal.Children.Count -gt 0)
{
$script:currentModal = $global:grdModal.Children[0]
}
Add-XamlEvent $script:editForm "btnSaveScriptEdit" "add_click" ({
$scriptText = Get-XamlProperty $script:editForm "txtScriptText" "Text"
$bytes = [System.Text.Encoding]::UTF8.GetBytes($scriptText)
$encodedText = [Convert]::ToBase64String($bytes)
if($script:currentScriptObject.Object.scriptContent -ne $encodedText)
{
# Save script
if(([System.Windows.MessageBox]::Show("Are you sure you want to update the script?`n`nObject:`n$($script:currentScriptObject.displayName)", "Update script?", "YesNo", "Warning")) -eq "Yes")
{
Write-Status "Update $($script:currentScriptObject.displayName)"
$obj = $script:currentScriptObject.Object | ConvertTo-Json -Depth 20 | ConvertFrom-Json
$obj.scriptContent = $encodedText
Start-GraphPreImport $obj $script:currentScriptObject.ObjectType
foreach($prop in $script:currentScriptObject.ObjectType.PropertiesToRemoveForUpdate)
{
Remove-Property $obj $prop
}
Remove-Property $obj "Assignments"
Remove-Property $obj "isAssigned"
$json = ConvertTo-Json $obj -Depth 15
$objectUpdated = (Invoke-GraphRequest -Url "$($script:currentScriptObject.ObjectType.API)/$($script:currentScriptObject.Object.Id)" -Content $json -HttpMethod "PATCH")
if(-not $objectUpdated)
{
Write-Log "Failed to update script" 3
[System.Windows.MessageBox]::Show("Failed to save the script object. See log for more information","Update failed!", "OK", "Error")
}
Write-Status ""
}
}
$global:grdModal.Children.Clear()
if($script:currentModal)
{
$global:grdModal.Children.Add($script:currentModal)
}
[System.Windows.Forms.Application]::DoEvents()
})
Add-XamlEvent $script:editForm "btnCancelScriptEdit" "add_click" ({
$global:grdModal.Children.Clear()
if($script:currentModal)
{
$global:grdModal.Children.Add($script:currentModal)
}
[System.Windows.Forms.Application]::DoEvents()
})
$global:grdModal.Children.Clear()
$script:editForm.SetValue([System.Windows.Controls.Grid]::RowProperty,1)
$script:editForm.SetValue([System.Windows.Controls.Grid]::ColumnProperty,1)
$global:grdModal.Children.Add($script:editForm) | Out-Null
[System.Windows.Forms.Application]::DoEvents()
}
#endregion
#region Terms and Conditions

View File

@@ -0,0 +1,249 @@
<#
.SYNOPSIS
Module for listing Intune assignments
.DESCRIPTION
.NOTES
Author: Mikael Karlsson
#>
function Get-ModuleVersion
{
'1.0.0'
}
function Invoke-InitializeModule
{
Add-EMToolsViewItem (New-Object PSObject -Property @{
Title = "Intune Assignments"
Id = "IntuneAssignments"
ViewID = "EMTools"
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
Icon="DeviceConfiguration"
ShowViewItem = { Show-EMToolsIntuneAssignments }
})
}
function Show-EMToolsIntuneAssignments
{
if(-not $script:frmIntuneAssignments)
{
$script:frmIntuneAssignments = Get-XamlObject ($global:AppRootFolder + "\Xaml\EndpointManagerToolsIntuneAssignments.xaml") #-AddVariables
if(-not $script:frmIntuneAssignments) { return }
Add-XamlEvent $script:frmIntuneAssignments "btnBrowseIntuneAssignmentsExportPath" "add_click" ({
$folder = Get-Folder (Get-XamlProperty $script:frmIntuneAssignments "txtIntuneAssignmentsExportPath" "Text") "Select root folder for exported files"
if($folder)
{
Set-XamlProperty $script:frmIntuneAssignments "txtIntuneAssignmentsExportPath" "Text" $folder
}
})
Add-XamlEvent $script:frmIntuneAssignments "btnGetIntuneAssignments" "add_click" ({
$folder = Get-XamlProperty $script:frmIntuneAssignments "txtIntuneAssignmentsExportPath" "Text"
if($folder)
{
Write-Status "Get Intune Assignments"
Get-EMIntuneAssignments $folder
Write-Status ""
}
})
Add-XamlEvent $script:frmIntuneAssignments "btnIntuneAssignmentsCopy" "add_click" ({
$script:objAssignments | Select Name, Type, IncludedString, ExcludedString | ConvertTo-Csv -NoTypeInformation | Set-Clipboard
})
Add-XamlEvent $script:frmIntuneAssignments "btnIntuneAssignmentsSave" "add_click" ({
$dlgSave = New-Object -Typename System.Windows.Forms.SaveFileDialog
#$dlgSave.InitialDirectory = Get-SettingValue "IntuneRootFolder" $env:Temp
$dlgSave.FileName = $obj.FileName
$sf.DefaultExt = "*.csv"
$sf.Filter = "CSV (*.csv)|*.csv|All files (*.*)| *.*"
if($dlgSave.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK -and $dlgSave.Filename)
{
$script:objAssignments | Select Name, Type, IncludedString, ExcludedString | ConvertTo-Csv -NoTypeInformation | Out-File -LiteralPath $dlgSave.Filename -Encoding UTF8 -Force
}
})
}
$global:grdToolsMain.Children.Clear()
$global:grdToolsMain.Children.Add($frmIntuneAssignments)
}
function Get-EMIntuneAssignmentInfo
{
param($rootDir)
Write-Status "Gather Export Information"
$path = "$rootDir\Groups"
$script:htGroups = @{}
foreach($file in (Get-Item -path "$path\*.json"))
{
$graphObj = (ConvertFrom-Json (Get-Content -LiteralPath $file.FullName -Raw))
$htGroups.Add($graphObj.Id, $graphObj)
}
$script:fileArr = @()
foreach($path in [IO.Directory]::EnumerateDirectories($rootDir))
{
if($path -eq "$rootDir\Groups") { continue }
foreach($file in (Get-Item -path "$path\*.json" -Exclude @("*_settings.json","*_assignments.json")))
{
$graphObj = (ConvertFrom-Json (Get-Content -LiteralPath $file.FullName -Raw))
$obj = New-Object PSObject -Property @{
FileName = $file.Name
FileInfo = $file
Selected = $SelectedStatus
Object = $graphObj
}
$script:fileArr += $obj
}
}
}
function Get-EMIntuneAssignments
{
param($folder)
Set-XamlProperty $script:frmIntuneAssignments "dgIntuneAssignments" "ItemsSource" $null
$folderDI = [IO.DirectoryInfo]$folder
if(-not $folderDI.Exists) { return }
Get-EMIntuneAssignmentInfo $folder
Write-Status "Collect exported assignments"
$script:objAssignments = @()
foreach($fileObj in $script:fileArr)
{
$obj = New-Object PSObject -Property @{
Object = $fileObj.Object
Name = $fileObj.Object.DisplayName
Type = $null
Included = $null
Excluded = $null
IncludedString = ""
ExcludedString = ""
}
$obj.Included = @()
$obj.Excluded = @()
if($fileObj.Object.'@OData.Type')
{
$obj.Type = $fileObj.Object.'@OData.Type'.Split('.')[-1]
}
else
{
$obj.Type = $file.Directory.Parent.Name
}
foreach($assignment in $fileObj.Object.assignments)
{
$assignmentObj = $null
$included = $true
if($assignment.target.'@odata.type' -eq "#microsoft.graph.groupAssignmentTarget" -or
$assignment.target.'@odata.type' -eq "#microsoft.graph.exclusionGroupAssignmentTarget")
{
if($script:htGroups.ContainsKey($assignment.target.groupId))
{
$assignmentObj = $script:htGroups[$assignment.target.groupId].displayName
}
else
{
Write-Warning "Could not find a group with ID $($assignment.target.groupId)"
}
$included = $assignment.target.'@odata.type' -eq "#microsoft.graph.groupAssignmentTarget"
}
elseif($assignment.target.'@odata.type' -eq "#microsoft.graph.allDevicesAssignmentTarget")
{
$assignmentObj = "All Devices"
}
elseif($assignment.target.'@odata.type' -eq "#microsoft.graph.allLicensedUsersAssignmentTarget")
{
$assignmentObj = "All Users"
}
if($included)
{
$obj.Included += $assignmentObj
}
else
{
$obj.Excluded += $assignmentObj
}
}
$obj.IncludedString = $obj.Included -join ";"
$obj.ExcludedString = $obj.Excluded -join ";"
$script:objAssignments += $obj
}
Add-XamlEvent $script:frmIntuneAssignments "txtIntuneAssignmentsFilter" "Add_LostFocus" ({
Invoke-IntueAssignmentFilterBoxChanged $this
})
Add-XamlEvent $script:frmIntuneAssignments "txtIntuneAssignmentsFilter" "Add_GotFocus" ({
if($this.Tag -eq "1" -and $this.Text -eq "Filter") { $this.Text = "" }
Invoke-IntueAssignmentFilterBoxChanged $this ($script:frmIntuneAssignments.FindName("dgIntuneAssignments"))
})
Add-XamlEvent $script:frmIntuneAssignments "txtIntuneAssignmentsFilter" "Add_TextChanged" ({
Invoke-IntueAssignmentFilterBoxChanged $this ($script:frmIntuneAssignments.FindName("dgIntuneAssignments"))
})
Invoke-IntueAssignmentFilterBoxChanged ($script:frmIntuneAssignments.FindName("txtIntuneAssignmentsFilter")) ($script:frmIntuneAssignments.FindName("dgIntuneAssignments"))
$ocList = [System.Collections.ObjectModel.ObservableCollection[object]]::new(@($script:objAssignments))
Set-XamlProperty $script:frmIntuneAssignments "dgIntuneAssignments" "ItemsSource" ([System.Windows.Data.CollectionViewSource]::GetDefaultView($ocList))
}
function Invoke-IntueAssignmentFilterBoxChanged
{
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"
}
else
{
if($txtBox.Tag -eq "1" -and $txtBox.Text -eq "Filter" -and $txtBox.IsFocused -eq $false) { return }
$txtBox.FontStyle = "Normal"
$txtBox.Tag = $null
$txtBox.Foreground="Black"
$txtBox.Background="White"
if($txtBox.Text)
{
$filter = {
param ($item)
return ( $item.Name -match [regex]::Escape($txtBox.Text) -or $item.IncludedString -match [regex]::Escape($txtBox.Text) -or $item.ExcludedString -match [regex]::Escape($txtBox.Text) )
}
}
}
if($dgObject.ItemsSource -is [System.Windows.Data.ListCollectionView])
{
# 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()
}
}

View File

@@ -17,53 +17,19 @@ This module is for the Intune Tools View.
.NOTES
Author: Mikael Karlsson
#>
$global:EMToolsViewObject = $null
function Get-ModuleVersion
{
'1.0.0'
'1.0.1'
}
function Invoke-InitializeModule
{
$viewPanel = Get-XamlObject ($global:AppRootFolder + "\Xaml\EndpointManagerTools.xaml") -AddVariables
if(-not $viewPanel) { return }
Add-ADMXRegClasses
Add-ADMXRegClasses
#Add menu group and items
$global:EMToolsViewObject = (New-Object PSObject -Property @{
Title = "Intune Tools"
Description = "Additional tools for managing Intune"
ID = "EMTools"
ViewPanel = $viewPanel
ItemChanged = { Show-EMTool }
Activating = { Invoke-EMToolsActivatingView }
Authentication = (Get-MSALAuthenticationObject)
Authenticate = { Invoke-EMToolsAuthenticateToMSAL }
AppInfo = (Get-GraphAppInfo "EM" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547")
SaveSettings = { Invoke-EMSaveSettings }
Permissions = @()
})
Add-ViewObject $global:EMToolsViewObject
Add-ViewItem (New-Object PSObject -Property @{
Title = "ADMX Import"
Id = "ADMXImport"
ViewID = "EMTools"
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
Icon="DeviceConfiguration"
ShowViewItem = { Show-ADMXIngestion }
})
Add-ViewItem (New-Object PSObject -Property @{
Title = "Reg Values"
Id = "ADMXRegValues"
ViewID = "EMTools"
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
Icon="DeviceConfiguration"
ShowViewItem = { Show-ADMXRegValues }
})
Add-EMToolsViewItem
# https://docs.microsoft.com/en-us/windows/client-management/mdm/win32-and-centennial-app-policy-configuration
# ADMX ingestion cannot write to these paths:
@@ -95,6 +61,58 @@ function Invoke-InitializeModule
"@
}
function Add-EMToolsViewItem
{
param($viewItem)
if(-not $global:EMToolsViewObject)
{
$viewPanel = Get-XamlObject ($global:AppRootFolder + "\Xaml\EndpointManagerTools.xaml") -AddVariables
if(-not $viewPanel) { return }
#Add menu group and items
$global:EMToolsViewObject = (New-Object PSObject -Property @{
Title = "Intune Tools"
Description = "Additional tools for managing Intune"
ID = "EMTools"
ViewPanel = $viewPanel
ItemChanged = { Show-EMTool }
Activating = { Invoke-EMToolsActivatingView }
Authentication = (Get-MSALAuthenticationObject)
Authenticate = { Invoke-EMToolsAuthenticateToMSAL }
AppInfo = (Get-GraphAppInfo "EM" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547")
SaveSettings = { Invoke-EMSaveSettings }
Permissions = @()
})
Add-ViewObject $global:EMToolsViewObject
Add-ViewItem (New-Object PSObject -Property @{
Title = "ADMX Import"
Id = "ADMXImport"
ViewID = "EMTools"
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
Icon="DeviceConfiguration"
ShowViewItem = { Show-ADMXIngestion }
})
Add-ViewItem (New-Object PSObject -Property @{
Title = "Reg Values"
Id = "ADMXRegValues"
ViewID = "EMTools"
Permissons=@("DeviceManagementConfiguration.ReadWrite.All")
Icon="DeviceConfiguration"
ShowViewItem = { Show-ADMXRegValues }
})
}
if($viewItem)
{
Add-ViewItem $viewItem
}
}
function Invoke-EMToolsActivatingView
{