Cómo crear tareas del planificador con PowerShell
Aprender a crear y actualizar tareas en un plan planificador usando PowerShell
Una de las formas más útiles de realizar un seguimiento de los cambios realizados por Microsoft en las cargas de trabajo de Microsoft 365 es sincronizar las notificaciones del centro de mensajes desde el centro de administración de Microsoft 365 con Planner. Esta capacidad de sincronizar publicaciones de actualización con Planner apareció por primera vez en 2020 y la he estado usando desde entonces. Aunque la sincronización es fácil de instalar y configurar y, en general, funciona bien, decidí que sería un buen desafío de aprendizaje replicar la sincronización usando PowerShell y cmdlets del SDK de Microsoft Graph PowerShell.
Este artículo describe mi experiencia al usar Graph SDK para sincronizar las notificaciones publicadas en el centro de administración de Microsoft 365 para que se conviertan en tareas en un plan de Planner. Los conceptos y técnicas explorados aquí se pueden utilizar para actualizar cualquier plan de Planner. Puede ejecutar el script en una sesión interactiva de Graph SDK si su cuenta es miembro del grupo propietario del plan de destino. De lo contrario, tendrá que utilizar los permisos de la aplicación con una aplicación Entra ID registrada y autenticarse con un secreto de cliente o un certificado X.509.
Sincronización 101
La idea básica es:
- Definir un plan objetivo.
- Encuentra nuevos elementos de anuncios.
- Cree nuevas tareas para los elementos de anuncio en el plan de destino.
Quería darle a mi versión de la sincronización algunos detalles que la versión estándar no admite, así que agregué:
- Asignación automática de tareas a miembros designados del equipo.
- Actualización automática de tareas con etiquetas (Planner admite hasta 25 etiquetas diferentes por plan).
- Agregue una fecha objetivo para cada tarea.
Veamos cómo se desarrollan estos pasos.
Definición de un plan objetivo
Para simplificar las cosas, el guión define dos variables para el grupo objetivo y el plan. El grupo objetivo (propietario del plan) está definido por su identificador de grupo. El plan de destino se define por su nombre para mostrar:
$GroupId = '78b47932-b35f-4b26-94c2-3228cb234b07'
$TargetPlanName = 'Admin Task Assignment'
Encontrar nuevas notificaciones del Centro de mensajes de Microsoft 365
Las notificaciones del centro de mensajes se denominan mensajes de anuncio de servicio y forman parte de la API Graph de comunicaciones y estado del servicio. El cmdlet del SDK para recuperar mensajes de anuncios de servicio es Get-MgServiceAnnouncementMessage. Otro ejemplo del uso de este cmdlet es averiguar cuántos anuncios realizados por Microsoft terminan retrasándose por una razón u otra.
Este código muestra cómo el script recupera anuncios de servicio y luego filtra los elementos para encontrar aquellos con una fecha de inicio mayor que la fecha de verificación. Lógicamente, para asegurarnos de que la sincronización funciona como debería, la fecha de verificación debe ser la fecha de la última ejecución.
[array]$AllAnnouncements = Get-MgServiceAnnouncementMessage -Sort 'LastmodifiedDateTime desc' -All
[array]$AnnouncementsForPeriod = $AllAnnouncements | Where-Object {$_.StartDateTime -as [datetime] -gt $CheckDate}
If ($AnnouncementsForPeriod.Count -eq 0) {
Write-Host ("No new message center posts found since {0} - exiting" -f $CheckDate)
Break
} Else {
Write-Host ("{0} message center posts found to process..." -f $AnnouncementsForPeriod.count)
}
El siguiente paso del script crea o actualiza tareas. Volveremos a cómo sucede eso pronto.
Asignación automática a miembros del plan
En aras de la simplicidad, supongamos que un plan pertenece a un grupo de Microsoft 365. Los miembros del grupo también son miembros del plan a quienes se les pueden asignar tareas. El script hace esto definiendo un responsable para cada categoría de anuncio de servicio que espera procesar. Las categorías incluyen Exchange, Teams, SharePoint, Viva, etc. Las asignaciones se realizan buscando un miembro del plan que figura en la información de membresía devuelta por Get-MgGroup. Esto nos proporciona un nombre para mostrar de miembro que podemos usar con Get-MgUser para devolver un objeto de usuario completo, incluido el identificador de objeto (un GUID) que se usa para asignar una tarea.
$SharePointAssignee = $PlanMembers.additionalProperties | Where-Object mail -match 'Rene.artois@office365itpros.com'
$SharePointAssignee = (Get-MgUser -UserId $SharePointAssignee.userPrincipalName) | Select-Object -First 1
Posteriormente, el script utiliza una declaración Switch para interpretar los servicios descritos en un anuncio de servicio para asignar responsabilidad a un miembro del grupo. Si todo funciona, el script debería crear una tarea para cualquier anuncio de SharePoint Online y asignarla al responsable de SharePoint.
Asignación automática de etiquetas
Como se mencionó anteriormente, un plan puede utilizar hasta 25 etiquetas. Cada etiqueta tiene un color y un nombre para mostrar asignado (de forma predeterminada, el color) que se puede personalizar para su uso dentro de un plan. Cuando se ejecuta la sincronización estándar, no asigna una etiqueta a las tareas que crea. Antes de que el script pueda hacerlo, alguien debe definir las etiquetas (lo que se hace fácilmente en el cuadro de diálogo de creación de tareas) y debemos incluir detalles sobre las etiquetas en el script.
La GUI del Planificador solo muestra etiquetas con los nombres personalizados configurados para un plan. Para descubrir los números de etiqueta, necesitamos tomar un ejemplo de la configuración categoryDescriptions para el plan. Aquí se explica cómo encontrar esta información:
$Uri =("https://graph.microsoft.com/beta/planner/plans/{0}/details" -f $TargetPlan.id)
$Data = Invoke-MgGraphRequest -Uri $Uri -Method GET
$Data.Categorydescriptions
Name Value
---- -----
category17 Microsoft Viva
category7 SharePoint Online
category6 Microsoft 365 Apps
Por ejemplo, esto nos dice que para aplicar la etiqueta de SharePoint Online a una tarea, incluimos una referencia a la categoría 7, y así sucesivamente. Dentro de las propiedades de una tarea, la propiedad appliedCategories contiene las etiquetas asignadas a esa tarea. Una tarea puede tener hasta 25 etiquetas, pero el script solo asigna la etiqueta que coincide con el depósito elegido para la tarea.
Creando tareas
Antes de que el script pueda crear una nueva tarea, se deben completar varias tablas hash con la configuración para la nueva tarea. El script utiliza tablas hash para:
- Parámetros de la tarea.
- Asignaciones.
- Etiquetas.
- Descripción (el cuerpo de la tarea que contiene una descripción de texto libre sobre los detalles de la tarea). El script realiza algún procesamiento para eliminar etiquetas HTML del cuerpo incluido en un anuncio de servicio. También agrega algunos detalles en la parte superior de la descripción que aparecen en las tareas creadas por la sincronización regular. Estos detalles incluyen el identificador del centro de mensajes (por ejemplo, MC712150), fechas de publicación y última actualización, categorías y etiquetas (Figura 1).
La creación de una nueva tarea se realiza ejecutando el cmdlet New-MgPlannerTask. Todos los parámetros para la nueva tarea se especifican en una tabla hash. Aquí está el fragmento de código que cubre la creación de una nueva tarea.
$TaskParameters = @{}
$TaskParameters.Add('planId',$TargetPlan.Id)
$TaskParameters.Add('bucketid',$TargetBucket)
$TaskParameters.Add('title', $TaskTitle)
$TaskParameters.Add('assignments', $TaskAssignments)
$TaskParameters.Add('priority', '5')
$TaskParameters.Add('startDateTime', $Announcement.LastModifiedDateTime)
$TaskParameters.Add('details',$TaskDescription)
$TaskParameters.Add('appliedCategories', $TaskLabels)
# If an end date is given, use it as the due date for the task
If ($Announcement.EndDateTime) {
$TaskParameters.Add('dueDateTime', $Announcement.EndDateTime)
}
$NewTask = New-MgPlannerTask -BodyParameter $TaskParameters
Cuando Planner detecta la creación de una nueva tarea, envía automáticamente un correo electrónico a los encargados de la tarea para informarles que tienen una nueva tarea (Figura 2). Lo mismo ocurre con las tareas creadas con la aplicación del navegador Planner y las Tareas en Teams. No sucede cuando la aplicación móvil Planner crea nuevas tareas.
Actualización de tareas previamente asignadas
El script también incluye código para manejar actualizaciones de tareas asignadas previamente. Esto se hace comparando el conjunto de tareas incompletas en el plan (recuperadas con el cmdlet Get-MgPlannerPlanTask) con el conjunto de anuncios de servicio que se almacenan entre ejecuciones del script en un archivo CSV. Si se encuentra una actualización, el script actualiza la tarea usando el Update-MgPlannerTask cmdlet. Si es necesario, la descripción de la tarea se actualiza usando el Update-MgPlannerTaskDetail cmdlet.
Lo último que hace el script es exportar el conjunto de anuncios de servicio al archivo CSV en preparación para la siguiente ejecución. En verdad, la sincronización de actualizaciones con tareas existentes es el código en el que tengo menos confianza porque no dediqué tanto tiempo a trabajar en él. Considérelo un desafío verificar y mejorar el código si tiene tiempo e interés.
Obtener y ejecutar el script
La Figura 3 muestra el resultado: un conjunto de tareas creadas en un plan Planner asignadas a personas responsables designadas y con una etiqueta adecuada. En definitiva, el guión funciona (últimas palabras famosas). Al menos a mí me lo parece.
Puede descargar el script completo desde GitHub. Para ejecutar el script de forma interactiva, la cuenta que inicia sesión con Connect-MgGraph debe ser miembro del grupo propietario del plan. Esto se debe a que los cmdlets del SDK de Graph usan permisos delegados para sesiones interactivas. Por otro lado, si el script se ejecuta de forma interactiva mediante una aplicación y una huella digital de certificado para la autenticación o se ejecuta mediante una identidad administrada como un runbook de Azure Automation programado, los cmdlets pueden usar permisos de aplicación y acceder a cualquier plan.
Las sesiones interactivas utilizan el permiso Tasks.ReadWrite. El permiso de la aplicación es Tasks.ReadWrite.All. La lógica aquí es que el primero es el permiso para trabajar con tareas en planes a los que tiene acceso el usuario que ha iniciado sesión. El segundo permite el acceso a todos los planes mediante un proceso en segundo plano (aquí se muestra un ejemplo del uso de permisos de aplicación para analizar las tareas de Planner). Recuerde que si usa runbooks de Azure Automation, la entidad de servicio de la cuenta de automatización debe tener consentimiento para todos los permisos necesarios.
Hubo más trabajo del que esperaba para crear y depurar el script. Parte de esto se debe a la forma un tanto oscura en que Planner realiza sus negocios. Parte se debe a falta de documentación. En cualquier caso, el dolor de perseguir callejones sin salida e ideas erróneas pronto pasa. Se aplica la advertencia normal de que este código está diseñado para ilustrar un principio en lugar de ser una solución completa. Aun así, disfrute trabajando con Planner a través de PowerShell.


