Home / Writing / Automation

Bringing Structure to an AVD Assessment

2026.07.11 · Automation · Updated 2026-09-18
Bringing Structure to an AVD Assessment

An Azure Virtual Desktop assessment can cover quite a lot of ground. There are session hosts and images to inspect, profiles and storage to consider, network dependencies, security settings and the operational procedures around all of them. It is easy to spend the available time on the most visible configuration and leave the less visible questions until later.

I wanted a way to make that review more consistent: a defined set of questions, a reference for each one, and somewhere to record both the findings and the information that is still missing. The result is AvdAssessor, a PowerShell/WPF application with a separate discovery script.

The intention is not to replace an assessment with a scan. It is to automate the collection work that can be automated, then use the workshop to understand the environment and agree what needs to change. A list of resources is useful, but it will not tell you whether anyone has tested the recovery procedure.

Start with a defined scope

The check catalog draws on Microsoft's Cloud Adoption Framework, Well-Architected Framework, AVD product documentation and the AVD Landing Zone Accelerator. Each check has a reference, category, severity, weight and effort estimate.

As of the September 2026 revision reviewed here, the catalog contains 183 checks across 11 categories:

AVD assessment catalog, September 2026
CategoryChecks
Session Hosts29
FSLogix & Profiles27
Security24
Networking21
Governance & Cost17
Monitoring16
Identity & Access12
BCDR12
Landing Zone10
Application Delivery10
Operations5

The reference is there so that you can inspect the reasoning, not simply accept the result because a tool displays it. The selection of checks, their weights and the maturity thresholds are choices in this tool. They are not Microsoft-issued scores or a certification of the environment.

Before collecting anything, agree which subscriptions, host pools and shared services are in scope. Also establish the users and workloads the service must support, its availability requirements and the decisions the assessment is supposed to inform. Otherwise, it is quite possible to produce a detailed report that answers the wrong question.

Collect what the available evidence can tell you

The catalog marks 121 checks as automated and 62 as manual. Those numbers describe the catalog, not a promise that every automated check can be evaluated in every run. Permissions, enabled collection options, available telemetry and the selected subscriptions affect what the discovery script can observe.

Invoke-AvdDiscovery.ps1 collects resource information and check results into JSON. The customer can run it in the agreed scope and share the output through an approved channel, without sharing sign-in credentials. The output is still infrastructure data and should be handled accordingly.

From the tool directory, a multi-subscription run has the following form. Replace the placeholders with the approved subscription IDs and review the module and permission prerequisites first:

$subscriptionIds = @(
    '<avd-subscription-id>'
    '<shared-services-subscription-id>'
)

.\Invoke-AvdDiscovery.ps1 `
    -SubscriptionId $subscriptionIds `
    -OutputPath '.\assessments\customer-avd.json'

Include shared networking and storage subscriptions where they are relevant and access has been approved. The collector does not automatically expand the scope to every subscription that might contain a dependency.

Reader is not the complete permission model

Azure Reader covers the core resource inventory. Graph-backed checks need the relevant read scopes; workspace queries need Log Analytics access; some resources, such as reservations, have additional access requirements. -IncludeGuestChecks is an explicit opt-in that invokes Run Command on a sample of session hosts and requires that action permission. Do not enable it on the assumption that it is just another Reader query.

It is important to keep configuration, runtime evidence and missing evidence separate. An agent extension with a successful provisioning state is not, by itself, proof that the agent is healthy or sending data. Likewise, a query that returns nothing because access is missing does not establish that a resource is absent. Review collection errors and the evidence behind the status before accepting a finding.

Use the workshop to complete the assessment

Once discovery is available, the workflow is fairly straightforward:

  1. Import and review. Load the discovery JSON, confirm the collection time and scope, and inspect incomplete or failed collection areas.
  2. Check applicability. Decide which checks apply to this environment. Record why something is N/A or explicitly excluded instead of using those options to hide an unanswered question.
  3. Review the findings together. Confirm the automated results and work through the manual checks with the people responsible for the service. Attach notes that identify the evidence and any limits.
  4. Agree the next steps. For each actionable finding, establish an owner, a proposed change, its dependencies and how the result will be verified.
  5. Save the assessment. Preserve the JSON and the evidence needed for the follow-up review, then export the findings.

Questions about ownership, recovery objectives, application testing or an operating procedure do not become less important because they require a conversation. A written runbook is useful evidence; a record of a successful recovery test tells you something different. Capture that distinction in the notes.

The application enables periodic autosave after startup, with a default interval of 60 seconds and rolling backups. It writes when there are unsaved changes. Check the settings and save explicitly at useful points in the workshop as well; I would not leave the only copy of a day's findings to a timer.

Understand what the score means

The scoring rules are simple, but they need to be read alongside assessment completion:

  • Pass contributes 100 points, Warning 50, and Fail zero, multiplied by the check's weight.
  • Not Assessed also contributes zero but retains its weight in the denominator. It describes an unanswered check, not an observed failure.
  • N/A and explicitly Excluded checks are removed from both numerator and denominator.

A category score uses the checks in that category. The overall score uses the weighted contributions of all included checks directly; it is not an average of the displayed category percentages. If none of the included checks has been assessed, the result is not scored.

For example, four equally weighted checks marked Pass, Warning, Fail and Not Assessed produce a displayed score of 38%. The unanswered check has not disappeared from the calculation. This is why I would always review the completion state and the individual findings alongside the headline number. A high aggregate score also does not cancel out one critical issue.

The six maturity views group selected checks into Security & Identity, Operations & Hosts, Networking, Resiliency & BCDR, Profiles & Storage, and Monitoring. They provide another way to discuss the results, but the labels are the tool's summary of its scoring model. They do not replace the full category review or demonstrate that a recovery, security or performance target has actually been met.

Make the report useful after the meeting

AvdAssessor exports an HTML report and CSV, and saves assessment state as JSON for later review. That reduces the work of assembling a deliverable, but exporting is not the final quality check. Review the wording, unresolved questions, references and proposed actions before sharing it.

The source links matter here too. Guidance can move, be superseded or stop applying to the version under review. A populated reference field is not proof that a recommendation is still current. Use the current AVD documentation and the relevant component guidance to confirm it.

The catalog is stored in JSON, which makes its definitions inspectable and allows new manual review items to be added. Automating a new check is more work: the collector must gather the right evidence, evaluate it correctly and produce a result the importer understands. Adding a catalog entry alone does not do that.

That is the useful part of bringing structure to the review. The next person should be able to see what was checked, what was observed, what remains unknown and why a change was recommended. The tool helps keep that information together. The assessment still depends on the quality of the evidence and the discussion.

The catalog and scoring behavior described here were checked against repository revision ae652985. The toolkit overview links to the current version.