New features and fixes
This commit is contained in:
Mikael Karlsson
2022-03-01 17:54:14 +11:00
parent 5534eb368e
commit 46435b5717
70 changed files with 43671 additions and 5340 deletions

View File

@@ -20,7 +20,7 @@ $global:documentationProviders = @()
function Get-ModuleVersion
{
'1.0.8'
'1.1.0'
}
function Invoke-InitializeModule
@@ -628,12 +628,21 @@ function Add-ScopeTagStrings
if(($obj.roleScopeTagIds | measure).Count -gt 0)
{
foreach($scopeTagId in $obj.roleScopeTagIds)
{
$scopeTagObj = $script:scopeTags | Where Id -eq $scopeTagId
if($scopeTagObj)
{
$scopeTagName = $scopeTagId
if($scopeTagId -eq "0")
{
$objScopeTags += $scopeTagObj.displayName
$scopeTagName = (Get-LanguageString "SettingDetails.default")
}
elseif($script:scopeTags)
{
$scopeTagObj = $script:scopeTags | Where Id -eq $scopeTagId
if($scopeTagObj.displayName)
{
$scopeTagName = $scopeTagObj.displayName
}
}
$objScopeTags += $scopeTagName
}
}
if($objScopeTags.Count -gt 0)
@@ -1793,7 +1802,11 @@ function Invoke-TranslateSection
elseif($rawValue -eq $null -and ![String]::IsNullOrEmpty($prop.defaultValue) -and $global:chkSetDefaultValue.IsChecked)
{
$propValue = $prop.defaultValue
}
}
elseif($rawValue -eq $null -and ![String]::IsNullOrEmpty($prop.emptyValueResourceKey) -and $global:chkSetDefaultValue.IsChecked)
{
$propValue = Get-LanguageString $prop.emptyValueResourceKey
}
else
{
$propValue = $rawValue
@@ -1834,6 +1847,11 @@ function Invoke-TranslateSection
}
$rawValue = $value
}
elseif($script:currentObject.'@ObjectFromFile' -eq $true)
{
$value = "##TBD - Linked Certificate"
$rawValue = $value
}
}
elseif($prop.dataType -eq 200) # Multi option based on boolean value
{
@@ -2064,6 +2082,8 @@ function Add-PropertyInfo
}
$script:objectSettingsData += Get-PropertyInfo $prop $value $originalValue $jsonValue
Invoke-CustomPostAddValue $prop
}
function Add-PropertyInfoObject
@@ -2110,6 +2130,15 @@ function Get-PropertyInfo
$jsonValue = $rawValue | ConvertTo-Json -Depth 10 -Compress
}
if($prop.emptyValueResourceKey)
{
$defValue = Get-LanguageString $prop.emptyValueResourceKey
}
else
{
$defValue = $prop.defaultValue
}
return New-Object PSObject -Property @{
Name=$name
Description=$description
@@ -2121,7 +2150,7 @@ function Get-PropertyInfo
DataType=$prop.dataType
RawValue=$originalValue
RawJsonValue=$jsonValue
DefaultValue=$prop.defaultValue
DefaultValue=$defValue
UnconfiguredValue=$prop.unconfiguredValue
Enabled=$prop.Enabled
EntityKey=$prop.EntityKey
@@ -2156,6 +2185,23 @@ function Get-CustomProfileValue
}
}
function Invoke-CustomPostAddValue
{
param($prop)
foreach($docProvider in ($global:documentationProviders | Sort -Property Priority))
{
if($docProvider.PostAddValue)
{
$retObj = & $docProvider.PostAddValue $script:currentObject $prop $script:propertySeparator $script:objectSeparator
if($retObj -ne $null)
{
return $retObj
}
}
}
}
function Get-CustomPropertyObject
{
param($obj, $prop)
@@ -2852,6 +2898,8 @@ function Invoke-TranslateAssignments
}
}
$groupInfo = $null
if($groupIds.Count -gt 0)
{
$ht = @{}
@@ -2861,6 +2909,12 @@ function Invoke-TranslateAssignments
$groupInfo = (Invoke-GraphRequest -Url "/directoryObjects/getByIds?`$select=displayName,id" -Content $body -Method "Post").Value
}
if(($null -eq $groupInfo -or ($groupInfo | measure).Count -eq 0) -and $obj."@ObjectFromFile" -eq $true -and $script:migTable)
{
### Get group info from mig table when documenting from file if there's no access to the environment
$groupInfo = $script:migTable.Objects | Where Type -eq "Group"
}
if($filterIds.Count -gt 0)
{
@@ -3152,7 +3206,10 @@ function Show-DocumentationForm
$objectTypes,
[Switch]
[Parameter(Mandatory=$false,ParameterSetName = "Objects")]
$SelectedDocuments)
$SelectedDocuments,
[Switch]
$ShowFolderSource
)
$objectList = @()
@@ -3226,6 +3283,22 @@ function Show-DocumentationForm
$global:btnAddToDocumentationList.Visibility = "Collapsed"
}
if($ShowFolderSource -ne $true)
{
$global:grdDocumentFromFolder.Visibility = "Collapsed"
$global:spDocumentFromFolder.Visibility = "Collapsed"
}
else
{
Add-XamlEvent $script:docForm "browseDocumentFromFolder" "add_click" {
$folder = Get-Folder (Get-XamlProperty $script:docForm "txtDocumentFromFolder" "Text") "Select root folder for export files"
if($folder)
{
Set-XamlProperty $script:docForm "txtDocumentFromFolder" "Text" $folder
}
}
}
$column = Get-GridCheckboxColumn "IsSelected"
$global:grdDocumentObjects.Columns.Add($column)
@@ -3316,6 +3389,11 @@ function Show-DocumentationForm
$txtDocumentationRawData.Text = ""
$loadExportedInfo = $true
$script:migTable = $null
$script:scopeTags = $null
$diSource = $nul
$global:intentCategories = $null
$global:catRecommendedSettings = $null
$global:intentCategoryDefs = $null
@@ -3374,6 +3452,19 @@ function Show-DocumentationForm
}
elseif($global:grdDocumentObjects.Tag -eq "ObjectTypes")
{
$fromExportFolder = $false
if($global:txtDocumentFromFolder.Text)
{
$diSource = [IO.DirectoryInfo]$global:txtDocumentFromFolder.Text
if($diSource.Exists -eq $false)
{
[System.Windows.MessageBox]::Show("Source folder not found:`n`n$($diSource.FullName)", "Documentation", "OK", "Error")
Write-Status ""
return
}
$fromExportFolder = $true
}
$sourceList = @()
foreach($objGroup in ($global:grdDocumentObjects.ItemsSource | Where IsSelected -eq $true))
{
@@ -3382,11 +3473,25 @@ function Show-DocumentationForm
{
Write-Status "Get $($objectType.Title) objects"
$graphObjects = @(Get-GraphObjects -property $objectType.ViewProperties -objectType $objectType)
if($objectType.PostListCommand)
if($fromExportFolder -eq $false)
{
$graphObjects = & $objectType.PostListCommand $graphObjects $objectType
$graphObjects = @(Get-GraphObjects -property $objectType.ViewProperties -objectType $objectType)
if($objectType.PostListCommand)
{
$graphObjects = & $objectType.PostListCommand $graphObjects $objectType
}
}
else
{
$objectPath = [IO.Path]::Combine($diSource.FullName,$objectType.ID)
if([IO.Directory]::Exists($objectPath) -eq $false)
{
Write-Log "Object path for $($objectType.Title) ($($objectType.ID)) not found. Skipping object type" 2
continue
}
$graphObjects = Get-GraphFileObjects $objectPath -ObjectType $objectType
$graphObjects | ForEach-Object { $_.Object | Add-Member Noteproperty -Name "@ObjectFromFile" -Value $true -Force }
}
$groupSourceList += $graphObjects
}
@@ -3412,6 +3517,39 @@ function Show-DocumentationForm
return
}
if($fromExportFolder -eq $true -and $diSource -and $loadExportedInfo -eq $true)
{
$loadExportedInfo = $false
$migFileName = [IO.Path]::Combine($diSource.FullName,"MigrationTable.json")
if([IO.File]::Exists($migFileName) -eq $false)
{
Write-Log "MigrationTable not found. Groups will be documented with GroupId" 2
}
else
{
Write-Log "Load Migration table from $migFileName"
$script:migTable = ConvertFrom-Json (Get-Content $migFileName -Raw)
}
$scopeTagObjectType = $global:currentViewObject.ViewItems | Where Id -eq "ScopeTags"
if($scopeTagObjectType)
{
$scopePath = [IO.Path]::Combine($diSource.FullName,$scopeTagObjectType.Id)
if([IO.Directory]::Exists($scopePath) -eq $false)
{
Write-Log "Object path for Scope (Tags) ($($scopePath)) not found" 2
}
else
{
$scopeTagObjects = Get-GraphFileObjects $scopePath -ObjectType $scopeTagObjectType
$script:scopeTags = @(($scopeTagObjects | Select Object))
}
}
}
if($global:cbDocumentationType.SelectedItem.PreProcess)
{
Write-Status "Run PreProcess for $($global:cbDocumentationType.SelectedItem.Name)"
@@ -3436,7 +3574,14 @@ function Show-DocumentationForm
}
}
$obj = Get-GraphObject $tmpObj.Object $tmpObj.ObjectType
if($tmpObj.Object."@ObjectFromFile" -eq $true)
{
$obj = $tmpObj
}
else
{
$obj = Get-GraphObject $tmpObj.Object $tmpObj.ObjectType
}
if($obj)
{
@@ -3669,7 +3814,7 @@ function Set-OutputOptionsTabStatus
function Invoke-DocumentObjectTypes
{
Show-DocumentationForm -objectTypes $global:currentViewObject.ViewItems
Show-DocumentationForm -objectTypes $global:currentViewObject.ViewItems -ShowFolderSource
}
function Invoke-DocumentSelectedObjects

View File

@@ -10,7 +10,7 @@ This module will also document some objects based on PowerShell functions
function Get-ModuleVersion
{
'1.0.6'
'1.1.0'
}
function Invoke-InitializeModule
@@ -23,6 +23,7 @@ function Invoke-InitializeModule
GetCustomChildObject = { Get-CDDocumentCustomChildObjet @args }
GetCustomPropertyObject = { Get-CDDocumentCustomPropertyObject @args }
AddCustomProfileProperty = { Add-CDDocumentCustomProfileProperty @args }
PostAddValue = { Invoke-CDDocumentCustomPostAdd @args }
})
}
@@ -92,6 +93,13 @@ function Invoke-CDDocumentObject
return [PSCustomObject]@{
Properties = @("Name","Value","Category","SubCategory")
}
}
elseif($type -eq '#microsoft.graph.deviceAndAppManagementAssignmentFilter')
{
Invoke-CDDocumentAssignmentFilter $documentationObj
return [PSCustomObject]@{
Properties = @("Name","Value")
}
}
}
@@ -169,6 +177,73 @@ Property separator character
Object separator character
#>
function Invoke-CDDocumentCustomPostAdd
{
param($obj, $prop, $propSeparator, $objSeparator)
if($obj.'@OData.Type' -eq "#microsoft.graph.windowsUpdateForBusinessConfiguration")
{
if($prop.EntityKey -eq "featureUpdatesDeferralPeriodInDays")
{
# Inject Windows 11 update setting. Not included in the file
$tmpProp = [PSCustomObject]@{
nameResourceKey = "allowWindows11UpgradeName"
descriptionResourceKey = "allowWindows11UpgradeDescription"
entityKey = "allowWindows11Upgrade"
dataType = 0
booleanActions = 109
category = $prop.Category
}
$propValue = Invoke-TranslateBoolean $obj $tmpProp
$script:UpdateCategory = $prop.Category
Add-PropertyInfo $tmpProp $propValue -originalValue $obj.allowWindows11Upgrade
}
if($prop.EntityKey -eq "featureUpdatesRollbackWindowInDays")
{
if($obj.businessReadyUpdatesOnly -eq "businessReadyOnly")
{
$propValue = Get-LanguageString "BooleanActions.notConfigured"
}
else
{
$propValue = Get-LanguageString "BooleanActions.enable"
}
# Inject Pre-release setting. Not included in the file
$tmpProp = [PSCustomObject]@{
nameResourceKey = "preReleaseBuilds"
descriptionResourceKey = "preReleaseBuildsDescription"
entityKey = "preReleaseEnabled" # Not a class property!
dataType = 0
booleanActions = 2
category = $prop.Category
}
Add-PropertyInfo $tmpProp $propValue -originalValue $obj.businessReadyUpdatesOnly
if($obj.businessReadyUpdatesOnly -ne "businessReadyOnly")
{
# Pre-release channel selected. Inject info
$propValue = Get-LanguageString "SettingDetails.$($obj.businessReadyUpdatesOnly)Option"
$tmpProp = [PSCustomObject]@{
nameResourceKey = "preReleaseChannel"
descriptionResourceKey = "preReleaseBuildsDescription"
entityKey = "businessReadyUpdatesOnly"
dataType = 0
booleanActions = 2
category = $prop.Category
}
Add-PropertyInfo $tmpProp $propValue -originalValue $obj.businessReadyUpdatesOnly
}
}
}
}
function Add-CDDocumentCustomProfileValue
{
param($obj, $prop, $topObj, $propSeparator, $objSeparator)
@@ -318,7 +393,19 @@ function Add-CDDocumentCustomProfileValue
$propValue = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($obj.eapXml))
Add-PropertyInfo $prop $propValue -originalValue $propValue
return $false
}
}
}
elseif($obj.'@OData.Type' -eq "#microsoft.graph.windowsUpdateForBusinessConfiguration")
{
if($prop.EntityKey -eq "businessReadyUpdatesOnly" -or
$prop.EntityKey -eq "autoRestartNotificationDismissal" -or
$prop.EntityKey -eq "scheduleRestartWarningInHours" -or
$prop.EntityKey -eq "scheduleImminentRestartWarningInMinutes" -or
$prop.EntityKey -eq "deliveryOptimizationMode")
{
# Not used anymore
return $false
}
}
}
@@ -695,6 +782,11 @@ function Add-CDDocumentCustomProfileProperty
}
$obj | Add-Member Noteproperty -Name "syntheticWipOrApps" -Value $syntheticWipOrApps -Force
if($null -eq $obj.profileTarget)
{
$obj.profileTarget = "user"
}
$retValue = $true
}
elseif($obj.'@OData.Type' -like "#microsoft.graph.iosDeviceFeaturesConfiguration")
@@ -872,6 +964,29 @@ function Add-CDDocumentCustomProfileProperty
$obj | Add-Member Noteproperty -Name "featureUpdateDisplayName" -Value $verInfoTxt
if($obj.rolloutSettings.offerStartDateTimeInUTC -and
$obj.rolloutSettings.offerEndDateTimeInUTC)
{
$featureUpdateRolloutOption = "gradualRollout"
$obj | Add-Member Noteproperty -Name "featureUpdateRolloutStartDate" -Value ((Get-Date $obj.rolloutSettings.offerStartDateTimeInUTC).ToLongDateString())
$obj | Add-Member Noteproperty -Name "featureUpdateRolloutEndDate" -Value ((Get-Date $obj.rolloutSettings.offerEndDateTimeInUTC).ToLongDateString())
if($null -ne $obj.rolloutSettings.offerIntervalInDays)
{
$obj | Add-Member Noteproperty -Name "featureUpdateRolloutInterval" -Value ($obj.rolloutSettings.offerIntervalInDays)
}
}
elseif($obj.rolloutSettings.offerStartDateTimeInUTC)
{
$featureUpdateRolloutOption = "startDateOnly"
$obj | Add-Member Noteproperty -Name "featureUpdateRolloutStartDate" -Value ((Get-Date $obj.rolloutSettings.offerStartDateTimeInUTC).ToLongDateString())
}
else
{
$featureUpdateRolloutOption = "immediateStart"
}
$obj | Add-Member Noteproperty -Name "featureUpdateRolloutOption" -Value $featureUpdateRolloutOption
$retValue = $true
}
elseif($obj.'@OData.Type' -eq "#microsoft.graph.iosUpdateConfiguration")
@@ -2500,4 +2615,44 @@ function Invoke-CDDocumentNotification
})
}
}
#endregion
#region
function Invoke-CDDocumentAssignmentFilter
{
param($documentationObj)
$obj = $documentationObj.Object
$objectType = $documentationObj.ObjectType
$script:objectSeparator = ?? $global:cbDocumentationObjectSeparator.SelectedValue ([System.Environment]::NewLine)
$script:propertySeparator = ?? $global:cbDocumentationPropertySeparator.SelectedValue ","
###################################################
# Basic info
###################################################
Add-BasicDefaultValues $obj $objectType
# "Filters" is not in the translation file
Add-BasicPropertyValue (Get-LanguageString "TableHeaders.configurationType") "Filters"
Add-BasicPropertyValue (Get-LanguageString "Inputs.platformLabel") (Get-LanguageString "Platform.$($obj.platform)")
###################################################
# Settings
###################################################
$label = Get-LanguageString "ApplicabilityRules.GridLabel.rule"
# "Rules" is not in the translation file
$category = "Rules"
Add-CustomSettingObject ([PSCustomObject]@{
Name = $label
Value = $obj.rule
EntityKey = "rule"
Category = $category
SubCategory = $null
})
}
#endregion

