> For the complete documentation index, see [llms.txt](https://docs.realmjoin.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.realmjoin.com/pt/automacao/runbooks/runbook-customization.md).

# Personalização de Runbooks

## Visão geral

A implementação do runbook RealmJoin oferece capacidades de personalização ao autor de um runbook ou ao administrador de um ambiente, para que possam:

* Hospedar parâmetros e modelos específicos do cliente/Tenant
* Oferecer elementos de UI como seletores de utilizador ou seleções em menu suspenso
* Apresentar explicações legíveis por humanos dos parâmetros
* Ocultar elementos de UI desnecessários

<figure><img src="/files/fc10f116696800198ba3d0f0bf0012c61f38abbc" alt=""><figcaption></figcaption></figure>

As personalizações podem ser incluídas no próprio runbook e/ou armazenadas na instância do RealmJoin Portal do cliente. Por predefinição, tentaremos oferecer predefinições sensatas nos runbooks oferecidos em [GitHub](https://github.com/realmjoin/realmjoin-runbooks).

Alguns runbooks virão com exemplos de como configurar modelos específicos do cliente, como especificar localizações de Office para a integração de utilizadores.

### Formato

A personalização pode ser definida (por ordem decrescente de prioridade)

* Bloco de JSON em [definições do RealmJoin Portal](https://portal.realmjoin.com/settings/runbooks-customizations), substituindo o comportamento predefinido do runbook
* Bloco de JSON no cabeçalho de um runbook

Adicionalmente (com a menor prioridade)

* por parâmetro no cabeçalho do runbook
* por parâmetro no bloco param do runbook (usando o Módulo Auxiliar RJRb)

Algumas funcionalidades (como modelos) só estão disponíveis em formato JSON. Algumas funcionalidades (como criar um seletor de utilizador) só estão disponíveis ao especificar um tipo de dados no bloco param. Pode combinar vários tipos de personalizações para obter os melhores resultados.

## Bloco de Parâmetros do Runbook

O RealmJoin Portal analisa o bloco param do PowerShell de um runbook para determinar quais campos de entrada renderizar. Sempre que possível, também validará as entradas de acordo com o tipo .NET fornecido para uma variável.

Os seguintes tipos de dados são atualmente reconhecidos:

* `[bool]`, `[boolean]` - apresentará um alternador binário
* `[string]` - apresentará uma caixa de texto para escrever qualquer entrada alfanumérica
* `[int]` - apresentará uma caixa de texto, permitindo apenas entradas numéricas
* `[DateTime]`, `[DateTimeOffset]` - Apresentará um seletor de data/hora

Pode aplicar modificadores padrão do PowerShell aos parâmetros. O RealmJoin Portal, em particular, compreenderá se especificar `[Parameter(Mandatory = $true)]` para indicar um parâmetro obrigatório e impor que estes parâmetros sejam preenchidos.

Sempre que possível, o RealmJoin Portal também lerá e apresentará valores predefinidos dados na UI.

Tenha em atenção que os valores predefinidos do runbook podem ser substituídos por personalizações. Além disso, os parâmetros podem ser completamente ocultados por personalizações.

### Personalização de Parâmetros

Para poder personalizar parâmetros, certifique-se de incluir o Módulo PS Auxiliar de Runbook do RealmJoin no seu runbook:

`#Requires -Modules @{ModuleName = "RealmJoin.RunbookHelper"; ModuleVersion = "0.6.0" }`

Pode então incluir `[ValidateScript( { Use-RJInterface ... } )]` instruções nas definições de parâmetros. Por exemplo, o seguinte criará um seletor de utilizador, permitindo escolher um utilizador do Entra ID e passará o respetivo id de objeto como string para o runbook.

```powershell
param(
    [ValidateScript( { Use-RJInterface -DisplayName "Atribuir dispositivo a este utilizador (opcional)" -Type Graph -Entity User } )]
    [string] $AssignedUserId = ""
)
```

Vamos analisar isto passo a passo. `[ValidateScript...]` é um modificador para o próximo parâmetro definido no bloco param. Neste caso a variável `$AssignedUserId`.

`Use-RJInterface` faz parte do nosso [RealmJoin Runbook Helper](https://github.com/realmjoin/RealmJoin.RunbookHelper) Módulo PowerShell. Permite-lhe especificar que tipo de entrada espera usando `-Type` e `-Entity`, se isso ainda não estiver totalmente definido pelo tipo de variável.

`-DisplayName` permite-lhe passar um aviso / descrição legível por humanos para este parâmetro para o RealmJoin Portal.

#### Recursos Graph

No exemplo acima, a origem da informação é o MS Graph, conforme descrito por `-Type Graph`. Para o MS Graph, use `-Entity` para especificar que tipo de recurso está a esperar. As entidades disponíveis são `Utilizador`, `Grupo`, `Dispositivo`. Isto produzirá um seletor para utilizadores, grupos ou dispositivos no Entra ID fornecido.

O seletor inclui uma pesquisa rápida, para localizar facilmente o recurso necessário.

![Exemplo do Seletor](/files/fd8e7a08510ba33d9ad8bc27ed96b9401be94849)

Atualmente, não é possível multisseleção usando um seletor.

Por predefinição, um seletor de MS Graph devolverá o ID do objeto. Se precisar, por exemplo, do nome principal do utilizador em vez disso, certifique-se de incluir "name" como sufixo no nome da sua variável. Portanto, basicamente, para obter o id de um utilizador, nomeie o parâmetro `$userid`. Se quiser um UPN, nomeie-o `$username`.

#### Filtragem Graph

Se estiver a usar um seletor baseado em MS Graph, também pode especificar `-Filter` e usar um [Filtro ODATA](https://docs.microsoft.com/en-us/graph/query-parameters?context=graph%2Fapi%2F1.0\&view=graph-rest-1.0#filter-parameter) para limitar os objetos oferecidos no seletor.

O exemplo seguinte listará apenas grupos do Entra ID que comecem com "LIC\_".

```powershell
param(
    [Parameter(Mandatory = $true)]
    [ValidateScript( { Use-RJInterface -Type Graph -Entity Group -Filter "startswith(DisplayName, 'LIC_')" -DisplayName "Grupo de licenças" } )]
    [String] $GroupID_License
)
```

Pode preparar filtros e reutilizá-los em vários scripts usando o [arquivo de dados central](#graph-filters). Neste caso, basta referenciar o filtro pelo nome usando `-Filter "ref:LicenseGroup"`, onde `ref:` indica procurar um filtro armazenado.

```powershell
param(
    [Parameter(Mandatory = $true)]
    [ValidateScript( { Use-RJInterface -Type Graph -Entity Group -Filter "ref:LicenseGroup" } )]
    [String] $GroupID_License
)
```

Este exemplo específico `ref:LicenseGroup` está disponível por predefinição, sem necessidade de configuração adicional.

![Filtro ODATA](/files/af67c2f470082ec3fe983dfbd473ab0da74f6b0f)

## Cabeçalho do Runbook

O Portal pode analisar a [ajuda baseada em comentários](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_comment_based_help?view=powershell-5.1) de um runbook, se existir.

Aqui está um exemplo:

```powershell
<#
  .SYNOPSIS
  (Des-)Atribuir uma licença a um utilizador através da filiação em grupo.

  .DESCRIPTION
  (Des-)Atribuir uma licença a um utilizador através da filiação em grupo. Descrição mais detalhada...

  .PARAMETER DefaultGroups
  Lista de grupos separada por vírgulas a atribuir. por exemplo "DL Sales,LIC Internal Product"

  .NOTES
  Permissões:
  MS Graph (API):
  - User.Read.All
  - GroupMember.ReadWrite.All 
  - Group.ReadWrite.All

  .INPUTS
  RunbookCustomization: {
        "Parameters": {
            "UserName": {
                "Hide": true
            },
            "Remove": {
                "DisplayName": "Atribuir ou Remover Licença",
                "SelectSimple": {
                    "Atribuir Licença ao Utilizador": false,
                    "Remover Licença do Utilizador": true
                }
            }
        }
    }
#>
```

`.SYNOPSIS` - Dê uma descrição muito breve da função do seu runbook. Isto será apresentado na lista de runbooks disponíveis.

`.DESCRIPTION` - Dê uma descrição da função do seu runbook. Pode conter um pouco mais de detalhe, uma vez que isto será apresentado dentro do diálogo de execução/parâmetros dos runbooks.

`.PARAMETER` - Precisa de ser seguido pelo nome de um parâmetro. Permite-lhe dar uma explicação detalhada da entrada esperada para o parâmetro em questão.

`.INPUTS` - Pode conter um bloco de personalização de runbook baseado em JSON.

`.NOTES` - Não é analisado / renderizado. Use este espaço para escrever quais permissões e requisitos existem para o seu runbook.

`.EXAMPLE` - Não é analisado / renderizado. Pode conter um exemplo de uma Personalização baseada em JSON a usar no RealmJoin Datastore no seu Tenant. Estes podem ser exemplos de como criar modelos, por exemplo, para diferentes fluxos de trabalho ou classes de utilizadores.

## Personalização Baseada em JSON

### Arquivo de Dados Central

Cada Tenant do Azure pode alojar um arquivo de dados "Runbook Customizations", encontrado em <https://portal.realmjoin.com/settings/runbooks-customizations> .

O formato é JSON com comentários, permitindo vírgulas finais. Atualmente, existem três secções relevantes, `Configurações`, `Modelos`, `Runbooks`.

```json
{
    "Settings": {
    },
    "Templates": {
    },
    "Runbooks": {
    }
}
```

### Secção de Runbooks

`Runbooks` é analisada pelo portal ao iniciar um runbook. Se existir uma secção com o nome do Azure Automation Runbook atual, o seu conteúdo será usado para personalizar o frontend apresentado ao utilizador.

Suponha o seguinte runbook de demonstração simples, chamado `rjgit-device_demo-runbook-customizing`.

```powershell
<#
  .SYNOPSIS
  Demonstrar Personalização de Runbook

  .DESCRIPTION
  Demonstrar Personalização de Runbook, como dropdown/seleção
#>

#Requires -Modules @{ModuleName = "RealmJoin.RunbookHelper"; ModuleVersion = "0.6.0" }

param(
    [string] $DeviceId,
    [bool] $ExtraWorkflow = $true,
    [int] $ExtraWorkflowTime = 15
)

"## A fazer coisas ao Device '$DeviceID'"

# Fluxo de trabalho complicado altamente opcional
if ($ExtraWorkflow) {
    "## A executar Meditação..."
    Start-Sleep -Seconds $ExtraWorkflowTime
}
```

Se não for personalizado, será apresentado assim no frontend:

![Demo - antes](/files/1bbf7a0209bf21af95d610cb26d298976c221f5c)

Pensamentos:

* Como este runbook é iniciado a partir do contexto de um dispositivo no portal, o `$DeviceId` é informação redundante para um utilizador. Eu já sei em que dispositivo estou a trabalhar.
* O que acontece se eu ativar ou desativar o "Extra Workflow"? Preciso de pensar no "Extra Workflow Time" se desativar o "Extra Workflow"?

Vamos melhorar isso. O seguinte JSON de exemplo no arquivo de dados central modificará a UI para o runbook.

```json
{
    "Runbooks": {
        "rjgit-device_demo-runbook-customizing": {
            "ParameterList": [
                {
                    "Name": "DeviceId",
                    "Hide": true
                }, 
                {
                    "Name": "ExtraWorkflow",
                    "Hide": true
                },
                {
                    "Name": "ExtraWorkflowTime",
                    "DisplayName": "Quanto tempo para meditar?",
                },
                {
                    "DisplayName": "Executar Fluxo de Trabalho Extra",
                    "DisplayBefore": "ExtraWorkflowTime",
                    "Select": {
                        "Options": [
                            {
                                "Display": "Executar Meditação (opcional)",
                                "Customization": {
                                    "Default": {
                                        "ExtraWorkflow": true
                                    }
                                }
                            },
                            {
                                "Display": "Ignorar a Atenção ao Dispositivo",
                                "Customization": {
                                    "Default": {
                                        "ExtraWorkflow": false
                                    },
                                    "Hide": [
                                        "ExtraWorkflowTime"
                                    ]
                                }
                            }
                        ],
                        
                    },
                    "Default": "Ignorar a Atenção ao Dispositivo"
                }
            ]
        }
    }
}
```

Pode usar a mesma notação / funcionalidades no seu [cabeçalho do runbook](#runbook-header).

#### ParameterList

Cada parâmetro tem a sua própria secção em `ParameterList`. [Modificadores](#modifiers) permitem alterar o comportamento desse parâmetro.

O resultado será assim:

![Demo - após ocultado](/files/13056fe34a28a7dd86d5a404c992058d0fcfbf5a)

Escolher o fluxo de trabalho adicional apresentará (mostrará novamente) mais parâmetros:

![Demo - após mostrado novamente](/files/0fade93442f6dcac041b2e83099d5de301ceabd5)

Isto mostra menos desordem em comparação com antes de aplicar a personalização. Ao mesmo tempo, mais informação sobre as alternativas de "Extra Workflow" está disponível para o utilizador. Além disso, um utilizador agora só se preocupará com "Extra Workflow Time" se isso for relevante.

Alterar a visibilidade desse campo foi feito usando um `"Customization"` bloco dentro de uma das `"Select"` opções. Atualmente, pode ter no máximo um bloco desse tipo ativo de cada vez. `"Customization"` Como pode ver, o parâmetro

está completamente oculto. Isto é feito definindo o `$DeviceId` para este parâmetro. `"Hide": true` Os parâmetros podem ter um

. Oferecemos um `DisplayName`mais legível para humanos `DisplayName` para substituir `$ExtraWorkflowTime` na UI. Veja outros [modificadores](#modifiers) para mais informações.

Pode inserir parâmetros "sem nome" (faltando a `Nome` instrução) como a secção "Executar Fluxo de Trabalho Extra", se quiser oferecer elementos de UI sem devolver diretamente um valor. Isto é normalmente usado apenas em conjunto com `Selecione`.

#### Selecione

Usámos `Selecione`, para apresentar uma lista de `Opções` num dropdown. Cada opção pode `Exibir` texto, ou acionar uma `Personalização`, como definir `Ocultar` ou um `Padrão` valor noutros parâmetros. No nosso exemplo, usámo-lo para (mostrar/ocultar) `$ExtraWorkflowTime` e substituir `$ExtraWorkflow`o respetivo valor.

`$ExtraWorkflowTime` é assim apenas mostrado quando relevante e o interruptor binário `$ExtraWorkflow` está agora substituído por alternativas significativas da perspetiva de um utilizador.

No caso de um `Selecione` para um parâmetro nomeado, cada opção deve ter um `"ParameterValue": "..."` para passar para o runbook. Pode colocar um `"ShowValue: false"` dentro do `Selecione` bloco para mostrar apenas o dropdown e não um campo para o valor do parâmetro resultante.

Exemplo de parâmetro nomeado:

```json
{
    "Name": "ExtraWorkflow",
    "DefaultValue": true,
    "DisplayName": "Executar Fluxo de Trabalho Extra",
    "DisplayBefore": "ExtraWorkflowTime",
    "Select": {
        "Options": [
            {
                "Display": "Executar Meditação (opcional)",
                "ParameterValue": true
            },
            {
                "Display": "Ignorar a Atenção ao Dispositivo",
                "ParameterValue": false,
                "Customization": {
                    "Hide": [
                        "ExtraWorkflowTime"
                    ]
                }
            }
        ],
        "ShowValue": false
    }
}
```

O `Padrão` / `DefaultValue` instrução no parâmetro também especifica o estado inicial do dropdown. No caso de um parâmetro sem nome, use o `DisplayName` do valor desejado, caso contrário dê um valor de retorno predefinido, como "true" ou "false" ou alguma string.

#### Parâmetros

Se só tiver parâmetros nomeados, pode usar o formato ligeiramente mais curto `Parâmetros` em vez de `ParameterList`.

Para um exemplo, veja SelectSimple

#### SelectSimple

Se o poder total de um `Selecione` não for necessário e apenas quiser oferecer uma lista de valores possíveis num dropdown (sem aplicar personalização adicional), pode usar `SelectSimple`.

`SelectSimple` só pode ser usado para parâmetros nomeados.

Exemplo:

```json
{
    "Runbooks": {
        "rjgit-device_demo-runbook-customizing": {
            "Parameters": {
                "DeviceId": {
                    "Hide": true
                }, 
                "ExtraWorkflow": {
                    "Name": "ExtraWorkflow",
                    "DisplayName": "Executar Fluxo de Trabalho Extra",
                    "Default": false,
                    "SelectSimple": {
                        "Executar Meditação (opcional)": true,
                        "Ignorar a Atenção ao Dispositivo": false
                    }
                },
                "ExtraWorkflowTime": {
                    "DisplayName": "Quanto tempo para meditar?"
                }
            }
        }
    }
}
```

A maior diferença (para além de ser muito mais curta) em relação ao nosso exemplo anterior é que `$ExtraWorkflowTime` está sempre visível.

#### Modificadores

Cada parâmetro pode ter um ou mais dos seguintes modificadores:

* `"DisplayName": "texto"` - Exibir "texto" como nome do parâmetro na UI
* `"Hide": true / false` - Ocultar este parâmetro
* `"Mandatory": true / false` - Exigir que este parâmetro seja preenchido
* `"ReadOnly": true / false` - Proteger este parâmetro de ser alterado do seu valor predefinido
* `"DefaultValue": "..."` - Definir um valor predefinido para este parâmetro. (Também pode usar `Padrão` em vez disso.)
* `"GraphFilter": "startswith(DisplayName, 'LIC_')"` - ver [Filtragem Graph](#graph-filtering)
* `"AllowEdit": true / false` - Proteger este parâmetro de edição manual. (combine isto com modelos)

### Configurações

`Configurações` permite-lhe armazenar dados de configuração como nomes de Azure Storage Account num local central, mantendo-os ainda separados dos seus runbooks.

Pode aceder a valores individuais de um bloco param de runbook usando `Use-RJInterface`.

Vamos analisar este bloco param de exemplo de um runbook:

```powershell
param(
    [ValidateScript( { Use-RJInterface -Type Setting -Attribute "CaPoliciesExport.Container" } )]
    [string] $ContainerName,
    [ValidateScript( { Use-RJInterface -Type Setting -Attribute "CaPoliciesExport.ResourceGroup" } )]
    [string] $ResourceGroupName,
    [ValidateScript( { Use-RJInterface -Type Setting -Attribute "CaPoliciesExport.StorageAccount.Name" } )]
    [string] $StorageAccountName,
    [ValidateScript( { Use-RJInterface -Type Setting -Attribute "CaPoliciesExport.StorageAccount.Location" } )]
    [string] $StorageAccountLocation,
    [ValidateScript( { Use-RJInterface -Type Setting -Attribute "CaPoliciesExport.StorageAccount.Sku" } )]
    [string] $StorageAccountSku
)
```

O Portal tentará preencher previamente cada parâmetro com valores do arquivo de dados central - se presentes. Isto também funciona se o parâmetro tiver sido ocultado na UI.

Um possível JSON no arquivo de dados para este runbook seria:

```json
{
    "Settings": {
        "CaPoliciesExport": {
            "ResourceGroup": "rj-runbooks-01",
            "StorageAccount": {
                "Name": "rjrbexports01",
                "Location": "West Europe",
                "Sku": "Standard_LRS"
            }
        }
    }
}
```

O elemento em falta `Container` simplesmente não será preenchido previamente na UI.

### Modelos

`Modelos` use referências JSON para incorporar dados - por exemplo, uma longa lista de localizações de Office - quando usar uma `Selecione` instrução.

Isto permite manter uma personalização neutra/reutilizável/separada dos dados reais.

Vamos tomar o exemplo da integração de novos utilizadores. Pode ter várias opções fornecidas para departamentos ou localizações de Office, em que atribuir uma localização de Office também exige uma determinada morada, país, estado etc.

O seguinte exemplo de uma personalização de runbook usa a secção `$ref` dentro do `Runbooks` para referenciar/importar uma subárvore da secção `Modelos` . Procure o `$id`/`$values` palavras-chave. Tenha em atenção que `$id`/`$values` têm de ser definidas antes de as referenciar usando `$ref`. É por isso que `Modelos` é definido antes de `Runbooks` neste exemplo.

Neste exemplo, dizemos ao portal para obter a subárvore com o `$id` chamado `LocationOptions` e incluir os seus `$values`, substituindo a `$ref` instrução. Assim, o portal renderizará um `Selecione` como descrito na `Runbooks` secção, mas incluirá as opções reais de `Modelos`.

Um modelo pode conter qualquer instrução suportada na localização de referência. Neste exemplo, usamos uma `Personalização` instrução para modificar outros parâmetros como `Morada`.

Assim, podemos ter uma personalização específica do runbook em `Runbooks` reutilizável em vários ambientes, mantendo os dados reais separados.

```json
{
    "Templates": {
        "Options": [
            {
                "$id": "LocationOptions",
                "$values": [
                    {
                        "Display": "DE-OF",
                        "Customization": {
                            "Default": {
                                "StreetAddress": "Kaiserstraße 39",
                                "PostalCode": "63065",
                                "City": "Offenbach",
                                "Country": "Alemanha"
                            }
                        }
                    },
                    {
                        "Display": "DE-DEG",
                        "Customization": {
                            "Default": {
                                "StreetAddress": "Lateinschulgassse 24-26",
                                "PostalCode": "94469",
                                "City": "Deggendorf",
                                "Country": "Alemanha"
                            }
                        }
                    },
                    {
                        "Display": "DE-HH",
                        "Customization": {
                            "Default": {
                                "StreetAddress": "Hans-Henny-Jahnn-Weg 53",
                                "PostalCode": "22085",
                                "City": "Hamburg",
                                "Country": "Alemanha"
                            }
                        }
                    },
                    {
                        "Display": "FI-HS",
                        "Customization": {
                            "Default": {
                                "StreetAddress": "Somewhere 42",
                                "PostalCode": "12345",
                                "City": "Helsínquia",
                                "Country": "Finlândia"
                            }
                        }
                    }
                ]
            },
            {
                "$id": "CompanyOptions",
                "$values": [
                    {
                        "Id": "gkg",
                        "Display": "glueckkanja",
                        "Value": "glueckkanja AG"
                    },
                    {
                        "Id": "pp",
                        "Display": "PRIMEPULSE",
                        "Value": "PRIMEPULSE SE"
                    }
                ]
            }
        ]
    },
    "Runbooks": {
        "rjgit-org_general_add-user": {
            "ParameterList": [
                {
                    "DisplayName": "Localização do Office",
                    "DisplayAfter": "CompanyName",
                    "Select": {
                        "Options": {
                            "$ref": "LocationOptions"
                        }
                    }
                },
                {
                    "Name": "CompanyName",
                    "Select": {
                        "Options": {
                            "$ref": "CompanyOptions"
                        },
                        "AllowEdit": false
                    }
                }
            ],
            "ReadOnly": [
                "StreetAddress",
                "PostalCode",
                "City",
                "Country"
            ]
        }
    }
}
```

Isto criará a seguinte IU:

![Demonstração - ref-location](/files/717595c867fde31c038d5dfdaae7050099a19769)

![Demonstração - ref-address](/files/e4bdfb7b2cfc908c189034499e2393bf9c868b7d)

### Filtros de Graph

Pode preparar [Filtros de Graph ODATA](https://docs.microsoft.com/en-us/graph/query-parameters?context=graph%2Fapi%2F1.0\&view=graph-rest-1.0#filter-parameter) para serem usados em vários runbooks. Armazene-os numa secção chamada `GraphFilters`.

O exemplo seguinte filtra por um determinado prefixo no `DisplayName` de um grupo, para mostrar apenas grupos relacionados com licenciamento num seletor de grupos.

```json
"GraphFilters": {
    "LicenseGroup": "startswith(DisplayName, 'LIC_')" // também incluído no código RJ como predefinição
  }
```

Veja [Filtragem do Graph](#graph-filtering) sobre como usar isto a partir de um runbook.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.realmjoin.com/pt/automacao/runbooks/runbook-customization.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
