This commit is contained in:
Mikael Karlsson
2021-12-14 02:04:15 +11:00
parent 2b9efd5c85
commit bc48d14176
16 changed files with 1112 additions and 115 deletions

View File

@@ -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 }

View File

@@ -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)

View 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
}
}
}

View File

@@ -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)
{

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.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

View File

@@ -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

View File

@@ -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()
}
}

View File

@@ -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()
}
}

View File

@@ -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)
{

View File

@@ -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
}