View File

@@ -3,7 +3,7 @@
#https://docs.microsoft.com/en-us/office/vba/api/overview/word
function Get-ModuleVersion
{
'1.0.7'
'1.1.0'
}
function Invoke-InitializeModule
@@ -70,6 +70,14 @@ function Add-WordOptionsControl
$global:spWordCustomProperties.Visibility = (?: ($global:cbWordDocumentationProperties.SelectedValue -ne "custom") "Collapsed" "Visible")
$global:txtWordCustomProperties.Visibility = (?: ($global:cbWordDocumentationProperties.SelectedValue -ne "custom") "Collapsed" "Visible")
$global:cbWordDocumentationLevel.ItemsSource = ("[ { Name: `"Full`",Value: `"full`" }, { Name: `"Limited`",Value: `"limited`" }, { Name: `"Basic`",Value: `"basic`" }]" | ConvertFrom-Json)
$global:cbWordDocumentationLevel.SelectedValue = (Get-Setting "Documentation" "WordDocumentationLevel" "full")
$global:gdWordDocumentationLimitOptions.Visibility = (?: ($global:cbWordDocumentationLevel.SelectedValue -ne "limited") "Collapsed" "Visible")
$global:txtWordDocumentationLimitMaxLength.Text = Get-Setting "Documentation" "WordDocumentationLimitMaxLength" ""
$global:txtWordDocumentationLimitTruncateLength.Text = Get-Setting "Documentation" "WordDocumentationLimitTruncateLength" ""
$global:chkWordDocumentationLimitAttatch.IsChecked = ((Get-Setting "Documentation" "WordDocumentationLimitAttatch" "true") -ne "false")
$global:txtWordDocumentTemplate.Text = Get-Setting "Documentation" "WordDocumentTemplate" ""
$global:txtWordDocumentName.Text = (Get-Setting "Documentation" "WordDocumentName" "%MyDocuments%\%Organization%-%Date%.docx")
@@ -88,6 +96,8 @@ function Add-WordOptionsControl
$global:chkWordIncludeScripts.IsChecked = ((Get-Setting "Documentation" "WordIncludeScripts" "true") -ne "false")
$global:chkWordExcludeScriptSignature.IsChecked = ((Get-Setting "Documentation" "WordExcludeScriptSignature" "false") -ne "false")
$global:chkWordAttatchJsonFile.IsChecked = ((Get-Setting "Documentation" "WordAttatchJsonFile" "false") -ne "false")
$global:txtWordScriptTableStyle.Text = Get-Setting "Documentation" "WordScriptTableStyle" ""
$global:txtWordScriptStyle.Text = Get-Setting "Documentation" "WordScriptStyle"
@@ -109,6 +119,10 @@ function Add-WordOptionsControl
$global:txtWordCustomProperties.Visibility = (?: ($this.SelectedValue -ne "custom") "Collapsed" "Visible")
}
Add-XamlEvent $script:wordForm "cbWordDocumentationLevel" "add_selectionChanged" {
$global:gdWordDocumentationLimitOptions.Visibility = (?: ($this.SelectedValue -ne "limited") "Collapsed" "Visible")
}
$script:wordForm
}
function Invoke-WordActivate
@@ -123,6 +137,11 @@ function Invoke-WordPreProcessItems
Save-Setting "Documentation" "WordDocumentTemplate" $global:txtWordDocumentTemplate.Text
Save-Setting "Documentation" "WordDocumentName" $global:txtWordDocumentName.Text
Save-Setting "Documentation" "WordDocumentationLevel" $global:cbWordDocumentationLevel.SelectedValue
Save-Setting "Documentation" "WordDocumentationLimitMaxLength" $global:txtWordDocumentationLimitMaxLength.Text
Save-Setting "Documentation" "WordDocumentationLimitTruncateLength" $global:txtWordDocumentationLimitTruncateLength.Text
Save-Setting "Documentation" "WordDocumentationLimitAttatch" $global:chkWordDocumentationLimitAttatch.IsChecked
Save-Setting "Documentation" "WordAddCategories" $global:chkWordAddCategories.IsChecked
Save-Setting "Documentation" "WordAddSubCategories" $global:chkWordAddSubCategories.IsChecked
Save-Setting "Documentation" "WordOpenDocument" $global:chkWordOpenDocument.IsChecked
@@ -139,9 +158,58 @@ function Invoke-WordPreProcessItems
Save-Setting "Documentation" "WordIncludeScripts" $global:chkWordIncludeScripts.IsChecked
Save-Setting "Documentation" "WordExcludeScriptSignature" $global:chkWordExcludeScriptSignature.IsChecked
Save-Setting "Documentation" "WordAttatchJsonFile" $global:chkWordAttatchJsonFile.IsChecked
Save-Setting "Documentation" "WordScriptTableStyle" $global:txtWordScriptTableStyle.Text
Save-Setting "Documentation" "WordScriptStyle" $global:txtWordScriptStyle.Text
$script:limitMaxValue = 100
$script:truncateValueLength = $script:limitMaxValue
if($global:cbWordDocumentationLevel.SelectedValue -eq "limited")
{
if($global:txtWordDocumentationLimitMaxLength.Text)
{
try
{
$script:limitMaxValue = [int]::Parse($global:txtWordDocumentationLimitMaxLength.Text)
}
catch
{
Write-LogError "Failed to parse $($global:txtWordDocumentationLimitMaxLength.Text) to int. Max value length will be set to 100." $_.Exception
}
}
if($global:txtWordDocumentationLimitTruncateLength.Text)
{
try
{
$script:truncateValueLength = [int]::Parse($global:txtWordDocumentationLimitTruncateLength.Text)
}
catch
{
Write-LogError "Failed to parse $($global:txtWordDocumentationLimitTruncateLength.Text) to int. Truncat length will be set to $script:limitMaxValue." $_.Exception
}
}
if($script:limitMaxValue -lt 20)
{
Write-Log "Max value length must be 20 or more. Changed to 20" 2
$script:limitMaxValue = 0
}
if($script:truncateValueLength -lt 0)
{
Write-Log "Truncate length must be 0 or more. Changed to 0" 2
$script:truncateValueLength = 0
}
elseif($script:truncateValueLength -gt $script:limitMaxValue)
{
Write-Log "Truncate length cannot be larger than Max value length. Canged to: $($script:limitMaxValue)" 2
$script:truncateValueLength = $script:limitMaxValue
}
}
try
{
$script:wordApp = New-Object -ComObject Word.Application
@@ -284,6 +352,17 @@ function Invoke-WordPreProcessItems
}
}
}
else
{
if(($script:doc.TablesOfContents | measure).Count -eq 0)
{
# Where should it be added?
# $script:doc.TablesOfContents.Add($script:wordApp.Selection.Range) | out-null
}
Invoke-DocGoToEnd
$script:wordApp.Selection.InsertNewPage()
}
}
function Invoke-WordPostProcessItems
@@ -459,30 +538,39 @@ function Invoke-WordProcessItem
{
$properties = (?? $documentedObj.DefaultDocumentationProperties (@("Name","Value")))
}
if($global:cbWordDocumentationLevel.SelectedValue -eq "basic" -and $tableType -ne "BasicInfo")
{
continue
}
$lngId = ?: ($tableType -eq "BasicInfo") "SettingDetails.basics" "TableHeaders.settings" -AddCategories
Add-DocTableItems $obj $objectType ($documentedObj.$tableType) $properties $lngId `
-AddCategories:($global:chkWordAddCategories.IsChecked -eq $true) `
-AddSubcategories:($global:chkWordAddSubCategories.IsChecked -eq $true)
-AddSubcategories:($global:chkWordAddSubCategories.IsChecked -eq $true) `
-ForceFullValue:($tableType -eq "BasicInfo")
}
if(($documentedObj.ComplianceActions | measure).Count -gt 0)
if($global:cbWordDocumentationLevel.SelectedValue -ne "basic")
{
$properties = @("Action","Schedule","MessageTemplate","EmailCC")
if(($documentedObj.ComplianceActions | measure).Count -gt 0)
{
$properties = @("Action","Schedule","MessageTemplate","EmailCC")
Add-DocTableItems $obj $objectType $documentedObj.ComplianceActions $properties "Category.complianceActionsLabel"
Add-DocTableItems $obj $objectType $documentedObj.ComplianceActions $properties "Category.complianceActionsLabel"
}
if(($documentedObj.ApplicabilityRules | measure).Count -gt 0)
{
$properties = @("Rule","Property","Value")
Add-DocTableItems $obj $objectType $documentedObj.ApplicabilityRules $properties "SettingDetails.applicabilityRules"
}
Add-DocObjectSettings $obj $objectType $documentedObj
}
if(($documentedObj.ApplicabilityRules | measure).Count -gt 0)
{
$properties = @("Rule","Property","Value")
Add-DocTableItems $obj $objectType $documentedObj.ApplicabilityRules $properties "SettingDetails.applicabilityRules"
}
Add-DocObjectSettings $obj $objectType $documentedObj
if(($documentedObj.Assignments | measure).Count -gt 0)
{
$params = @{}
@@ -523,6 +611,20 @@ function Invoke-WordProcessItem
Add-DocTableItems $obj $objectType $documentedObj.Assignments $properties "TableHeaders.assignments" @params
}
if($global:chkWordAttatchJsonFile.IsChecked -eq $true)
{
$fileName = Export-GraphObject $obj $objectType ([IO.Path]::GetTempPath()) -IsFullObject -PassThru -SkipAddID
if($fileName)
{
$fi = [IO.FileInfo]$fileName
if($fi.Exists)
{
$script:doc.Application.Selection.InlineShapes.AddOLEObject("",$fi.FullName,$false,$true,"$($env:WinDir)\System32\Notepad.exe",0,$fi.Name)
try { $fi.Delete() } catch {} # Cleanup
}
}
}
}
catch
{
@@ -606,7 +708,7 @@ function Set-WordColumnHeaderLanguageId
function Add-DocTableItems
{
param($obj, $objectType, $items, $properties, $lngId, [switch]$AddCategories, [switch]$AddSubcategories, $captionOverride)
param($obj, $objectType, $items, $properties, $lngId, [switch]$AddCategories, [switch]$AddSubcategories, $captionOverride, [switch]$forceFullValue)
$tblHeaderStyle = $global:txtWordTableHeaderStyle.Text
$tblCategoryStyle = $global:txtWordCategoryHeaderStyle.Text
@@ -665,7 +767,48 @@ function Add-DocTableItems
{
$tmpObj = $tmpObj."$($propArr[$x])"
}
$script:docTable.Cell($row, $i).Range.Text = "$($tmpObj.$propName)"
$propValue = "$($tmpObj.$propName)"
$propValueFull = $null
if($forceFullValue -ne $true -and $global:cbWordDocumentationLevel.SelectedValue -eq "limited" -and $propValue.Length -gt $script:limitMaxValue)
{
$propValueFull = $propValue
if($script:truncateValueLength -gt 0)
{
$propValue = ($propValue.Substring(0, $script:truncateValueLength) + "...")
if($global:chkWordDocumentationLimitAttatch.IsChecked -eq $true)
{
$propValue = ("`r`n" + $propValue)
}
}
else
{
$propValue = $null
}
}
if($null -ne $propValue)
{
$script:docTable.Cell($row, $i).Range.Text = $propValue
}
if($propValueFull -and $global:chkWordDocumentationLimitAttatch.IsChecked -eq $true)
{
if($null -ne $propValue)
{
#$script:doc.Application.Selection.TypeParagraph()
}
$tmpName = "$((Get-GraphObjectName $obj $objectType))-$propName"
$tmpFile = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "$($tmpName).txt")
$tmpFile = Remove-InvalidFileNameChars $tmpFile
$propValueFull | Out-File -LiteralPath $tmpFile -Force
$fi = [IO.FileInfo]$tmpFile
[void]$script:docTable.Cell($row, $i).Range.InlineShapes.AddOLEObject("",$fi.FullName,$false,$true,"$($env:WinDir)\System32\Notepad.exe",0,"Full value")
#$script:doc.Application.Selection.InlineShapes.AddOLEObject("",$fi.FullName,$false,$true,"$($env:WinDir)\System32\Notepad.exe",0,"Full value", $script:docTable.Cell($row, $i).Range)
try { $fi.Delete() } catch {}
}
}
catch
{

View File

@@ -11,7 +11,7 @@ This module is for the Endpoint Manager/Intune View. It manages Export/Import/Co
#>
function Get-ModuleVersion
{
'3.1.14'
'3.4.0'
}
function Invoke-InitializeModule
@@ -239,8 +239,9 @@ 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
PostListCommand = { Start-PostListESP @args }
#PreUpdateCommand = { Start-PreUpdateEnrollmentRestrictions @args } # Note: Uses same PreUpdateCommand as restrictions
QUERYLIST = "`$filter=endsWith(id,'Windows10EnrollmentCompletionPageConfiguration')"
#QUERYLIST = "`$filter=endsWith(id,'Windows10EnrollmentCompletionPageConfiguration')"
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
SkipRemoveProperties = @('Id')
AssignmentsType = "enrollmentConfigurationAssignments"
@@ -253,19 +254,21 @@ function Invoke-InitializeModule
Id = "EnrollmentRestrictions"
API = "/deviceManagement/deviceEnrollmentConfigurations"
ViewID = "IntuneGraphAPI"
QUERYLIST = "`$filter=not endsWith(id,'Windows10EnrollmentCompletionPageConfiguration')"
#QUERYLIST = "`$filter=not endsWith(id,'Windows10EnrollmentCompletionPageConfiguration')"
PostExportCommand = { Start-PostExportEnrollmentRestrictions @args }
PreImportCommand = { Start-PreImportEnrollmentRestrictions @args }
PreDeleteCommand = { Start-PreDeleteEnrollmentRestrictions @args }
PreReplaceCommand = { Start-PreReplaceEnrollmentRestrictions @args }
PostReplaceCommand = { Start-PostReplaceEnrollmentRestrictions @args }
PreFilesImportCommand = { Start-PreFilesImportEnrollmentRestrictions @args }
PostListCommand = { Start-PostListEnrollmentRestrictions @args }
#PreUpdateCommand = { Start-PreUpdateEnrollmentRestrictions @args }
PropertiesToRemoveForUpdate = @('priority')
Permissons=@("DeviceManagementServiceConfig.ReadWrite.All")
SkipRemoveProperties = @('Id')
AssignmentsType = "enrollmentConfigurationAssignments"
GroupId = "EnrollmentRestrictions"
ViewProperties = @("displayName","platformType","description","Id")
})
Add-ViewItem (New-Object PSObject -Property @{
@@ -405,8 +408,10 @@ 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 }
PostCopyCommand = { Start-PostCopyApplications @args }
PreUpdateCommand = { Start-PreUpdateApplication @args }
PreImportCommand = { Start-PreImportCommandApplication @args }
DetailExtension = { Add-DetailExtensionApplications @args }
GroupId = "Apps"
})
@@ -1322,19 +1327,24 @@ function Add-ScriptExportExtensions
{
param($form, $buttonPanel, $index = 0)
$xaml = @"
$ctrl = $form.FindName("chkExportScript")
if(-not $ctrl)
{
$xaml = @"
<StackPanel $($global:wpfNS) Orientation="Horizontal" Margin="0,0,5,0">
<Label Content="Export script" />
<Rectangle Style="{DynamicResource InfoIcon}" ToolTip="Export the powershell script to a ps1 file" />
<Rectangle Style="{DynamicResource InfoIcon}" ToolTip="Export the script associated with PowerShell or Shell profiles" />
</StackPanel>
"@
$label = [Windows.Markup.XamlReader]::Parse($xaml)
$label = [Windows.Markup.XamlReader]::Parse($xaml)
$global:chkExportScript = [System.Windows.Controls.CheckBox]::new()
$global:chkExportScript.IsChecked = $true
$global:chkExportScript.VerticalAlignment = "Center"
$global:chkExportScript = [System.Windows.Controls.CheckBox]::new()
$global:chkExportScript.IsChecked = $true
$global:chkExportScript.VerticalAlignment = "Center"
$global:chkExportScript.Name = "chkExportScript"
@($label, $global:chkExportScript)
@($label, $global:chkExportScript)
}
}
function Start-PostExportScripts
@@ -1672,40 +1682,60 @@ function Start-PreImportAssignmentsAppConfiguration
#endregon
#region Applications
function Start-PostCopyApplications
{
param($objCopyFrom, $objNew, $objectType)
Start-ImportApp $objNew
Write-Status ""
}
function Start-PostFileImportApplications
{
param($obj, $objectType, $file)
$tmpObj = Get-Content -LiteralPath $file | ConvertFrom-Json
if(-not $tmpObj.'@odata.type') { return }
$pkgPath = Get-SettingValue "EMIntuneAppPackages"
if(-not $pkgPath -or [IO.Directory]::Exists($pkgPath) -eq $false)
{
Write-LogDebug "Package source directory is either missing or does not exist" 2
return
}
$packageFile = "$($pkgPath)\$($obj.fileName)"
if([IO.File]::Exists($packageFile) -eq $false)
{
Write-LogDebug "Package source file $packageFile not found" 2
return
}
Write-Status "Import appliction package file $($obj.fileName)"
Write-Log "Import application file '$($packageFile)' for $($obj.displayName)"
if(-not ($obj.PSObject.Properties | Where Name -eq '@odata.type'))
{
# Add @odata.type property if it is missing. Required by app package import
$obj | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value $tmpObj.'@odata.type'
$obj | Add-Member -MemberType NoteProperty -Name '@odata.type' -Value $objectType.'@odata.type'
}
Start-ImportApp $obj
}
function local:Start-ImportApp
{
param($obj, $packageFile = $null)
if(-not $obj.'@odata.type') { return }
if($null -eq $packageFile)
{
$pkgPath = Get-SettingValue "EMIntuneAppPackages"
if(-not $pkgPath -or [IO.Directory]::Exists($pkgPath) -eq $false)
{
Write-LogDebug "Package source directory is either missing or does not exist" 2
return
}
$packageFile = "$($pkgPath)\$($obj.fileName)"
}
$fi = [IO.FileInfo]$packageFile
if($fi.Exists -eq $false)
{
Write-LogDebug "Package source file $($fi.FullName) not found" 2
return
}
$appType = $tmpObj.'@odata.type'.Trim('#')
Write-Status "Import appliction package file $($fi.FullName)"
Write-Log "Import application file '$($($fi.FullName))' for $($obj.displayName)"
$appType = $obj.'@odata.type'.Trim('#')
if($appType -eq "microsoft.graph.win32LobApp")
{
@@ -1760,6 +1790,55 @@ function Start-PreImportCommandApplication
}
}
function Add-DetailExtensionApplications
{
param($form, $buttonPanel, $index = 0)
$btnUpload = New-Object System.Windows.Controls.Button
$btnUpload.Content = 'Upload'
$btnUpload.Name = 'btnUploadAppfile'
$btnUpload.Margin = "0,0,5,0"
$btnUpload.Width = "100"
$btnUpload.Add_Click({
if($global:dgObjects.SelectedItem.Object.publishingState -ne "notPublished")
{
# Only allow upload of not published apps
# Use portal to replace app file...
if(([System.Windows.MessageBox]::Show("Are you sure you want to upload a new file for the app?`n`nApplication:`n$($global:dgObjects.SelectedItem.Object.displayName)", "Update app file?", "YesNo", "Warning")) -ne "Yes")
{
return
}
}
$pkgPath = Get-SettingValue "EMIntuneAppPackages"
$of = [System.Windows.Forms.OpenFileDialog]::new()
$of.FileName = $global:dgObjects.SelectedItem.Object.fileName
$of.DefaultExt = "*.intunewin"
$of.Filter = "Intune Win32 (*.intunewin)|*.*"
$of.Multiselect = $false
if($pkgPath -and [IO.Directory]::Exists($pkgPath))
{
$of.InitialDirectory = $pkgPath
}
if($of.ShowDialog() -eq "OK")
{
Write-Status "Import $($global:dgObjects.SelectedItem.Object.displayName) file"
Start-ImportApp $global:dgObjects.SelectedItem.Object $of.FileName
Write-Status ""
}
})
$tmp = $form.FindName($buttonPanel)
if($tmp)
{
$tmp.Children.Insert($index, $btnUpload)
}
}
#endregion
#region Group Policy/Administrative Templates functions
@@ -2241,6 +2320,14 @@ function Start-PostExportESP
Save-EMDefaultPolicy $obj $objectType $path
}
}
function Start-PostListESP
{
param($objList, $objectType)
# endswith not working so filter them out
$objList | Where { $_.Object.'@OData.Type' -eq '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration' }
}
#endregion
#region Enrollment Restriction functions
@@ -2326,6 +2413,19 @@ function Start-PreUpdateEnrollmentRestrictions
Remove-Property $obj "priority"
}
function Start-PostListEnrollmentRestrictions
{
param($objList, $objectType)
# endswith not working so filter them out
$objList | Where {
($_.Object.'@OData.Type' -eq '#microsoft.graph.deviceEnrollmentPlatformRestrictionConfiguration' -or
$_.Object.'@OData.Type' -eq '#microsoft.graph.deviceEnrollmentLimitConfiguration' -or
$_.Object.'@OData.Type' -eq '#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration') -and
$_.Object.id -notlike "*_PlatformRestrictions" -and $_.Object.platformType -ne "WindowsPhone" -and $_.Object.platformType -ne "AndroidAosp"
}
}
#endregion
#region ScopeTags
@@ -2596,6 +2696,7 @@ function Add-ConditionalAccessImportExtensions
$global:cbImportCAState.Margin="0,5,0,0"
$global:cbImportCAState.HorizontalAlignment="Left"
$global:cbImportCAState.Width=250
$global:cbImportCAState.Name = "cbImportCAState"
@($label, $global:cbImportCAState)
}

