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("") $tableText.AppendLine("") $columnHeaders = "|" $columnChars = "|" $columnCount = 0 foreach($prop in $properties) { $tableText.AppendLine("") $columnCount++ $columnHeaders += ((Invoke-DocTranslateColumnHeader ($prop.Split(".")[-1])) + "|") $columnChars += "----|" } $tableText.AppendLine("") #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("") $tableText.AppendLine("") $tableText.AppendLine("") #$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("") $tableText.AppendLine("") $tableText.AppendLine("") #$columnSubCategory = "|***" + (Set-MDText $itemObj.SubCategory) + "***|" #Add-MDText $columnSubCategory $curSubCategory = $itemObj.SubCategory } #$columnData = "|" try { $tableText.AppendLine("") 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("") #$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("") } #Add-MDText $columnData } $tableText.AppendLine("
$($prop.Split(".")[-1])
`n`n**$((Set-MDText $itemObj.Category))**`n`n
`n`n***$((Set-MDText $itemObj.SubCategory))***`n`n
$((Set-MDText "$($tmpObj.$propName)" -CodeBlock))
") 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", "
") $text = $text.Replace("`n", "
") $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("$text") } 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 } } }