3.3.2
This commit is contained in:
@@ -11,7 +11,7 @@ Objects can be compared based on Properties or Documentatation info.
|
||||
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.0.8'
|
||||
'1.0.9'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -127,9 +127,6 @@ function Invoke-ShowMainWindow
|
||||
$button.Margin = "0,0,5,0"
|
||||
$button.IsEnabled = $false
|
||||
$button.ToolTip = "Compare object with exported file"
|
||||
$global:dgObjects.add_selectionChanged({
|
||||
Set-XamlProperty $global:dgObjects.Parent "btnCompare" "IsEnabled" (?: ($global:dgObjects.SelectedItem -eq $null) $false $true)
|
||||
})
|
||||
|
||||
$button.Add_Click({
|
||||
Show-CompareForm $global:dgObjects.SelectedItem
|
||||
@@ -140,6 +137,12 @@ function Invoke-ShowMainWindow
|
||||
$global:spSubMenu.Children.Insert(0, $button)
|
||||
}
|
||||
|
||||
function Invoke-EMSelectedItemsChanged
|
||||
{
|
||||
$hasSelectedItems = ($global:dgObjects.ItemsSource | Where IsSelected -eq $true) -or ($null -ne $global:dgObjects.SelectedItem)
|
||||
Set-XamlProperty $global:dgObjects.Parent "btnCompare" "IsEnabled" $hasSelectedItems
|
||||
}
|
||||
|
||||
function Invoke-ViewActivated
|
||||
{
|
||||
if($global:currentViewObject.ViewInfo.ID -ne "IntuneGraphAPI") { return }
|
||||
|
||||
@@ -20,13 +20,38 @@ $global:documentationProviders = @()
|
||||
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.0.7'
|
||||
'1.0.8'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
{
|
||||
# Make sure we add the default Output types
|
||||
Add-OutputType
|
||||
|
||||
$script:columnHeaders = @{
|
||||
Name="Inputs.displayNameLabel"
|
||||
Value="TableHeaders.value"
|
||||
Description="TableHeaders.description"
|
||||
GroupMode="SettingDetails.modeTableHeader" #assignmentTypeSelectionLabel?
|
||||
Group="TableHeaders.assignedGroups"
|
||||
Groups="TableHeaders.groups"
|
||||
useDeviceContext="SettingDetails.installContextLabel"
|
||||
uninstallOnDeviceRemoval="SettingDetails.UninstallOnRemoval"
|
||||
isRemovable="SettingDetails.installAsRemovable"
|
||||
vpnConfigurationId="PolicyType.vpn"
|
||||
Action="SettingDetails.actionColumnName"
|
||||
Schedule="ScheduledAction.List.schedule"
|
||||
MessageTemplate="ScheduledAction.Notification.messageTemplate"
|
||||
EmailCC="ScheduledAction.Notification.additionalRecipients"
|
||||
Filter="AssignmentFilters.assignmentFilterColumnHeader"
|
||||
Rule="ApplicabilityRules.GridLabel.Rule"
|
||||
ValueWithLabel="TableHeaders.value"
|
||||
Status="TableHeaders.status"
|
||||
CombinedValueWithLabel="TableHeaders.value"
|
||||
CombinedValue="TableHeaders.value"
|
||||
useDeviceLicensing="TableHeaders.licenseType"
|
||||
#filterMode="Filter mode" # Not in any string file yet
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-ShowMainWindow
|
||||
@@ -38,12 +63,6 @@ function Invoke-ShowMainWindow
|
||||
$button.Margin = "0,0,5,0"
|
||||
$button.IsEnabled = $false
|
||||
$button.ToolTip = "Document selected objects"
|
||||
$global:dgObjects.add_selectionChanged({
|
||||
##Set-XamlProperty $global:dgObjects.Parent "btnDocument" "IsEnabled" (?: ($global:dgObjects.SelectedItem -eq $null) $false $true)
|
||||
#$itemSelected = ($global:dgObjects.ItemsSource | Where IsSelected -eq $true).Count -ge 0 -or $global:dgObjects.SelectedItem
|
||||
|
||||
Set-XamlProperty $global:dgObjects.Parent "btnDocument" "IsEnabled" (?: ($global:dgObjects.SelectedItem -eq $null) $false $true)
|
||||
})
|
||||
|
||||
$button.Add_Click({
|
||||
|
||||
@@ -57,6 +76,12 @@ function Invoke-ShowMainWindow
|
||||
$global:spSubMenu.Children.Insert(0, $button)
|
||||
}
|
||||
|
||||
function Invoke-EMSelectedItemsChanged
|
||||
{
|
||||
$hasSelectedItems = ($global:dgObjects.ItemsSource | Where IsSelected -eq $true) -or ($null -ne $global:dgObjects.SelectedItem)
|
||||
Set-XamlProperty $global:dgObjects.Parent "btnDocument" "IsEnabled" $hasSelectedItems
|
||||
}
|
||||
|
||||
function Invoke-GraphObjectsChanged
|
||||
{
|
||||
$btnDocument = $global:spSubMenu.Children | Where-Object { $_.Name -eq "btnDocument" }
|
||||
@@ -87,6 +112,35 @@ function Invoke-ViewActivated
|
||||
}
|
||||
}
|
||||
|
||||
function Set-DocColumnHeaderLanguageId
|
||||
{
|
||||
param($columnName, $lngId)
|
||||
|
||||
if(-not $script:columnHeaders -or -not $lngId) { return }
|
||||
|
||||
if($script:columnHeaders.ContainsKey($columnName))
|
||||
{
|
||||
$script:columnHeaders[$columnName] = $lngId
|
||||
}
|
||||
else
|
||||
{
|
||||
$script:columnHeaders.Add($columnName, $lngId)
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-DocTranslateColumnHeader
|
||||
{
|
||||
param($columnName)
|
||||
|
||||
$lngText = ""
|
||||
if($script:columnHeaders.ContainsKey($columnName))
|
||||
{
|
||||
$lngText = Get-LanguageString $script:columnHeaders[$columnName]
|
||||
}
|
||||
|
||||
(?? $lngText $columnName)
|
||||
}
|
||||
|
||||
function Add-OutputType
|
||||
{
|
||||
param($outputInfo)
|
||||
@@ -588,27 +642,6 @@ function Add-ScopeTagStrings
|
||||
}
|
||||
}
|
||||
|
||||
function Get-AllEntityTypes
|
||||
{
|
||||
param($entityType, $xml, $hashTable)
|
||||
|
||||
if(-not $hashTable.ContainsKey($entityType))
|
||||
{
|
||||
$hashTable.Add($entityType, $xml.SelectSingleNode("//*[name()='EntityType' and @Name='$entityType']"))
|
||||
}
|
||||
|
||||
$nodes = $xml.SelectNodes("//*[@BaseType='graph.$entityType']")
|
||||
|
||||
foreach($node in $nodes)
|
||||
{
|
||||
if($node.Abstract -ne "true")
|
||||
{
|
||||
$hashTable.Add($node.Name, $node)
|
||||
}
|
||||
Get-AllEntityTypes $node.Name $xml $hashTable
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ObjectPlatformFromType
|
||||
{
|
||||
param($obj)
|
||||
|
||||
482
Extensions/DocumentationMD.psm1
Normal file
482
Extensions/DocumentationMD.psm1
Normal file
@@ -0,0 +1,482 @@
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.0.0'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
{
|
||||
Add-OutputType ([PSCustomObject]@{
|
||||
Name="Markdown (Experimental)"
|
||||
Value="md"
|
||||
#OutputOptions = (Add-MDOptionsControl)
|
||||
#Activate = { Invoke-MDActivate @args }
|
||||
PreProcess = { Invoke-MDPreProcessItems @args }
|
||||
NewObjectGroup = { Invoke-MDNewObjectGroup @args }
|
||||
Process = { Invoke-MDProcessItem @args }
|
||||
PostProcess = { Invoke-MDPostProcessItems @args }
|
||||
ProcessAllObjects = { Invoke-MDProcessAllObjects @args }
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
function Invoke-MDPreProcessItems
|
||||
{
|
||||
$script:mdStrings = [System.Text.StringBuilder]::new()
|
||||
$script:sectionAnchors = @()
|
||||
$script:totAnchors = @()
|
||||
}
|
||||
|
||||
function Invoke-MDPostProcessItems
|
||||
{
|
||||
$userName = $global:me.displayName
|
||||
if($global:me.givenName -and $global:me.surname)
|
||||
{
|
||||
$userName = ($global:me.givenName + " " + $global:me.surname)
|
||||
}
|
||||
|
||||
$script:mdContent = [System.Text.StringBuilder]::new()
|
||||
|
||||
$script:mdContent.AppendLine("# $((?? $global:txtMDTitleProperty.Text "Intune documentation"))")
|
||||
$script:mdContent.AppendLine("")
|
||||
$script:mdContent.AppendLine("")
|
||||
|
||||
$mail = ""
|
||||
if($global:me.mail)
|
||||
{
|
||||
$mail = " ($($global:me.mail))"
|
||||
}
|
||||
|
||||
$script:mdContent.AppendLine("*Organization:* $($global:Organization.displayName)`n")
|
||||
$script:mdContent.AppendLine("*Generated by:* $userName$mail`n")
|
||||
$script:mdContent.AppendLine("*Generated:* $((Get-Date).ToShortDateString()) $((Get-Date).ToLongTimeString())`n")
|
||||
|
||||
if($script:sectionAnchors.Count -gt 0)
|
||||
{
|
||||
$script:mdContent.AppendLine("")
|
||||
$script:mdContent.AppendLine("## Table of Contents")
|
||||
}
|
||||
|
||||
foreach($header in $script:sectionAnchors)
|
||||
{
|
||||
$script:mdContent.AppendLine("[$($header.Name)](#$($header.Anchor))`n")
|
||||
}
|
||||
|
||||
$script:mdContent.AppendLine("")
|
||||
$mdText = $script:mdContent.ToString()
|
||||
$mdText += $script:mdStrings.ToString()
|
||||
|
||||
$fileName = Expand-FileName "%MyDocuments%\%Organization%-%Date%.md"
|
||||
|
||||
try
|
||||
{
|
||||
$mdText | Out-File -FilePath $fileName -Force -Encoding utf8 -ErrorAction Stop
|
||||
Write-Log "Markdown document $fileName saved successfully"
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-LogError "Failed to save Markdown file" $_.Exception
|
||||
}
|
||||
}
|
||||
|
||||
function Invoke-MDNewObjectGroup
|
||||
{
|
||||
param($obj, $documentedObj)
|
||||
|
||||
$objectTypeString = Get-ObjectTypeString $obj.Object $obj.ObjectType
|
||||
|
||||
Add-MDHeader "$((?? $objectTypeString $obj.ObjectType.Title))" -Level 1 -USEHtml
|
||||
|
||||
}
|
||||
|
||||
function Invoke-MDProcessItem
|
||||
{
|
||||
param($obj, $objectType, $documentedObj)
|
||||
|
||||
if(!$documentedObj -or !$obj -or !$objectType) { return }
|
||||
|
||||
$objName = Get-GraphObjectName $obj $objectType
|
||||
|
||||
Add-MDHeader $objName -Level 2 -USEHtml
|
||||
|
||||
$script:mdStrings.AppendLine("")
|
||||
|
||||
try
|
||||
{
|
||||
foreach($tableType in @("BasicInfo","FilteredSettings"))
|
||||
{
|
||||
if($tableType -eq "BasicInfo")
|
||||
{
|
||||
$properties = @("Name","Value")
|
||||
}
|
||||
elseif($global:cbMDDocumentationProperties.SelectedValue -eq 'extended' -and $documentedObj.DisplayProperties)
|
||||
{
|
||||
$properties = @("Name","Value","Description")
|
||||
}
|
||||
elseif($global:cbMDDocumentationProperties.SelectedValue -eq 'custom' -and $global:txtMDCustomProperties.Text)
|
||||
{
|
||||
$properties = @()
|
||||
|
||||
foreach($prop in $global:txtMDCustomProperties.Text.Split(","))
|
||||
{
|
||||
# This will add language support for custom columens (or replacing existing header)
|
||||
$propInfo = $prop.Split('=')
|
||||
if(($propInfo | measure).Count -gt 1)
|
||||
{
|
||||
$properties += $propInfo[0]
|
||||
Set-DocColumnHeaderLanguageId $propInfo[0] $propInfo[1]
|
||||
}
|
||||
else
|
||||
{
|
||||
$properties += $prop
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$properties = (?? $documentedObj.DefaultDocumentationProperties (@("Name","Value")))
|
||||
}
|
||||
|
||||
$lngId = ?: ($tableType -eq "BasicInfo") "SettingDetails.basics" "TableHeaders.settings" -AddCategories
|
||||
|
||||
Add-MDTableItems $obj $objectType ($documentedObj.$tableType) $properties $lngId -AddCategories -AddSubcategories
|
||||
|
||||
#Add-MDTableItems $obj $objectType ($documentedObj.$tableType) $properties $lngId `
|
||||
# -AddCategories:($global:chkMDAddCategories.IsChecked -eq $true) `
|
||||
# -AddSubcategories:($global:chkMDAddSubCategories.IsChecked -eq $true)
|
||||
}
|
||||
|
||||
if(($documentedObj.ComplianceActions | measure).Count -gt 0)
|
||||
{
|
||||
$properties = @("Action","Schedule","MessageTemplate","EmailCC")
|
||||
|
||||
Add-MDTableItems $obj $objectType $documentedObj.ComplianceActions $properties "Category.complianceActionsLabel"
|
||||
}
|
||||
|
||||
if(($documentedObj.ApplicabilityRules | measure).Count -gt 0)
|
||||
{
|
||||
$properties = @("Rule","Property","Value")
|
||||
|
||||
Add-MDTableItems $obj $objectType $documentedObj.ApplicabilityRules $properties "SettingDetails.applicabilityRules"
|
||||
}
|
||||
|
||||
Add-MDObjectSettings $obj $objectType $documentedObj
|
||||
|
||||
if(($documentedObj.Assignments | measure).Count -gt 0)
|
||||
{
|
||||
$params = @{}
|
||||
if($documentedObj.Assignments[0].RawIntent)
|
||||
{
|
||||
$properties = @("GroupMode","Group","Filter","FilterMode")
|
||||
|
||||
$settingsObj = $documentedObj.Assignments | Where { $_.Settings -ne $null } | Select -First 1
|
||||
|
||||
if($settingsObj)
|
||||
{
|
||||
foreach($objProp in $settingsObj.Settings.Keys)
|
||||
{
|
||||
if($objProp -in $properties) { continue }
|
||||
if($objProp -in @("Category","RawIntent")) { continue }
|
||||
$properties += ("Settings." + $objProp)
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$isFilterAssignment = $false
|
||||
foreach($assignment in $documentedObj.Assignments)
|
||||
{
|
||||
if(($assignment.target.PSObject.Properties | Where Name -eq "deviceAndAppManagementAssignmentFilterType"))
|
||||
{
|
||||
$isFilterAssignment = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
$properties = @("Group")
|
||||
if($isFilterAssignment)
|
||||
{
|
||||
$properties += @("Filter","FilterMode")
|
||||
}
|
||||
$params.Add("AddCategories", $true)
|
||||
}
|
||||
|
||||
Add-MDTableItems $obj $objectType $documentedObj.Assignments $properties "TableHeaders.assignments" @params
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-LogError "Failed to process object $objName" $_.Exception
|
||||
}
|
||||
}
|
||||
|
||||
function Add-MDTableItems
|
||||
{
|
||||
param($obj, $objectType, $items, $properties, $lngId, [switch]$AddCategories, [switch]$AddSubcategories, $captionOverride)
|
||||
|
||||
if($captionOverride)
|
||||
{
|
||||
$caption = $captionOverride
|
||||
}
|
||||
elseif($lngId)
|
||||
{
|
||||
$caption = "$((Get-LanguageString $lngId)) - $((Get-GraphObjectName $obj $objectType))"
|
||||
}
|
||||
else
|
||||
{
|
||||
$caption = "$((Get-GraphObjectName $obj $objectType)) ($($objectType.Title))"
|
||||
}
|
||||
|
||||
$tableText = [System.Text.StringBuilder]::new()
|
||||
$tableText.AppendLine("<table>")
|
||||
$tableText.AppendLine("<tr>")
|
||||
$columnHeaders = "|"
|
||||
$columnChars = "|"
|
||||
$columnCount = 0
|
||||
foreach($prop in $properties)
|
||||
{
|
||||
$tableText.AppendLine("<td> $($prop.Split(".")[-1]) </td>")
|
||||
$columnCount++
|
||||
|
||||
$columnHeaders += ((Invoke-DocTranslateColumnHeader ($prop.Split(".")[-1])) + "|")
|
||||
$columnChars += "----|"
|
||||
}
|
||||
$tableText.AppendLine("</tr>")
|
||||
|
||||
#Add-MDText $columnHeaders
|
||||
#Add-MDText $columnChars
|
||||
|
||||
$curCategory = ""
|
||||
$curSubCategory = ""
|
||||
|
||||
$columnCategory = $null
|
||||
$columnSubCategory = $null
|
||||
|
||||
foreach($itemObj in $items)
|
||||
{
|
||||
if($itemObj.Category -and $curCategory -ne $itemObj.Category -and $AddCategories -eq $true)
|
||||
{
|
||||
$tableText.AppendLine("<tr>")
|
||||
$tableText.AppendLine("<td colspan=`"$($columnCount)`">`n`n**$((Set-MDText $itemObj.Category))**`n`n</td>")
|
||||
$tableText.AppendLine("</tr>")
|
||||
|
||||
#$columnCategory = "|**" + (Set-MDText $itemObj.Category) + "**|"
|
||||
#Add-MDText $columnCategory
|
||||
$curCategory = $itemObj.Category
|
||||
$curSubCategory = ""
|
||||
}
|
||||
|
||||
if($itemObj.SubCategory -and $curSubCategory -ne $itemObj.SubCategory -and $AddSubcategories -eq $true)
|
||||
{
|
||||
$tableText.AppendLine("<tr>")
|
||||
$tableText.AppendLine("<td colspan=`"$($columnCount)`">`n`n***$((Set-MDText $itemObj.SubCategory))***`n`n</td>")
|
||||
$tableText.AppendLine("</tr>")
|
||||
|
||||
#$columnSubCategory = "|***" + (Set-MDText $itemObj.SubCategory) + "***|"
|
||||
#Add-MDText $columnSubCategory
|
||||
$curSubCategory = $itemObj.SubCategory
|
||||
}
|
||||
|
||||
#$columnData = "|"
|
||||
try
|
||||
{
|
||||
$tableText.AppendLine("<tr>")
|
||||
|
||||
foreach($prop in $properties)
|
||||
{
|
||||
try
|
||||
{
|
||||
# This adds support for properties like Settings.PropName
|
||||
$propArr = $prop.Split('.')
|
||||
$tmpObj = $itemObj
|
||||
$propName = $propArr[-1]
|
||||
for($x = 0; $x -lt ($propArr.Count - 1);$x++)
|
||||
{
|
||||
$tmpObj = $tmpObj."$($propArr[$x])"
|
||||
}
|
||||
$tableText.AppendLine("<td>$((Set-MDText "$($tmpObj.$propName)" -CodeBlock))</td>")
|
||||
#$columnData += "$((Set-MDText "$($tmpObj.$propName)"))|"
|
||||
}
|
||||
catch
|
||||
{
|
||||
#$columnData += "|"
|
||||
Write-LogError "Failed to add property value for $prop" $_.Exception
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Log "Failed to process property" 2
|
||||
}
|
||||
finally
|
||||
{
|
||||
$tableText.AppendLine("</tr>")
|
||||
}
|
||||
|
||||
#Add-MDText $columnData
|
||||
}
|
||||
|
||||
$tableText.AppendLine("</table>")
|
||||
Add-MDText $tableText.ToString()
|
||||
|
||||
Add-MDHeader $caption -Level 6 -TOT -AddParagraph
|
||||
}
|
||||
|
||||
function Add-MDText
|
||||
{
|
||||
param($text, [switch]$AddParagraph)
|
||||
|
||||
$script:mdStrings.AppendLine($text)
|
||||
|
||||
if($AddParagraph -eq $true)
|
||||
{
|
||||
# Add new paragraph by default
|
||||
$script:mdStrings.AppendLine("")
|
||||
}
|
||||
}
|
||||
|
||||
function Set-MDText
|
||||
{
|
||||
param($text, [switch]$CodeBlock)
|
||||
|
||||
if($CodeBlock -eq $true)
|
||||
{
|
||||
$trimText = $text.Trim()
|
||||
if($trimText.StartsWith("<") -and $trimText.EndsWith(">"))
|
||||
{
|
||||
return ([Environment]::NewLine + [Environment]::NewLine + "``````xml" + [Environment]::NewLine + $text + [Environment]::NewLine + "``````" + [Environment]::NewLine + [Environment]::NewLine)
|
||||
}
|
||||
}
|
||||
|
||||
$text = $text.Replace("|", '`|')
|
||||
$text = $text.Replace("*", '`*')
|
||||
$text = $text.Replace("$", '`$')
|
||||
$text = $text.Replace("`r`n", "<br />")
|
||||
$text = $text.Replace("`n", "<br />")
|
||||
|
||||
$text
|
||||
}
|
||||
|
||||
function Add-MDHeader
|
||||
{
|
||||
param($text, [int]$level = 1, [switch]$AddParagraph, [switch]$UseHTML, [switch]$ToT, [switch]$SkipTOC)
|
||||
|
||||
$prefix = ""
|
||||
if($ToT -eq $true)
|
||||
{
|
||||
$prefix = "Table $(($script:totAnchors.Count + 1)). "
|
||||
}
|
||||
|
||||
if($UseHTML -eq $true)
|
||||
{
|
||||
if($ToT -eq $true)
|
||||
{
|
||||
$sectionAnchor = "table-$(($script:totAnchors.Count + 1))"
|
||||
}
|
||||
else
|
||||
{
|
||||
$sectionAnchor = "section-$(($script:sectionAnchors.Count + 1))"
|
||||
}
|
||||
|
||||
$script:mdStrings.AppendLine("<h$level id=`"$prefix$($sectionAnchor)`">$text</h$level>")
|
||||
}
|
||||
else
|
||||
{
|
||||
# Warnig: Not complete! Use HTML if not working...
|
||||
$text = "$prefix$text"
|
||||
$sectionAnchor = $text.ToLower().Replace(" ","-").Replace("[","").Replace("]","")
|
||||
|
||||
$mdHeader = [String]::new('#',$level)
|
||||
$script:mdStrings.AppendLine("$mdHeader $text")
|
||||
}
|
||||
|
||||
if($ToT -eq $true)
|
||||
{
|
||||
$script:totAnchors += [PSCustomObject]@{
|
||||
Name = $text
|
||||
Anchor = $sectionAnchor
|
||||
}
|
||||
}
|
||||
elseif($SkipTOC -ne $true)
|
||||
{
|
||||
$script:sectionAnchors += [PSCustomObject]@{
|
||||
Name = $text
|
||||
Anchor = $sectionAnchor
|
||||
}
|
||||
}
|
||||
|
||||
if($AddParagraph -eq $true)
|
||||
{
|
||||
# Add new paragraph by default
|
||||
$script:mdStrings.AppendLine("`n")
|
||||
}
|
||||
}
|
||||
|
||||
function Add-MDObjectSettings
|
||||
{
|
||||
param($obj, $objectType, $documentedObj)
|
||||
|
||||
if($obj."@OData.Type" -eq "#microsoft.graph.deviceManagementScript")
|
||||
{
|
||||
if($obj.ScriptContent)
|
||||
{
|
||||
$script:mdStrings.AppendLine("~~~powershell")
|
||||
$script:mdStrings.AppendLine((Get-DocScriptContent $obj.ScriptContent))
|
||||
$script:mdStrings.AppendLine("~~~")
|
||||
$caption = "{1} - {0}" -f $obj.fileName,(Get-LanguageString "WindowsManagement.powerShellScriptObjectName")
|
||||
Add-MDHeader $caption -Level 6 -SkipTOC -AddParagraph
|
||||
}
|
||||
}
|
||||
if($obj."@OData.Type" -eq "#microsoft.graph.deviceShellScript")
|
||||
{
|
||||
if($obj.ScriptContent)
|
||||
{
|
||||
$script:mdStrings.AppendLine("~~~shell")
|
||||
$script:mdStrings.AppendLine((Get-DocScriptContent $obj.ScriptContent))
|
||||
$script:mdStrings.AppendLine("~~~")
|
||||
|
||||
$caption = "{1} - {0}" -f $obj.fileName,(Get-LanguageString "WindowsManagement.shellScriptObjectName")
|
||||
Add-MDHeader $caption -Level 6 -SkipTOC -AddParagraph
|
||||
}
|
||||
}
|
||||
elseif($obj."@OData.Type" -eq "#microsoft.graph.deviceHealthScript")
|
||||
{
|
||||
if($obj.detectionScriptContent)
|
||||
{
|
||||
$script:mdStrings.AppendLine("~~~powershell")
|
||||
$script:mdStrings.AppendLine((Get-DocScriptContent $obj.detectionScriptContent))
|
||||
$script:mdStrings.AppendLine("~~~")
|
||||
$caption = Get-LanguageString "ProactiveRemediations.Create.Settings.DetectionScriptMultiLineTextBox.label"
|
||||
Add-MDHeader $caption -Level 6 -SkipTOC -AddParagraph
|
||||
}
|
||||
|
||||
if($obj.remediationScriptContent)
|
||||
{
|
||||
$script:mdStrings.AppendLine("~~~powershell")
|
||||
$script:mdStrings.AppendLine((Get-DocScriptContent $obj.remediationScriptContent))
|
||||
$script:mdStrings.AppendLine("~~~")
|
||||
$caption = Get-LanguageString "ProactiveRemediations.Create.Settings.RemediationScriptMultiLineTextBox.label"
|
||||
Add-MDHeader $caption -Level 6 -SkipTOC -AddParagraph
|
||||
}
|
||||
}
|
||||
elseif($obj."@OData.Type" -eq "#microsoft.graph.win32LobApp")
|
||||
{
|
||||
foreach($rule in ($obj.requirementRules | Where { $_.'@OData.Type' -eq "#microsoft.graph.win32LobAppPowerShellScriptRequirement" } ))
|
||||
{
|
||||
$script:mdStrings.AppendLine("~~~powershell")
|
||||
$script:mdStrings.AppendLine((Get-DocScriptContent $obj.scriptContent))
|
||||
$script:mdStrings.AppendLine("~~~")
|
||||
$caption = "{0} - {1}" -f @($obj.displayName, "Requirement script")
|
||||
Add-MDHeader $caption -Level 6 -SkipTOC -AddParagraph
|
||||
}
|
||||
|
||||
foreach($rule in ($obj.detectionRules | Where { $_.'@OData.Type' -eq "#microsoft.graph.win32LobAppPowerShellScriptDetection" } ))
|
||||
{
|
||||
$script:mdStrings.AppendLine("~~~powershell")
|
||||
$script:mdStrings.AppendLine((Get-DocScriptContent $obj.scriptContent))
|
||||
$script:mdStrings.AppendLine("~~~")
|
||||
$caption = "{0} - {1}" -f @($obj.displayName,(Get-LanguageString "ProactiveRemediations.Create.Settings.DetectionScriptMultiLineTextBox.label"))
|
||||
Add-MDHeader $caption -Level 6 -SkipTOC -AddParagraph
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
#https://docs.microsoft.com/en-us/office/vba/api/overview/word
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.0.6'
|
||||
'1.0.7'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -163,7 +163,7 @@ function Invoke-WordPreProcessItems
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-LogError "Failed to create document based on tmeplate: $($global:txtWordDocumentTemplate.Text)" $_.Exception
|
||||
Write-LogError "Failed to create document based on template: $($global:txtWordDocumentTemplate.Text)" $_.Exception
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -442,7 +442,7 @@ function Invoke-WordProcessItem
|
||||
|
||||
foreach($prop in $global:txtWordCustomProperties.Text.Split(","))
|
||||
{
|
||||
# This will add language support for custom colument (or replacing existing header)
|
||||
# This will add language support for custom columens (or replacing existing header)
|
||||
$propInfo = $prop.Split('=')
|
||||
if(($propInfo | measure).Count -gt 1)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ This module is for the Endpoint Manager/Intune View. It manages Export/Import/Co
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.1.13'
|
||||
'3.1.14'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -225,6 +225,7 @@ function Invoke-InitializeModule
|
||||
Icon = "Branding"
|
||||
SkipRemoveProperties = @('Id')
|
||||
GroupId = "Azure"
|
||||
SkipAddIDOnExport = $true
|
||||
})
|
||||
|
||||
Add-ViewItem (New-Object PSObject -Property @{
|
||||
@@ -722,9 +723,7 @@ function Set-EMViewPanel
|
||||
Set-XamlProperty $panel "btnDelete" "Visibility" (?: ($allowDelete -eq $true) "Visible" "Collapsed")
|
||||
|
||||
$global:dgObjects.add_selectionChanged({
|
||||
Set-XamlProperty $this.Parent "btnView" "IsEnabled" (?: ($null -eq $global:dgObjects.SelectedItem) $false $true)
|
||||
Set-XamlProperty $this.Parent "btnCopy" "IsEnabled" (?: ($null -eq $global:dgObjects.SelectedItem) $false $true)
|
||||
Set-XamlProperty $this.Parent "btnDelete" "IsEnabled" (?: ($null -eq $global:dgObjects.SelectedItem -and $global:curObjectType.AllowDelete -ne $false) $false $true)
|
||||
Invoke-ModuleFunction "Invoke-EMSelectedItemsChanged"
|
||||
})
|
||||
|
||||
# ToDo: Move this to the view object
|
||||
@@ -760,12 +759,40 @@ function Set-EMViewPanel
|
||||
Show-GraphObjects
|
||||
Write-Status ""
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
$global:btnLoadAllPages.add_click({
|
||||
Write-Status "Loading $($global:curObjectType.Title) objects"
|
||||
$graphObjects = @(Get-GraphObjects -property $global:curObjectType.ViewProperties -objectType $global:curObjectType -AllPages)
|
||||
$graphObjects | ForEach-Object { $global:dgObjects.ItemsSource.AddNewItem($_) | Out-Null }
|
||||
$global:dgObjects.ItemsSource.CommitNew()
|
||||
Set-GraphPagesButtonStatus
|
||||
Invoke-FilterBoxChanged $global:txtFilter -ForceUpdate
|
||||
Write-Status ""
|
||||
})
|
||||
|
||||
$global:btnLoadNextPage.add_click({
|
||||
Write-Status "Loading $($global:curObjectType.Title) objects"
|
||||
$graphObjects = @(Get-GraphObjects -property $global:curObjectType.ViewProperties -objectType $global:curObjectType -SinglePage)
|
||||
$graphObjects | ForEach-Object { $global:dgObjects.ItemsSource.AddNewItem($_) | Out-Null }
|
||||
$global:dgObjects.ItemsSource.CommitNew()
|
||||
Set-GraphPagesButtonStatus
|
||||
Invoke-FilterBoxChanged $global:txtFilter -ForceUpdate
|
||||
Write-Status ""
|
||||
})
|
||||
}
|
||||
|
||||
function Invoke-EMSelectedItemsChanged
|
||||
{
|
||||
$hasSelectedItems = ($global:dgObjects.ItemsSource | Where IsSelected -eq $true) -or ($null -ne $global:dgObjects.SelectedItem)
|
||||
Set-XamlProperty $global:dgObjects.Parent "btnView" "IsEnabled" $hasSelectedItems #(?: ($null -eq ($global:dgObjects.SelectedItem)) $false $true)
|
||||
Set-XamlProperty $global:dgObjects.Parent "btnCopy" "IsEnabled" $hasSelectedItems #(?: ($null -eq $global:dgObjects.SelectedItem) $false $true)
|
||||
Set-XamlProperty $global:dgObjects.Parent "btnDelete" "IsEnabled" $hasSelectedItems #(?: ($null -eq $global:dgObjects.SelectedItem -and $global:curObjectType.AllowDelete -ne $false) $false $true)
|
||||
}
|
||||
|
||||
function Invoke-FilterBoxChanged
|
||||
{
|
||||
param($txtBox)
|
||||
param($txtBox,[switch]$ForceUpdate)
|
||||
|
||||
$filter = $null
|
||||
|
||||
@@ -774,11 +801,18 @@ function Invoke-FilterBoxChanged
|
||||
$txtBox.FontStyle = "Italic"
|
||||
$txtBox.Tag = 1
|
||||
$txtBox.Text = "Filter"
|
||||
$txtBox.Foreground="Lightgray"
|
||||
$txtBox.Foreground="Lightgray"
|
||||
}
|
||||
elseif($ForceUpdate -eq $true)
|
||||
{
|
||||
$dgObjects.ItemsSource.Filter = $dgObjects.ItemsSource.Filter
|
||||
}
|
||||
elseif($txtBox.Tag -eq "1" -and $txtBox.Text -eq "Filter" -and $txtBox.IsFocused -eq $false)
|
||||
{
|
||||
|
||||
}
|
||||
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"
|
||||
@@ -800,11 +834,9 @@ function Invoke-FilterBoxChanged
|
||||
}
|
||||
}
|
||||
|
||||
if($dgObjects.ItemsSource -is [System.Windows.Data.ListCollectionView])
|
||||
if($dgObjects.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
|
||||
$dgObjects.ItemsSource.Filter = $filter
|
||||
$dgObjects.ItemsSource.Refresh()
|
||||
}
|
||||
|
||||
$allObjectsCount = 0
|
||||
@@ -869,9 +901,15 @@ function Start-PostExportEndpointSecurity
|
||||
{
|
||||
param($obj, $objectType, $path)
|
||||
|
||||
$fileName = (Get-GraphObjectName $obj $objectType)
|
||||
if((Get-SettingValue "AddIDToExportFile") -eq $true -and $obj.Id)
|
||||
{
|
||||
$fileName = ($fileName + "_" + $obj.Id)
|
||||
}
|
||||
|
||||
$settings = Invoke-GraphRequest -Url "$($objectType.API)/$($obj.id)/settings"
|
||||
$settingsJson = "{ `"settings`": $((ConvertTo-Json $settings.value -Depth 20 ))`n}"
|
||||
$fileName = "$path\$((Remove-InvalidFileNameChars (Get-GraphObjectName $obj $objectType)))_Settings.json"
|
||||
$fileName = "$path\$((Remove-InvalidFileNameChars $fileName))_Settings.json"
|
||||
$settingsJson | Out-File -LiteralPath $fileName -Force
|
||||
}
|
||||
|
||||
@@ -1142,8 +1180,8 @@ function Start-PostGetIntuneBranding
|
||||
|
||||
foreach($imgType in @("themeColorLogo","lightBackgroundLogo","landingPageCustomizedImage"))
|
||||
{
|
||||
Write-LogDebug "Get $imgType for $($obj.profileName)"
|
||||
$imgJson = Invoke-GraphRequest -Url "$($objectType.API)/$($obj.Id)/$imgType"
|
||||
Write-LogDebug "Get $imgType for $($obj.Object.profileName)"
|
||||
$imgJson = Invoke-GraphRequest -Url "$($objectType.API)/$($obj.Object.Id)/$imgType"
|
||||
if($imgJson.Value)
|
||||
{
|
||||
$obj.Object.$imgType = $imgJson
|
||||
@@ -1793,9 +1831,23 @@ function Start-PostExportAdministrativeTemplate
|
||||
{
|
||||
param($obj, $objectType, $path)
|
||||
|
||||
$fileName = (Get-GraphObjectName $obj $objectType)
|
||||
if((Get-SettingValue "AddIDToExportFile") -eq $true -and $obj.Id)
|
||||
{
|
||||
$fileName = ($fileName + "_" + $obj.Id)
|
||||
}
|
||||
|
||||
# Collect and save all the settings of the Administrative Templates profile
|
||||
$settings = Get-GPOObjectSettings $obj
|
||||
$fileName = "$path\$((Remove-InvalidFileNameChars (Get-GraphObjectName $obj $objectType)))_Settings.json"
|
||||
if($obj.definitionValues)
|
||||
{
|
||||
$settings = $obj.definitionValues
|
||||
}
|
||||
else
|
||||
{
|
||||
$settings = Get-GPOObjectSettings $obj
|
||||
}
|
||||
|
||||
$fileName = "$path\$((Remove-InvalidFileNameChars $fileName))_Settings.json"
|
||||
ConvertTo-Json $settings -Depth 20 | Out-File -LiteralPath $fileName -Force
|
||||
}
|
||||
|
||||
@@ -1858,7 +1910,7 @@ function Start-PostGetAdministrativeTemplate
|
||||
$obj.Object | Add-Member Noteproperty -Name "definitionValues" -Value $definitionValues -Force
|
||||
}
|
||||
<#
|
||||
# Leave for now. This only loads the configured defenition values and not the values specified.
|
||||
# Leave for now. This only loads the configured definition values and not the values specified.
|
||||
# That would require enumerating each definition value which takes time.
|
||||
$definitionValues = (Invoke-GraphRequest "deviceManagement/groupPolicyConfigurations('$($obj.Id)')/definitionValues?`$expand=definition(`$select=id,classType,displayName,policyType,groupPolicyCategoryId)" -ODataMetadata "minimal").value
|
||||
|
||||
@@ -2025,8 +2077,21 @@ function Start-PostExportRoleDefinitions
|
||||
{
|
||||
param($obj, $objectType, $path)
|
||||
|
||||
$fileName = "$path\$((Remove-InvalidFileNameChars (Get-GraphObjectName $obj $objectType))).json"
|
||||
$tmpObj = Get-Content -LiteralPath $fileName | ConvertFrom-Json
|
||||
$fileName = (Get-GraphObjectName $obj $objectType)
|
||||
if((Get-SettingValue "AddIDToExportFile") -eq $true -and $obj.Id)
|
||||
{
|
||||
$fileName = ($fileName + "_" + $obj.Id)
|
||||
}
|
||||
$tmpObj = $null
|
||||
$fileName = "$path\$((Remove-InvalidFileNameChars $fileName)).json"
|
||||
if([IO.File]::Exists($fileName))
|
||||
{
|
||||
$tmpObj = Get-Content -LiteralPath $fileName | ConvertFrom-Json
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Log "File not found: $fileName. Could not get role assignments" 3
|
||||
}
|
||||
|
||||
if(($tmpObj.RoleAssignments | measure).Count -gt 0)
|
||||
{
|
||||
@@ -2397,10 +2462,15 @@ function Add-EMAssignmentsToExportFile
|
||||
{
|
||||
param($obj, $objectType, $path, $Url = "")
|
||||
|
||||
$fileName = "$path\$((Remove-InvalidFileNameChars (Get-GraphObjectName $obj $objectType))).json"
|
||||
$fileName = (Get-GraphObjectName $obj $objectType)
|
||||
if((Get-SettingValue "AddIDToExportFile") -eq $true -and $obj.Id)
|
||||
{
|
||||
$fileName = ($fileName + "_" + $obj.Id)
|
||||
}
|
||||
$fileName = "$path\$((Remove-InvalidFileNameChars $fileName)).json"
|
||||
if([IO.File]::Exists($fileName) -eq $false)
|
||||
{
|
||||
Write-Log "File not found: $fileName. Could not add assignments" 3
|
||||
Write-Log "File not found: $fileName. Could not add assignments to file" 3
|
||||
return
|
||||
}
|
||||
$tmpObj = Get-Content -LiteralPath $fileName | ConvertFrom-Json
|
||||
|
||||
@@ -10,7 +10,7 @@ This module manages Application objects in Intune e.g. uploading application fil
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.1.1'
|
||||
'3.1.2'
|
||||
}
|
||||
|
||||
#########################################################################################
|
||||
@@ -42,6 +42,12 @@ function Get-MSIFileInformation
|
||||
|
||||
$values = @{}
|
||||
|
||||
if(-not $MSIFile) { return }
|
||||
|
||||
$fi = [IO.FileInfo]$MSIFile
|
||||
|
||||
if($fi.Extension -ne ".msi") { return }
|
||||
|
||||
try
|
||||
{
|
||||
$wiObj = New-Object -ComObject WindowsInstaller.Installer
|
||||
|
||||
@@ -9,7 +9,7 @@ Module for listing Intune assignments
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.0.2'
|
||||
'1.0.3'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -231,10 +231,13 @@ function Invoke-IntueAssignmentFilterBoxChanged
|
||||
$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
|
||||
{
|
||||
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"
|
||||
@@ -245,15 +248,15 @@ function Invoke-IntueAssignmentFilterBoxChanged
|
||||
$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) )
|
||||
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])
|
||||
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()
|
||||
#$dgObject.ItemsSource.Refresh()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ $global:EMToolsViewObject = $null
|
||||
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'1.0.2'
|
||||
'1.0.3'
|
||||
}
|
||||
|
||||
function Invoke-InitializeModule
|
||||
@@ -890,10 +890,13 @@ function Invoke-ADMXFilterPolicies
|
||||
$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
|
||||
{
|
||||
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"
|
||||
@@ -908,11 +911,11 @@ function Invoke-ADMXFilterPolicies
|
||||
}
|
||||
}
|
||||
|
||||
if($global:dgADMXSettings.ItemsSource -is [System.Windows.Data.ListCollectionView])
|
||||
if($global:dgADMXSettings.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
|
||||
$global:dgADMXSettings.ItemsSource.Filter = $filter
|
||||
$global:dgADMXSettings.ItemsSource.Refresh()
|
||||
#$global:dgADMXSettings.ItemsSource.Refresh()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ This module manages Authentication for the application with MSAL. It is also res
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.3.1'
|
||||
'3.3.2'
|
||||
}
|
||||
|
||||
$global:msalAuthenticator = $null
|
||||
@@ -121,6 +121,14 @@ function Invoke-InitializeModule
|
||||
DefaultValue = "gcc"
|
||||
}) "MSAL"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Sort Account List"
|
||||
Key = "SortAccountList"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "Sort the list of cached accounts based on user name. Updated at restart or account change"
|
||||
}) "MSAL"
|
||||
|
||||
Add-MSALPrereq
|
||||
|
||||
#$script:MSALDLLMissing = $true #!!!!
|
||||
@@ -1389,13 +1397,21 @@ function Get-MSALProfileEllipse
|
||||
[System.Windows.Controls.Canvas]::SetTop($obj,($point.Y + $obj.Tag.ActualHeight))
|
||||
})
|
||||
|
||||
$otherLogins = $global:grdProfileInfo.FindName("grdAccountsAndTenants")
|
||||
$otherLogins = $global:grdProfileInfo.FindName("grdCachedAccounts")
|
||||
|
||||
#########################################################################################################
|
||||
### Add cached users
|
||||
#########################################################################################################
|
||||
if((Get-SettingValue "SortAccountList") -eq $true)
|
||||
{
|
||||
$accounts = $global:MSALAccounts | Sort -Property Username
|
||||
}
|
||||
else
|
||||
{
|
||||
$accounts = $global:MSALAccounts
|
||||
}
|
||||
|
||||
foreach($account in $global:MSALAccounts)
|
||||
foreach($account in $accounts)
|
||||
{
|
||||
# Skip current logged on user
|
||||
if($global:MSALToken.Account.Username -eq $Account.Username) { continue }
|
||||
@@ -1518,9 +1534,13 @@ function Get-MSALProfileEllipse
|
||||
Show-GraphObjects
|
||||
}
|
||||
Write-Status ""
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
$otherLogins = $global:grdProfileInfo.FindName("grdLoginAccount")
|
||||
|
||||
Add-GridObject $otherLogins $lnkButton
|
||||
|
||||
$otherLogins = $global:grdProfileInfo.FindName("grdTenantAccounts")
|
||||
|
||||
if(($script:AccessableTenants | measure).Count -gt 1)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ This module manages Microsoft Grap fuctions like calling APIs, managing graph ob
|
||||
#>
|
||||
function Get-ModuleVersion
|
||||
{
|
||||
'3.1.9'
|
||||
'3.1.10'
|
||||
}
|
||||
|
||||
$global:MSGraphGlobalApps = @(
|
||||
@@ -158,7 +158,24 @@ function Invoke-InitializeModule
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "This will add object ID to the export file to support objects with the same name e.g. ObjectName_ObjectId.json"
|
||||
}) "ImportExport"
|
||||
}) "ImportExport"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Use Batch API (Preview)"
|
||||
Key = "UseBatchAPI"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $false
|
||||
Description = "This will use batch API to call up to extport 20 objects on each API call"
|
||||
}) "ImportExport"
|
||||
|
||||
Add-SettingsObject (New-Object PSObject -Property @{
|
||||
Title = "Refresh Objects after copy"
|
||||
Key = "RefreshObjectsAfterCopy"
|
||||
Type = "Boolean"
|
||||
DefaultValue = $true
|
||||
Description = "This will refresh all objects when after a copy. If this is disabled, the list must be refreshed manually to see the new objects. Default is true"
|
||||
}) "ImportExport"
|
||||
|
||||
}
|
||||
|
||||
function Get-GraphAppInfo
|
||||
@@ -240,6 +257,12 @@ function Invoke-GraphRequest
|
||||
[switch]
|
||||
$AllPages,
|
||||
|
||||
[int]
|
||||
$PageSize = -1,
|
||||
|
||||
[switch]
|
||||
$Batch,
|
||||
|
||||
[switch]
|
||||
$NoError
|
||||
)
|
||||
@@ -313,12 +336,8 @@ function Invoke-GraphRequest
|
||||
$Url = $Url -replace "%OrganizationId%", $global:Organization.Id
|
||||
}
|
||||
|
||||
<#
|
||||
if($AllPages)
|
||||
{
|
||||
# Code to test paging - Force each page to size specified in top parameter below
|
||||
# Kept for reference
|
||||
|
||||
if($PageSize -gt 0 -and $url.IndexOf("`$top=") -eq -1)
|
||||
{
|
||||
if(($url.IndexOf('?')) -eq -1)
|
||||
{
|
||||
$url = "$($url.Trim())?"
|
||||
@@ -327,9 +346,8 @@ function Invoke-GraphRequest
|
||||
{
|
||||
$url = "$($url.Trim())&"
|
||||
}
|
||||
$url = "$($url.Trim())`$top=20"
|
||||
$url = "$($url.Trim())`$top=$($PageSize)"
|
||||
}
|
||||
#>
|
||||
|
||||
$ret = $null
|
||||
try
|
||||
@@ -390,13 +408,15 @@ function Get-GraphObjects
|
||||
$exclude,
|
||||
$SortProperty = "displayName",
|
||||
$objectType,
|
||||
[string]
|
||||
$select,
|
||||
[switch]
|
||||
$SinglePage,
|
||||
[switch]
|
||||
$AllPages,
|
||||
[switch]
|
||||
$SingleObject)
|
||||
|
||||
$objects = @()
|
||||
|
||||
if($property -isnot [Object[]]) { $property = @('displayName', 'description', 'id')}
|
||||
|
||||
|
||||
$params = @{}
|
||||
if($objectType.ODataMetadata)
|
||||
{
|
||||
@@ -417,15 +437,35 @@ function Get-GraphObjects
|
||||
else
|
||||
{
|
||||
$url = "$($url.Trim())&$($objectType.QUERYLIST.Trim())" # Risky...does not check that the parameter is already in use
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(($url.IndexOf("`$select=")) -eq -1 -and $select)
|
||||
{
|
||||
$url += (?: (($url.IndexOf('?')) -eq -1) "?" "&")
|
||||
$url += "`$select=$select"
|
||||
}
|
||||
|
||||
if($SingleObject -ne $true)
|
||||
if($SinglePage -eq $true)
|
||||
{
|
||||
#Use default page size or use below for a specific page size for testing
|
||||
#$params.Add("pageSize",100)
|
||||
}
|
||||
elseif($SingleObject -ne $true -and $SinglePage -ne $true)
|
||||
{
|
||||
$params.Add('AllPages',$true)
|
||||
}
|
||||
|
||||
if($script:nextGraphPage -and ($SinglePage -eq $true -or $AllPages -eq $true))
|
||||
{
|
||||
$url = $script:nextGraphPage
|
||||
}
|
||||
|
||||
$graphObjects = Invoke-GraphRequest -Url $url @params
|
||||
if($SinglePage -eq $true -or $AllPages -eq $true)
|
||||
{
|
||||
$script:nextGraphPage = $graphObjects.'@odata.nextLink'
|
||||
}
|
||||
|
||||
if($SingleObject -ne $true -and $objectType.PostListCommand)
|
||||
{
|
||||
@@ -441,6 +481,56 @@ function Get-GraphObjects
|
||||
$retObjects = $graphObjects
|
||||
}
|
||||
|
||||
return (Add-GraphObectProperties $retObjects $objectType $property $SortProperty)
|
||||
|
||||
$objects = @()
|
||||
|
||||
foreach($graphObject in $retObjects)
|
||||
{
|
||||
$params = @{}
|
||||
if($property) { $params.Add("Property", $property) }
|
||||
if($exclude) { $params.Add("ExcludeProperty", $exclude) }
|
||||
foreach($objTmp in ($graphObject | Select-Object @params))
|
||||
{
|
||||
$objTmp | Add-Member -NotePropertyName "IsSelected" -NotePropertyValue $false
|
||||
$objTmp | Add-Member -NotePropertyName "Object" -NotePropertyValue $graphObject
|
||||
$objTmp | Add-Member -NotePropertyName "ObjectType" -NotePropertyValue $objectType
|
||||
$objects += $objTmp
|
||||
}
|
||||
}
|
||||
$property = "IsSelected",$property
|
||||
|
||||
if($objects.Count -gt 0 -and $SortProperty -and ($objects[0] | GM -MemberType NoteProperty -Name $SortProperty))
|
||||
{
|
||||
$objects = $objects | sort -Property $SortProperty
|
||||
}
|
||||
|
||||
$objects
|
||||
}
|
||||
|
||||
function Add-GraphObectProperties
|
||||
{
|
||||
param($graphObjects,
|
||||
$objectType,
|
||||
[Array]
|
||||
$property = $null,
|
||||
[Array]
|
||||
$exclude,
|
||||
$SortProperty = "displayName")
|
||||
|
||||
if($property -isnot [Object[]]) { $property = @('displayName', 'description', 'id')}
|
||||
|
||||
$objects = @()
|
||||
|
||||
if($graphObjects -and ($graphObjects | GM -Name Value -MemberType NoteProperty))
|
||||
{
|
||||
$retObjects = $graphObjects.Value
|
||||
}
|
||||
else
|
||||
{
|
||||
$retObjects = $graphObjects
|
||||
}
|
||||
|
||||
foreach($graphObject in $retObjects)
|
||||
{
|
||||
$params = @{}
|
||||
@@ -460,6 +550,7 @@ function Get-GraphObjects
|
||||
{
|
||||
$objects = $objects | sort -Property $SortProperty
|
||||
}
|
||||
|
||||
$objects
|
||||
}
|
||||
|
||||
@@ -505,13 +596,15 @@ function Show-GraphObjects
|
||||
$global:grdTitle.Visibility = "Visible"
|
||||
}
|
||||
|
||||
$graphObjects = @(Get-GraphObjects -property $global:curObjectType.ViewProperties -objectType $global:curObjectType)
|
||||
$script:nextGraphPage = $null
|
||||
|
||||
$graphObjects = @(Get-GraphObjects -property $global:curObjectType.ViewProperties -objectType $global:curObjectType -SinglePage)
|
||||
|
||||
$dgObjects.AutoGenerateColumns = $false
|
||||
$dgObjects.Columns.Clear()
|
||||
|
||||
if(($graphObjects | measure).Count -gt 0)
|
||||
{
|
||||
{
|
||||
$tmpObj = $graphObjects | Select -First 1
|
||||
|
||||
$prop = $tmpObj.PSObject.Properties | Where Name -eq "IsSelected"
|
||||
@@ -526,6 +619,7 @@ function Show-GraphObjects
|
||||
$item.IsSelected = $this.IsChecked
|
||||
}
|
||||
$global:dgObjects.Items.Refresh()
|
||||
Invoke-ModuleFunction "Invoke-EMSelectedItemsChanged"
|
||||
})
|
||||
}
|
||||
|
||||
@@ -585,6 +679,7 @@ function Show-GraphObjects
|
||||
$dgObjects.ItemsSource = $null
|
||||
}
|
||||
|
||||
|
||||
# Show/Hide buttons based on object type
|
||||
foreach($ctrl in $spSubMenu.Children)
|
||||
{
|
||||
@@ -604,6 +699,16 @@ function Show-GraphObjects
|
||||
$ctrl.Visibility = "Collapsed"
|
||||
}
|
||||
}
|
||||
|
||||
Set-GraphPagesButtonStatus
|
||||
}
|
||||
|
||||
function Set-GraphPagesButtonStatus
|
||||
{
|
||||
$global:btnLoadAllPages.Visibility = (?: ($script:nextGraphPage) "Visible" "Collapsed")
|
||||
$global:btnLoadNextPage.Visibility = (?: ($script:nextGraphPage) "Visible" "Collapsed")
|
||||
$global:btnLoadAllPages.Tag = $script:nextGraphPage
|
||||
$global:btnLoadNextPage.Tag = $script:nextGraphPage
|
||||
}
|
||||
|
||||
function Clear-GraphObjects
|
||||
@@ -620,7 +725,7 @@ function Clear-GraphObjects
|
||||
|
||||
function Get-GraphObject
|
||||
{
|
||||
param($obj, $objectType, [switch]$SkipAssignments)
|
||||
param($obj, $objectType, [switch]$SkipAssignments, [switch]$GetAPI)
|
||||
|
||||
Write-Status "Loading $((Get-GraphObjectName $obj $objectType))"
|
||||
|
||||
@@ -696,6 +801,16 @@ function Get-GraphObject
|
||||
$api = ($api + ($expand -join ","))
|
||||
}
|
||||
|
||||
if($global:Organization.Id)
|
||||
{
|
||||
$api = $api -replace "%OrganizationId%", $global:Organization.Id
|
||||
}
|
||||
|
||||
if($GetAPI -eq $true)
|
||||
{
|
||||
return $api
|
||||
}
|
||||
|
||||
$objInfo = Get-GraphObjects -Url $api -property $objectType.ViewProperties -objectType $objectType -SingleObject
|
||||
|
||||
if($objInfo -and $objectType.PostGetCommand)
|
||||
@@ -959,18 +1074,38 @@ function Show-GraphBulkExportForm
|
||||
{
|
||||
$folder = Get-GraphObjectFolder $item.ObjectType (Get-XamlProperty $script:exportForm "txtExportPath" "Text") (Get-XamlProperty $script:exportForm "chkAddObjectType" "IsChecked") (Get-XamlProperty $script:exportForm "chkAddCompanyName" "IsChecked")
|
||||
|
||||
$objects = @(Get-GraphObjects -property $item.ObjectType.ViewProperties -objectType $item.ObjectType)
|
||||
foreach($obj in $objects)
|
||||
Write-Status "Get a list of all $($item.ObjectType.Title) objects" -SkipLog -Force
|
||||
$objects = @(Get-GraphObjects -property $item.ObjectType.ViewProperties -objectType $item.ObjectType)
|
||||
|
||||
if((Get-SettingValue "UseBatchAPI") -eq $true)
|
||||
{
|
||||
$objName = Get-GraphObjectName $obj.Object $obj.ObjectType
|
||||
|
||||
if($txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
|
||||
# Use batch to get details of each object
|
||||
$batchObjects = Get-GraphBatchObjects $objects $txtNameFilter
|
||||
$i = 1
|
||||
$total = ($batchObjects | measure).Count
|
||||
foreach($batchResult in $batchObjects)
|
||||
{
|
||||
continue
|
||||
}
|
||||
$objName = Get-GraphObjectName $batchResult.Object $batchResult.ObjectType
|
||||
Write-Status "Export $($item.Title): $objName ($($i)/$($total))" -Force
|
||||
Export-GraphObject $batchResult.Object $batchResult.ObjectType $folder -IsFullObject
|
||||
$i++
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach($obj in $objects)
|
||||
{
|
||||
# Export objects one by one
|
||||
$objName = Get-GraphObjectName $obj.Object $obj.ObjectType
|
||||
|
||||
Write-Status "Export $($item.Title): $objName" -Force
|
||||
Export-GraphObject $obj.Object $item.ObjectType $folder
|
||||
if($txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
|
||||
{
|
||||
continue
|
||||
}
|
||||
|
||||
Write-Status "Export $($item.Title): $objName" -Force
|
||||
Export-GraphObject $obj.Object $item.ObjectType $folder
|
||||
}
|
||||
}
|
||||
Save-Setting "" "LastUsedFullPath" $folder
|
||||
}
|
||||
@@ -2288,13 +2423,21 @@ function Export-GraphObject
|
||||
{
|
||||
param($objToExport,
|
||||
$objectType,
|
||||
$exportFolder)
|
||||
$exportFolder,
|
||||
[switch]$IsFullObject)
|
||||
|
||||
if(-not $exportFolder) { return }
|
||||
|
||||
Write-Status "Export $((Get-GraphObjectName $objToExport $objectType))"
|
||||
|
||||
$obj = Get-GraphExportObject $objToExport $objectType
|
||||
if($IsFullObject -eq $true)
|
||||
{
|
||||
$obj = $objToExport
|
||||
}
|
||||
else
|
||||
{
|
||||
$obj = Get-GraphExportObject $objToExport $objectType
|
||||
}
|
||||
|
||||
if(-not $obj)
|
||||
{
|
||||
@@ -2315,7 +2458,7 @@ function Export-GraphObject
|
||||
}
|
||||
|
||||
$fileName = Get-GraphObjectName $obj $objectType
|
||||
if((Get-SettingValue "AddIDToExportFile") -eq $true -and $obj.Id)
|
||||
if((Get-SettingValue "AddIDToExportFile") -eq $true -and $obj.Id -and $objectType.SkipAddIDOnExport -ne $true)
|
||||
{
|
||||
$fileName = ($fileName + "_" + $obj.Id)
|
||||
}
|
||||
@@ -2335,6 +2478,83 @@ function Export-GraphObject
|
||||
}
|
||||
}
|
||||
|
||||
function Get-GraphBatchObjects
|
||||
{
|
||||
param($objects, $txtNameFilter)
|
||||
|
||||
$curBatch = 1
|
||||
$batchArr = @()
|
||||
$batchResults = @()
|
||||
$batchTotal = 0
|
||||
$objectType = $null
|
||||
foreach($obj in $objects)
|
||||
{
|
||||
$objectType = $obj.ObjectType
|
||||
$objName = Get-GraphObjectName $obj.Object $obj.ObjectType
|
||||
|
||||
if($objName -and $txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
|
||||
{
|
||||
$batchTotal++
|
||||
}
|
||||
else
|
||||
{
|
||||
$ometadata = ?? $obj.ObjectType.ODataMetadata "Full"
|
||||
$batchArr += [PSCustomObject]@{
|
||||
id = ($batchArr.Count + 1)
|
||||
method = "GET"
|
||||
url = (Get-GraphObject $obj.Object $obj.ObjectType -GetAPI)
|
||||
headers = @{"Accept"="application/json;odata.metadata=$ometadata"}
|
||||
}
|
||||
}
|
||||
|
||||
if($batchArr.Count -eq 20 -or ($batchTotal + $batchArr.Count -eq $objects.Count))
|
||||
{
|
||||
$batchObj = [PSCustomObject]@{
|
||||
requests = $batchArr
|
||||
}
|
||||
|
||||
Write-Status "Get batch $curBatch $($obj.ObjectType.Title)" -Force
|
||||
$batchTotal += $batchArr.Count
|
||||
$json = $batchObj | ConvertTo-Json -Depth 10
|
||||
$tmpResults = Invoke-GraphRequest -Url "`$batch" -Content $json -HttpMethod "POST" -Batch #-Url $api -property $obj.ObjectType.ViewProperties -objectType $obj.ObjectType -
|
||||
$curResp = 1
|
||||
foreach($batchResult in ($tmpResults.responses | Sort -Property Id))
|
||||
{
|
||||
if($batchResult.Status -ne "200" -or -not $batchResult.body)
|
||||
{
|
||||
$reqObj = $batchObj.requests | where id -eq $batchResult.Id
|
||||
Write-Log "Batch result $($batchResult.Status) for URL $($reqObj.URL). Skipping..." 2
|
||||
continue
|
||||
}
|
||||
|
||||
$batchResults += $batchResult.body
|
||||
$curResp++
|
||||
}
|
||||
|
||||
$curBatch++
|
||||
$batchArr = @()
|
||||
}
|
||||
}
|
||||
|
||||
if($objectType -and $batchResults.Count -gt 0)
|
||||
{
|
||||
$batchResultsTmp = $batchResults
|
||||
$batchResults = Add-GraphObectProperties $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
|
||||
}
|
||||
|
||||
function Get-GraphExportObject
|
||||
{
|
||||
param($obj, $objectType)
|
||||
@@ -2527,7 +2747,10 @@ function Copy-GraphObject
|
||||
{
|
||||
if((& $global:curObjectType.PreCopyCommand $exportObj $global:curObjectType $ret))
|
||||
{
|
||||
Show-GraphObjects
|
||||
if((Get-SettingValue "RefreshObjectsAfterCopy") -eq $true)
|
||||
{
|
||||
Show-GraphObjects
|
||||
}
|
||||
Write-Status ""
|
||||
return
|
||||
}
|
||||
@@ -2547,7 +2770,10 @@ function Copy-GraphObject
|
||||
{
|
||||
& $global:curObjectType.PostCopyCommand $exportObj $newObj $global:curObjectType
|
||||
}
|
||||
Show-GraphObjects
|
||||
if((Get-SettingValue "RefreshObjectsAfterCopy") -eq $true)
|
||||
{
|
||||
Show-GraphObjects
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2674,4 +2900,75 @@ function Add-GraphBulkMenu
|
||||
$menuItem.AddChild($subItem) | Out-Null
|
||||
|
||||
$mnuMain.Items.Insert(1,$menuItem) | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function Get-GraphAllEntityTypes
|
||||
{
|
||||
param($entityType, $xml, $hashTable)
|
||||
|
||||
if(-not $hashTable.ContainsKey($entityType))
|
||||
{
|
||||
$hashTable.Add($entityType, $xml.SelectSingleNode("//*[name()='EntityType' and @Name='$entityType']"))
|
||||
}
|
||||
|
||||
$nodes = $xml.SelectNodes("//*[@BaseType='graph.$entityType']")
|
||||
|
||||
foreach($node in $nodes)
|
||||
{
|
||||
if($node.Abstract -ne "true")
|
||||
{
|
||||
$hashTable.Add($node.Name, $node)
|
||||
}
|
||||
Get-GraphAllEntityTypes $node.Name $xml $hashTable
|
||||
}
|
||||
}
|
||||
|
||||
function Get-GraphEntityTypeObject
|
||||
{
|
||||
param($entityType, $xml, $skipProperties = @())
|
||||
|
||||
$props = Get-GraphEntityTypeProperties $entityType $xml
|
||||
|
||||
if(-not $props) { return }
|
||||
|
||||
$obj = [PSCustomObject]@{
|
||||
|
||||
}
|
||||
|
||||
foreach($prop in $props)
|
||||
{
|
||||
if($prop.Name -in $skipProperties) { continue }
|
||||
$obj | Add-Member -NotePropertyName $prop.Name -NotePropertyValue $null
|
||||
}
|
||||
$obj
|
||||
}
|
||||
|
||||
function Get-GraphEntityTypeProperties
|
||||
{
|
||||
param($entityType, $xml)
|
||||
|
||||
$tmpEntity = $xml.SelectSingleNode("//*[name()='EntityType' and @Name='$entityType']")
|
||||
if(-not $tmpEntity) { return }
|
||||
|
||||
$entities = @()
|
||||
$entities += $tmpEntity
|
||||
|
||||
while($tmpEntity.BaseType)
|
||||
{
|
||||
$baseType = $tmpEntity.BaseType.Split('.')[-1]
|
||||
$tmpEntity = $xml.SelectSingleNode("//*[name()='EntityType' and @Name='$baseType']")
|
||||
if($tmpEntity)
|
||||
{
|
||||
$entities += $tmpEntity
|
||||
}
|
||||
}
|
||||
$properties = @()
|
||||
[array]::Reverse($entities)
|
||||
foreach($enitiy in $entities)
|
||||
{
|
||||
$properties += $enitiy.SelectNodes("*[name()='Property']")
|
||||
}
|
||||
|
||||
$properties
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user