View File

@@ -10,7 +10,7 @@ This module manages Application objects in Intune e.g. uploading application fil
#>
function Get-ModuleVersion
{
'3.1.2'
'3.4.0'
}
#########################################################################################
@@ -209,6 +209,8 @@ function Copy-Win32LOBPackage
Remove-Item -Path $tmpFile
$fi = [IO.FileInfo]$intunewinFile
# Get encryption info from detection.xml and build encryptionInfo object
$encryptionInfo = @{}
@@ -222,7 +224,7 @@ function Copy-Win32LOBPackage
$tmpIntunewinPath = ([IO.Path]::GetTempPath() + [Guid]::NewGuid().ToString("n"))
mkdir $tmpIntunewinPath | Out-Null
$tmpIntunewinFile = $tmpIntunewinPath + "\" + $DetectionXML.ApplicationInfo.FileName
$tmpIntunewinFile = $tmpIntunewinPath + "\" + $fi.Name
# Extract the encrypted file from the intunewin file
Export-IntunewinFileObject $intunewinFile $DetectionXML.ApplicationInfo.FileName $tmpIntunewinFile
@@ -250,8 +252,8 @@ function Add-FileToIntuneApp
{
param($appId, $appType, $appFile, $fileBody)
$contentVersion = Invoke-GraphRequest -Url "/deviceAppManagement/mobileApps/$appId/$appType/contentVersions"
$contentVersionId = $contentVersion.value[0].id
$contentVersion = Invoke-GraphRequest -Url "/deviceAppManagement/mobileApps/$appId/$appType/contentVersions" -HttpMethod POST -Content "{}"
$contentVersionId = $contentVersion.id
$fileObj = Invoke-GraphRequest -Url "/deviceAppManagement/mobileApps/$appId/$appType/contentVersions/$contentVersionId/files" -HttpMethod POST -Content (ConvertTo-Json $fileBody -Depth 5)
if(-not $fileObj)
@@ -274,10 +276,12 @@ function Add-FileToIntuneApp
Wait-IntuneFileState "/deviceAppManagement/mobileApps/$appId/$appType/contentVersions/$contentVersionId/files/$($fileObj.Id)" "CommitFile"
$fiUpload = [IO.FileInfo]$appFile
# Commit the content version
$commitAppBody = @{
"@odata.type" = "#$appType"
committedContentVersion = $contentVersionId
fileName = $fiUpload.Name
}
$reponse = Invoke-GraphRequest -Url "/deviceAppManagement/mobileApps/$appId" -HttpMethod PATCH -Content (ConvertTo-Json $commitAppBody -Depth 5)

View File

@@ -10,7 +10,7 @@ This module manages Authentication for the application with MSAL. It is also res
#>
function Get-ModuleVersion
{
'3.3.2'
'3.4.0'
}
$global:msalAuthenticator = $null
@@ -234,7 +234,7 @@ function Get-MSALUserInfo
{
Write-Log "Get current user"
$tmpMe = MSGraph\Invoke-GraphRequest -Url "ME" -SkipAuthentication -ODataMetadata "Skip"
if($tmpMe.creationType -ne "Invitation")
if($null -ne $tmpMe -and $tmpMe.creationType -ne "Invitation")
{
### Only get user info from home tenant
$global:Me = $tmpMe
@@ -342,6 +342,12 @@ function Install-MSALDependencyModule
{
param($moduleToInstall, $button)
if($global:hideUI -eq $true)
{
Write-Log "Cannot install MSAL module in Silent mode"
return
}
$forceUserInstallation = $false
if($global:chkCurrentUser.IsChecked -eq $false -and (Get-IsAdmin) -eq $false)
@@ -541,6 +547,38 @@ function Add-MSALPrereq
}
}
function Connect-MSALClientApp
{
param($clientId, $tenantId, $secret, $Certificate)
$scopes = [String[]]".default"
if(-not $script:MSALApp)
{
$authority = "https://login.microsoftonline.com/$tenantId"
#$redirectUri = "http://localhost"
if($secret)
{
$ClientApplicationBuilder = [Microsoft.Identity.Client.ConfidentialClientApplicationBuilder]::Create($clientId).WithClientSecret($ClientSecret).WithAuthority([URI]::new($authority)) #.WithRedirectUri($redirectUri)
}
elseif($Certificate)
{
$ClientApplicationBuilder = [Microsoft.Identity.Client.ConfidentialClientApplicationBuilder]::Create($clientId).WithCertificate($ClientSecret).WithAuthority([URI]::new($authority)) #.WithRedirectUri($redirectUri)
}
else
{
return
}
$script:MSALApp = $ClientApplicationBuilder.Build()
}
if($script:MSALApp)
{
$accessTokenRequest = $script:MSALApp.AcquireTokenForClient($scopes)
$global:MSALToken = Get-MsalAuthenticationToken $accessTokenRequest
}
}
function Get-MsalAuthenticationToken
{
param($aquireTokenObj)
@@ -689,6 +727,9 @@ function Connect-MSALUser
[switch]
$Interactive,
[switch]
$ClientApp,
$Account,
$Tenant
@@ -697,6 +738,24 @@ function Connect-MSALUser
# No login during first time the app is started
if($global:FirstTimeRunning -and $global:MainAppStarted -eq $false) { return }
if($global:hideUI -eq $true)
{
if($global:AzureAppId -and $global:ClientSecret -and $global:TenantId)
{
Connect-MSALClientApp $global:AzureAppId $global:TenantId -secret $global:ClientSecret
}
elseif($global:AzureAppId -and $global:ClientCert -and $global:TenantId)
{
Connect-MSALClientApp $global:AzureAppId $global:TenantId -certificate $global:ClientCert
}
else
{
Write-Log "Azure AppId, Tenant Id and Sercret/Cert must be specified for batch login" 3
}
return
}
Write-LogDebug "Authenticate"
if(-not $global:appObj.ClientId)

File diff suppressed because it is too large Load Diff