mirror of
https://github.com/Micke-K/IntuneManagement.git
synced 2026-09-28 19:05:38 +02:00
IntuneManagement 4.0.0-beta1
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
# Avalonia parallel of UI/WPF/ClassExtensions/IntuneScriptClassUIExtension.ps1.
|
||||
# Same ScriptMethod names (AddUIExportExtensions / AddUIDetailsExtension) so
|
||||
# the Add-IntuneManagerExportUIExtensions wrapper from
|
||||
# Extensions/IntuneManagerExtensionHooks.ps1 invokes them transparently.
|
||||
#
|
||||
# Two cross-cutting concerns:
|
||||
#
|
||||
# * [[scriptmethod-loses-module-scope]] — Add-Member ScriptMethod scriptblocks
|
||||
# execute outside the defining module's session state and can't see
|
||||
# module-scoped functions by name. Every helper used inside the SBs is
|
||||
# captured up front via `${function:X}` and invoked through `&`. The outer
|
||||
# SB calls .GetNewClosure() so the captures travel with it; nested OnClick
|
||||
# handlers do the same so their inner-scope copies survive too.
|
||||
#
|
||||
# * The WPF original used [System.Windows.Forms.SaveFileDialog] (R13 forbids
|
||||
# WinForms in UI/Avalonia) and built [System.Windows.Controls.*] objects
|
||||
# directly. Both are routed through the Avalonia helpers in
|
||||
# IntuneManagerExtensionHooks.ps1 (Add-AvaloniaExportPropertyCheckbox,
|
||||
# Add-AvaloniaDetailsButton, Show-AvaloniaScriptEditor) which use
|
||||
# [Avalonia.Controls.*] + Host::SaveFilePicker.
|
||||
|
||||
##############################################
|
||||
# Helpers (file-private functions invoked from inside the ScriptMethods).
|
||||
# Defined first so the `${function:X}` captures below see live refs before
|
||||
# the SBs build their closures.
|
||||
##############################################
|
||||
|
||||
function Invoke-DownloadScriptAvalonia
|
||||
{
|
||||
param($ScriptPolicy)
|
||||
|
||||
if (-not $ScriptPolicy) { return }
|
||||
if ($ScriptPolicy.IsFullObject -eq $false) { [void]$ScriptPolicy.Get() }
|
||||
if (-not $ScriptPolicy.JsonObject.scriptContent) { return }
|
||||
|
||||
Write-Status ""
|
||||
|
||||
$picked = (Get-AvaloniaHost)::SaveFilePicker(
|
||||
$script:Window,
|
||||
'Save script',
|
||||
[string]$ScriptPolicy.JsonObject.FileName,
|
||||
$null,
|
||||
'All files',
|
||||
'*.*')
|
||||
if (-not $picked) { return }
|
||||
|
||||
Save-IntuneScriptContent $ScriptPolicy $picked | Out-Null
|
||||
}
|
||||
|
||||
function Invoke-EditScriptAvalonia
|
||||
{
|
||||
param($ScriptPolicy)
|
||||
|
||||
if (-not $ScriptPolicy) { return }
|
||||
if ($ScriptPolicy.IsFullObject -eq $false) { [void]$ScriptPolicy.Get() }
|
||||
if (-not $ScriptPolicy.JsonObject.scriptContent) { return }
|
||||
|
||||
$scriptText = [System.Text.Encoding]::UTF8.GetString(
|
||||
[System.Convert]::FromBase64String($ScriptPolicy.JsonObject.scriptContent))
|
||||
|
||||
Show-AvaloniaScriptEditor `
|
||||
-Title "Edit: $($ScriptPolicy.JsonObject.displayName)" `
|
||||
-InitialText $scriptText `
|
||||
-OnSave {
|
||||
param([string]$NewText)
|
||||
|
||||
$pre = [System.Text.Encoding]::UTF8.GetPreamble()
|
||||
$utfBom = [System.Text.Encoding]::UTF8.GetString($pre)
|
||||
if ($NewText.StartsWith($utfBom)) { $NewText = $NewText.Remove(0, $utfBom.Length) }
|
||||
$bytes = [System.Text.Encoding]::UTF8.GetBytes($NewText)
|
||||
$encodedText = [Convert]::ToBase64String($bytes)
|
||||
|
||||
if ($ScriptPolicy.JsonObject.scriptContent -eq $encodedText) { return }
|
||||
|
||||
$confirm = $script:UIProvider.ShowMessageBox("Are you sure you want to update the script?`n`nObject:`n$($ScriptPolicy.Name)", "Update script?", "YesNo", "Warning")
|
||||
if ($confirm -ne "Yes") { return }
|
||||
|
||||
Write-Status "Update $($ScriptPolicy.Name)"
|
||||
$cloned = $ScriptPolicy.Clone()
|
||||
$cloned.JsonObject.scriptContent = $encodedText
|
||||
Remove-GraphPropertiesForImport $cloned $cloned.JsonObject
|
||||
foreach ($prop in $ScriptPolicy.PolicyType.PropertiesToRemoveForUpdate) {
|
||||
Remove-Property $cloned.JsonObject $prop
|
||||
}
|
||||
Remove-Property $cloned.JsonObject "Assignments"
|
||||
Remove-Property $cloned.JsonObject "isAssigned"
|
||||
|
||||
if ($ScriptPolicy.Set($null, $cloned.JsonString, "PATCH", $null)) {
|
||||
Write-Log "Script saved successfully"
|
||||
} else {
|
||||
Write-Log "Failed to save script" 3
|
||||
}
|
||||
Write-Status ""
|
||||
}.GetNewClosure()
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Captures (see [[scriptmethod-loses-module-scope]])
|
||||
##############################################
|
||||
|
||||
$sbAddCheckbox = ${function:Add-AvaloniaExportPropertyCheckbox}
|
||||
$sbAddDetailsBtn = ${function:Add-AvaloniaDetailsButton}
|
||||
$sbSetCache = ${function:Set-CacheObject}
|
||||
$sbWriteLogError = ${function:Write-LogError}
|
||||
$sbInvokeDownloadScript = ${function:Invoke-DownloadScriptAvalonia}
|
||||
$sbInvokeEditScript = ${function:Invoke-EditScriptAvalonia}
|
||||
|
||||
##############################################
|
||||
# ScriptBlocks (built AFTER captures are in scope so GetNewClosure picks them up)
|
||||
##############################################
|
||||
|
||||
$SBAddScriptUIExportExtension = {
|
||||
param($Form)
|
||||
|
||||
if (-not $Form) { return }
|
||||
|
||||
$chk = & $sbAddCheckbox -Form $Form `
|
||||
-CheckboxName 'chkExportScript' `
|
||||
-LabelText 'Export script' `
|
||||
-ToolTip 'Export the script associated with selected profiles' `
|
||||
-InitialChecked $true
|
||||
if (-not $chk) { return }
|
||||
|
||||
& $sbSetCache "ExportScripts" $chk.IsChecked
|
||||
|
||||
$chk.add_IsCheckedChanged({
|
||||
param($s, $e)
|
||||
& $sbSetCache "ExportScripts" $s.IsChecked
|
||||
}.GetNewClosure())
|
||||
}.GetNewClosure()
|
||||
|
||||
$SBAddScriptUIDetailsExtension = {
|
||||
param($Form)
|
||||
|
||||
if (-not $Form) { return }
|
||||
|
||||
$onDownload = {
|
||||
param($s, $e)
|
||||
$row = $script:dgIntuneManagerObjects.SelectedItem
|
||||
$sel = if ($row) { $row.Source } else { $null }
|
||||
if (-not $sel) { return }
|
||||
try { & $sbInvokeDownloadScript $sel }
|
||||
catch { & $sbWriteLogError "Download script failed" $_.Exception }
|
||||
}.GetNewClosure()
|
||||
|
||||
$onEdit = {
|
||||
param($s, $e)
|
||||
$row = $script:dgIntuneManagerObjects.SelectedItem
|
||||
$sel = if ($row) { $row.Source } else { $null }
|
||||
if (-not $sel) { return }
|
||||
try { & $sbInvokeEditScript $sel }
|
||||
catch { & $sbWriteLogError "Edit script failed" $_.Exception }
|
||||
}.GetNewClosure()
|
||||
|
||||
& $sbAddDetailsBtn -Form $Form -Name 'btnDownload' -Content 'Download' `
|
||||
-InsertIndex 0 -OnClick $onDownload | Out-Null
|
||||
& $sbAddDetailsBtn -Form $Form -Name 'btnEdit' -Content 'Edit' `
|
||||
-InsertIndex 1 -OnClick $onEdit | Out-Null
|
||||
}.GetNewClosure()
|
||||
|
||||
##############################################
|
||||
# Init
|
||||
##############################################
|
||||
|
||||
function Invoke-InitializeScriptUIExtensions
|
||||
{
|
||||
$typeClasses = @()
|
||||
|
||||
Get-SubClasses "ScriptTypeBase" | ForEach-Object {
|
||||
try {
|
||||
$tmpClass = Get-SingletonObject $_.Name
|
||||
if ($null -ne $tmpClass.PolicyGroup) {
|
||||
$typeClasses += $tmpClass
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
foreach ($typeClass in $typeClasses) {
|
||||
Add-ObjectMethod $typeClass "AddUIExportExtensions" $SBAddScriptUIExportExtension
|
||||
Add-ObjectMethod $typeClass "AddUIDetailsExtension" $SBAddScriptUIDetailsExtension
|
||||
}
|
||||
}
|
||||
|
||||
Invoke-InitializeScriptUIExtensions
|
||||
Reference in New Issue
Block a user