diff --git a/CODE_SIGNING.md b/CODE_SIGNING.md
new file mode 100644
index 0000000..18f437c
--- /dev/null
+++ b/CODE_SIGNING.md
@@ -0,0 +1,100 @@
+# Code Signing Configuration
+
+## Overview
+
+AsyncAwaitBestPractices supports Windows Authenticode code signing to ensure compatibility with Windows 11 Smart App Control. This feature helps prevent the security warnings that occur when Smart App Control is enabled.
+
+## How It Works
+
+### Build Process
+- Code signing is automatically enabled during Release builds when running on Windows
+- Signing occurs after the build completes for each target framework
+- The signing process is conditional and won't break builds when certificates are not available
+
+### Requirements
+- Valid Windows code signing certificate (`.pfx` file)
+- `signtool.exe` available in PATH (included with Windows SDK)
+- Windows build environment (signing is skipped on other platforms)
+
+## Configuration
+
+### Environment Variables
+Set these environment variables to enable code signing:
+
+```bash
+WINDOWS_CODESIGN_CERTIFICATE=path/to/your/certificate.pfx
+WINDOWS_CODESIGN_PASSWORD=your-certificate-password
+```
+
+### MSBuild Properties
+Alternatively, you can set these MSBuild properties:
+
+```xml
+
+ path/to/your/certificate.pfx
+ your-certificate-password
+ http://timestamp.digicert.com
+
+```
+
+## Azure DevOps Pipeline
+
+The Azure DevOps pipeline is configured to automatically sign assemblies when:
+1. A secure file named by `WINDOWS_CODESIGN_CERTIFICATE_NAME` variable is available
+2. The `WINDOWS_CODESIGN_PASSWORD` variable is set
+3. The build is running on Windows
+
+### Pipeline Setup
+1. Upload your code signing certificate as a secure file in Azure DevOps
+2. Set the `WINDOWS_CODESIGN_CERTIFICATE_NAME` variable to the name of your secure file
+3. Set the `WINDOWS_CODESIGN_PASSWORD` variable as a secret variable
+
+## Certificate Requirements
+
+### For Windows 11 Smart App Control
+- Certificate must be issued by a trusted Certificate Authority
+- Certificate must be valid for code signing
+- Certificate should have timestamping enabled for long-term validity
+
+### Recommended Certificate Authorities
+- DigiCert
+- Sectigo (formerly Comodo)
+- GlobalSign
+- Entrust
+
+## Troubleshooting
+
+### Common Issues
+- **Certificate not found**: Ensure the certificate path is correct and the file exists
+- **Invalid password**: Verify the certificate password is correct
+- **Timestamp server unavailable**: The build will retry timestamping, or you can change the timestamp server URL
+- **signtool not found**: Install Windows SDK or ensure signtool.exe is in your PATH
+
+### Local Development
+Code signing is disabled by default for local development. To test signing locally:
+1. Obtain a code signing certificate
+2. Set the required environment variables
+3. Build in Release configuration on Windows
+
+## Security Considerations
+
+- **Never commit certificates to source control**
+- **Use secure storage for certificates and passwords**
+- **Regularly update certificates before expiration**
+- **Use separate certificates for different environments if needed**
+
+## Verification
+
+### Checking if an Assembly is Signed
+You can verify if an assembly is signed using:
+
+```powershell
+# PowerShell
+Get-AuthenticodeSignature "AsyncAwaitBestPractices.dll"
+
+# Command Prompt
+signtool verify /pa "AsyncAwaitBestPractices.dll"
+```
+
+### Properties Dialog
+Right-click the DLL file and select "Properties" → "Digital Signatures" tab to view signature information.
\ No newline at end of file
diff --git a/README.md b/README.md
index ee86990..c160198 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,17 @@ Available on NuGet: https://www.nuget.org/packages/AsyncAwaitBestPractices/
- `AsyncValueCommand : IAsyncValueCommand`
- [Usage instructions](#asyncawaitbestpracticesmvvm-2)
+## Security & Code Signing
+
+AsyncAwaitBestPractices supports **Windows Authenticode code signing** for compatibility with Windows 11 Smart App Control. This ensures that applications using the library won't be blocked by enhanced security features.
+
+- **Automatic signing** in CI/CD pipeline when certificates are available
+- **Conditional signing** - doesn't break local development
+- **Platform detection** - only signs on Windows
+- **Secure certificate storage** using Azure DevOps secure files
+
+For detailed setup instructions, see [CODE_SIGNING.md](CODE_SIGNING.md).
+
## Setup
### AsyncAwaitBestPractices
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 3cea036..dc374c9 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -172,15 +172,29 @@ jobs:
summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'
failIfCoverageEmpty: true
+ # Download code signing certificate
+ - task: DownloadSecureFile@1
+ displayName: 'Download Windows Code Signing Certificate'
+ condition: and(eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['WINDOWS_CODESIGN_CERTIFICATE_NAME'], ''), ne(variables['WINDOWS_CODESIGN_PASSWORD'], '')) # Only run this step on Windows and when certificate and password are available
+ inputs:
+ secureFile: $(WINDOWS_CODESIGN_CERTIFICATE_NAME)
+ name: codesigncert
+
- task: CmdLine@2
displayName: 'Pack AsyncAwaitBestPractices NuGet'
inputs:
script: 'dotnet pack $(PathToAsyncAwaitBestPracticesCsproj) -c Release -p:PackageVersion=$(NugetPackageVersion)'
+ env:
+ WINDOWS_CODESIGN_CERTIFICATE: $(codesigncert.secureFilePath)
+ WINDOWS_CODESIGN_PASSWORD: $(WINDOWS_CODESIGN_PASSWORD)
- task: CmdLine@2
displayName: 'Pack AsyncAwaitBestPractices.MVVM NuGet'
inputs:
script: 'dotnet pack $(PathToAsyncAwaitBestPracticesMVVMCsproj) -c Release -p:PackageVersion=$(NugetPackageVersion)'
+ env:
+ WINDOWS_CODESIGN_CERTIFICATE: $(codesigncert.secureFilePath)
+ WINDOWS_CODESIGN_PASSWORD: $(WINDOWS_CODESIGN_PASSWORD)
# check vulnerabilities
- powershell: |
diff --git a/src/AsyncAwaitBestPractices.MVVM/AsyncAwaitBestPractices.MVVM.csproj b/src/AsyncAwaitBestPractices.MVVM/AsyncAwaitBestPractices.MVVM.csproj
index fbf411f..b83bb94 100644
--- a/src/AsyncAwaitBestPractices.MVVM/AsyncAwaitBestPractices.MVVM.csproj
+++ b/src/AsyncAwaitBestPractices.MVVM/AsyncAwaitBestPractices.MVVM.csproj
@@ -52,6 +52,11 @@
Debug;Release
false
true
+
+
+ $(WINDOWS_CODESIGN_CERTIFICATE)
+ $(WINDOWS_CODESIGN_PASSWORD)
+ http://timestamp.digicert.com
@@ -71,4 +76,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AsyncAwaitBestPractices/AsyncAwaitBestPractices.csproj b/src/AsyncAwaitBestPractices/AsyncAwaitBestPractices.csproj
index 9d97bf7..f17bbdd 100644
--- a/src/AsyncAwaitBestPractices/AsyncAwaitBestPractices.csproj
+++ b/src/AsyncAwaitBestPractices/AsyncAwaitBestPractices.csproj
@@ -53,6 +53,11 @@
Debug;Release
false
true
+
+
+ $(WINDOWS_CODESIGN_CERTIFICATE)
+ $(WINDOWS_CODESIGN_PASSWORD)
+ http://timestamp.digicert.com
@@ -82,4 +87,12 @@
+
+
+
+
+
+
\ No newline at end of file