What directory and file do I target to code sign my ClickOnce manifest and .application files?

# Signing ClickOnce Artifacts: Resolving Manifest Signing Errors in Multi-Version Deployments

## Summary
Signing ClickOnce artifacts using the `sign` command failed because the target directory contained multiple versioned subfolders. The signing tool attempted to sign every `MyApp.exe.manifest` found across all versions, causing a duplicate file error. Root cause was incorrect path specification for the base directory in the signing command.

## Root Cause
- The `sign` command was invoked on the `.application` file in the root publish directory.
- This command automatically searches for referenced manifest files in the current directory (`/publish`) and all subdirectories (`Application Files\MyApp_*`).
- Multiple manifests were found (one per version), causing the sign tool's duplicate file error due to ambiguous targeting.
- The manual `Target` attempted to sign the `.application` file with an incorrect base path (`$(PublishUrl)` wasn't specific to the current build's version).

## Why This Happens in Real Systems
- ClickOnce deployments retain historical versions in subdirectories (by default) for rollback/cached version support.
- Automated tools (e.g., `sign` command) traverse all subdirectories unless explicitly limited.
- Solutions often hardcode paths assuming single-version deployments or fail to dynamically pass the current build's versioned path.
- Build pipelines lacking cleanup between executions amplify directory clutter.

## Real-World Impact
- **Security Blocking**: Unsigned artifacts trigger OS/AV security warnings ("Unknown Publisher"), blocking installation.
- **Deployment Failure**: Installers fail to run unsigned ClickOnce manifests/applications.
- **User Trust Erosion**: Repeated security warnings erode end-user confidence.
- **CI/CD Breakdown**: Automated deployments stall post-build due to unsigned artifacts.

## Example or Code
**Original Problematic Target:**
```xml
<Target Name="SignClickOnce" AfterTargets="_CopyFilesToPublishFolder">
  <Exec Command="sign code trusted-signing $(AssemblyName).application ... -b &quot;$(PublishUrl)&quot;" />
</Target>

Fixed Target Using Dynamic Paths:

<Target Name="SignClickOnceDeploy" AfterTargets="Publish">
  <!-- Extract the current versioned path -->
  <PropertyGroup>
    <VersionDir>$([System.IO.Directory]::GetDirectories(`$(PublishDir)Application Files`, `$(AssemblyName)_*`).GetValue(0))</VersionDir>
  </PropertyGroup>

  <!-- Sign the version-specific manifest first -->
  <Exec Command="sign code trusted-signing &quot;$(VersionDir)\$(AssemblyName).exe.manifest&quot; -tse ... -tscp ... -an &quot;$(AssemblyName)&quot;" />

  <!-- Then sign the .application file -->
  <Exec Command="sign code trusted-signing &quot;$(PublishDir)$(AssemblyName).application&quot; -tse ... -tscp ... -an &quot;$(AssemblyName)&quot;" />
</Target>

How Senior Engineers Fix It

  1. Isolate the Current Version Path: Use environment variables/MSBuild properties to capture the current build’s version directory dynamically.
  2. Sign Manifests First: Explicitly sign the exe.manifest within its versioned subdirectory before signing the top-level .application file.
  3. Leverage Publish Targets: Hook into the Publish target (rather than file copies) for better timing guarantees.
  4. Clean Workspaces: Implement pre-publish cleanup to remove historical artifacts (if retention isn’t required).
  5. Parameterize Credentials: Store signing credentials in secure variables (e.g., Azure Key Vault) to avoid hardcoded values.

Why Juniors Miss It

  1. Assumption of Flat Structures: Misunderstanding ClickOnce’s multi-version directory hierarchy.
  2. Undocumented Dependencies: Unaware that .application files implicitly reference manifests in subdirectories.
  3. Tool Behavior Blind Spots: Not realizing sign traverses subdirectories by default.
  4. Over-Reliance on Tooling: Expecting the signing tool to “just work” without auditing actual directory topology.
  5. Insufficient Logging: Missing verbose file-existence checks to capture duplicity before signing.