Skip to content

Investigate switching VisioCmdlet base from Cmdlet to PSCmdlet #164

Description

@saveenr

Background

VisioPowerShell.Commands.VisioCmdlet derives from System.Management.Automation.Cmdlet, not from PSCmdlet. The choice was deliberate: an early-version attempt with PSCmdlet made unit testing infeasible because the existing test infrastructure relies on direct cmdlet instantiationvar cmd = new SomeVisioCmdlet(); cmd.Invoke<T>() — rather than driving cmdlets through a Runspace. PSCmdlet exposes runspace-tied members (MyInvocation, ParameterSetName, SessionState, etc.) which aren't populated when a PSCmdlet instance is constructed and Invoke()d outside a real PowerShell runspace, so most existing tests would break.

The cost of the current choice is showing up: any cmdlet design that wants to know which parameter set bound (e.g. for cmdlets with both a positional and a pipeline form, like the #163 work on Connect-VisioShape) can't access ParameterSetName and has to use indirect discriminators (e.g. inspecting which property is null at BeginProcessing).

What to investigate

  1. Re-validate the original blocker. Repro the testability problem with PSCmdlet on the current MSTest 4 / SDK-style csproj setup. Does direct cmdlet .Invoke<T>() still fail in the same ways it did circa initial commit, or has the surface improved (PSCmdlet-with-no-runspace-context, or test-friendly PSCmdletExtensions)?

  2. Catalog what we'd actually gain from PSCmdlet. ParameterSetName is the obvious one. Also: MyInvocation.BoundParameters, SessionState, Stopping, WriteProgress overloads, ShouldProcess support. Some of these are nice-to-have, some unblock specific cmdlet designs — document concretely.

  3. Catalog the current VTest.PowerShell test patterns that would break and what it'd take to migrate them. The two patterns in play are:

    • direct-invoke (Cmd_* helpers in VisioPS_Session.cs),
    • runspace-invoke (InvokeScript<T> helper, used for parameter-binding tests like the #143 audit).

    The second already drives a runspace, so it'd survive a PSCmdlet base. The first is the at-risk pattern. Question: can it be adapted to drive a minimal runspace with the same ergonomics, or is there a wrapper that fills in MyInvocation for direct-invoked PSCmdlet instances?

  4. Decide the migration shape if it goes ahead. All-at-once base swap, or PSCmdlet for new cmdlets only? If we keep both, any sister-class concerns?

Why now

This came up while implementing #163 (pipeline parameter set on Connect-VisioShape). The pipeline form worked when run from a real PowerShell session, but tests exercising the same path through VTest.PowerShell's InvokeScript<T> plumbing failed with a Visio session mismatch (CommandTarget: application does not match doc.application). That looked initially like a test-infrastructure quirk specific to runspace-invoked cmdlets that touch TargetPage.Auto, and one of the clean fixes (use ParameterSetName in the cmdlet to take a different code path) is the kind of thing PSCmdlet would unlock. So #163 is parked behind this investigation rather than worked around.

Acceptance

  • A short ADR (or note in docs/decisions/) capturing: original blocker, today's repro / non-repro, the trade-off, and the recommendation.
  • If the recommendation is "switch to PSCmdlet": follow-up implementation issue + migration plan filed against the appropriate semester.
  • If the recommendation is "stay on Cmdlet": close #163 with a "won't do via this design" comment and propose an alternative cmdlet shape (e.g. a separate Connect-VisioShapes for the bulk path) if the pipeline ergonomics goal is still wanted.

Effort

M. Mostly investigation and writing, but the test-pattern audit could surface unexpected migrations. ~half a day for the recommendation memo, more if migration is the answer.

Themed milestone

Milestone B (Test infrastructure).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions