- C# 96.2%
- PowerShell 2.9%
- Just 0.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .forgejo/workflows | ||
| .github/workflows | ||
| docs | ||
| scripts | ||
| src/LISSTech.KeyPaste | ||
| tests/LISSTech.KeyPaste.Tests | ||
| .editorconfig | ||
| .gitattributes | ||
| .gitignore | ||
| CHANGELOG.md | ||
| Directory.Build.props | ||
| Directory.Packages.props | ||
| global.json | ||
| justfile | ||
| LICENSE | ||
| LISSTech.KeyPaste.slnx | ||
| NOTICE | ||
| README.md | ||
| SECURITY.md | ||
⌨️ LISSTech KeyPaste
Clipboard blocked? Type it anyway.
KeyPaste turns text into layout-aware physical scan-code transitions for Windows remote and virtual consoles that refuse normal paste.
🌐 Landing page · 📦 Latest release · 🛡️ Security · 🧭 Changelog
Tip
Press the global shortcut, paste or type into the command palette, press Enter, then click the destination. KeyPaste handles the rest.
Important
KeyPaste stays local. Submitted text is held only in memory and is never written to settings, logs, telemetry, or a network service.
🧭 Table of contents
- Why KeyPaste
- Product tour
- How it works
- Architecture
- Compatibility
- Install
- Use
- Settings
- Security boundaries
- Build and test
- Signed releases
- Repository map
- Documentation
- Contributing
- License
🚧 Why KeyPaste
Remote consoles often block Ctrl+V, clipboard redirection, Unicode VK_PACKET, or synthetic text APIs. The result is familiar: a password, recovery key, command, or path is on your clipboard—but the destination accepts only physical-looking keyboard input.
KeyPaste uses the active Windows keyboard layout to translate confirmed text into:
| Stage | KeyPaste behavior |
|---|---|
| Preflight | Validates the complete string before sending a single key |
| Mapping | Resolves characters through the active foreground keyboard layout |
| Input | Emits explicit scan-code key-down, hold, key-up, and modifier transitions |
| Targeting | Captures click-release through a pass-through low-level hook—even inside Hyper-V Enhanced Session |
| Privacy | Keeps text in memory; never logs or persists it |
No clipboard forwarding. No guest agent. No target-specific plugin.
✨ Product tour
|
Fast command paletteA PowerToys Run–inspired surface with adaptive Fluent styling, a centered caret, Cascadia/Consolas monospace text, red digits, and blue symbols. Enter arms · Shift+Enter adds a line · Esc cancels. |
Deliberate controlsConfigure the shortcut, targeting mode, key timing, click delay, and timeout without fighting legacy Win32 widgets. Adaptive light/dark palette, custom segmented controls, high-DPI artwork, and a compact notification-area menu. |
|
🏁 How it works
sequenceDiagram
autonumber
actor User
participant Palette as KeyPaste palette
participant Hook as Target monitor
participant Mapper as Layout mapper
participant Win32 as SendInput
participant Target as RDP / Hyper-V / VMware
User->>Palette: Press global shortcut
User->>Palette: Paste or type text
User->>Palette: Enter
Palette->>Hook: Arm mouse-up + Escape hooks
Note over Hook: Non-activating hint follows pointer
User->>Target: Click destination
Hook-->>Palette: Pass click through + report release
Palette->>Mapper: Validate complete text
Mapper->>Win32: Build timed scan-code sequence
Win32->>Target: Physical key transitions
Target-->>User: Exact text appears
The five-second version
- Press your hotkey.
- Paste or type text.
- Press Enter.
- Click the destination.
- Done.
🧱 Architecture
flowchart LR
Hotkey["⌨️ Global hotkey"] --> Palette["✨ Fluent command palette"]
Tray["📍 Notification-area menu"] --> Palette
Palette --> Memory["🔒 In-memory text"]
Memory --> Monitor["🖱️ Pass-through target hooks"]
Monitor --> Layout["🗺️ Active keyboard layout"]
Layout --> Planner["🧮 Scan-code planner"]
Planner --> Sender["⚡ Timed SendInput engine"]
Sender --> RDP["Remote Desktop"]
Sender --> HyperV["Hyper-V VMConnect"]
Sender --> VMware["VMware console"]
Sender --> Support["Remote-support viewers"]
classDef ui fill:#e8f2ff,stroke:#0067b8,color:#10233f;
classDef core fill:#fff4f3,stroke:#c8102e,color:#3b1015;
classDef target fill:#f3f4f6,stroke:#374151,color:#111827;
class Hotkey,Tray,Palette ui;
class Memory,Monitor,Layout,Planner,Sender core;
class RDP,HyperV,VMware,Support target;
Design invariants
- Validate first; never type a partial unsupported string.
- Pass target clicks through unchanged.
- Release every hook and modifier on success, timeout, cancellation, and failure.
- Never log text, screenshots, target details, or credentials.
- Stay at ordinary-user integrity with
asInvoker.
🖥️ Compatibility
| Surface | Status | Notes |
|---|---|---|
| Microsoft Remote Desktop / Windows App | ✅ | Physical scan-code path |
| Hyper-V VMConnect | ✅ | Basic and Enhanced Session tested |
| VMware console | ✅ | Works where clipboard paste is blocked |
| Native remote-support viewers | ✅ | Viewer policy can still reject synthetic input |
| Browser-based consoles | ✅ | Requires the browser to accept host keyboard events |
| Windows sign-in fields | ✅ | When exposed through an ordinary remote console |
| UAC secure desktop | ❌ | Intentionally outside the process integrity boundary |
| BitLocker / firmware / pre-boot UI | ❌ | Not reachable through ordinary Windows SendInput |
| Higher-integrity target | ⚠️ | Run both applications at the same integrity level |
📦 Install
Signed release
- Open Releases.
- Download
LISSTech.KeyPaste-<version>-win-x64.zip. - Verify
SHA256SUMS. - Extract and run
LISSTech.KeyPaste.exe.
The release is self-contained: the target workstation does not need a preinstalled .NET runtime.
Trust
Production executables are:
- Authenticode-signed by LISS Consulting Corp.
- backed by an Entrust EV Code Signing certificate;
- SHA-256 signed;
- RFC 3161 timestamped through DigiCert; and
- verified with Windows Authenticode policy before packaging.
🚀 Use
Palette
| Input | Action |
|---|---|
| Configured global shortcut | Open KeyPaste |
Ctrl+V |
Paste text into the palette |
Enter |
Arm target selection |
Shift+Enter |
Insert a newline |
Esc |
Cancel without typing |
| Left-button release | Select target and begin typing |
Notification-area icon
- Double-click: open settings
- Right-click → Open KeyPaste: open the palette
- Right-click → Settings: configure behavior
- Right-click → Exit: unregister the hotkey and stop
⚙️ Settings
Settings live at:
%ProgramData%\LISS Technologies\LISSTech.KeyPaste\settings.json
Existing settings from %LOCALAPPDATA%\LISSTech\KeyPaste\settings.json are migrated once and the legacy file is removed after the ProgramData write succeeds.
| Setting | Purpose |
|---|---|
| Global shortcut | System-wide palette activation |
| Click target | Arm, follow the pointer, then type after click-release |
| Focused window | Type into the window restored after the palette closes |
| Key delay | Hold/gap timing for slow remote input transports |
| After click | Gives the target time to establish focus |
| Arm timeout | Automatically cancels stale target selection |
🛡️ Security boundaries
flowchart TB
subgraph OrdinaryUser["Ordinary user session"]
UI["Palette + settings"]
Buffer["Ephemeral text buffer"]
Hooks["Mouse-up / Escape hooks"]
Input["Scan-code sender"]
UI --> Buffer --> Hooks --> Input
end
Input -. blocked .-> SecureDesktop["UAC secure desktop"]
Input -. blocked .-> HigherIntegrity["Higher-integrity processes"]
Input --> SameIntegrity["Same-integrity local / remote console"]
- No network client exists in the application.
- No telemetry SDK is referenced.
- Clipboard contents and submitted text are never persisted.
- Low-level hooks observe only left-button release and Escape while armed.
- Hooks always call
CallNextHookEx; KeyPaste never swallows the user's click. - See SECURITY.md for private vulnerability reporting.
🧪 Build and test
Requirements
- Windows 10 or 11
- .NET SDK
10.0.401 - Windows SDK
10.0.26100for release signing - Optional:
just1.58+
just ci
Equivalent commands:
dotnet restore LISSTech.KeyPaste.slnx
dotnet format LISSTech.KeyPaste.slnx --verify-no-changes --no-restore
dotnet build LISSTech.KeyPaste.slnx --configuration Release --no-restore
dotnet test LISSTech.KeyPaste.slnx --configuration Release --no-build
The test suite covers settings normalization and persistence, hotkey validation, CRLF handling, Caps Lock compensation, Unicode rejection, physical modifier ordering, and native INPUT ABI size.
✍️ Signed releases
Unsigned local candidate:
./scripts/Build-Release.ps1 -Version 1.0.0
Production-signed package:
./scripts/Build-Release.ps1 -Version 1.0.0 -Sign
The release pipeline:
- restores locked dependencies;
- verifies formatting;
- runs all tests;
- publishes a self-contained single-file
win-x64executable; - signs and timestamps it;
- verifies the complete Authenticode chain;
- creates the release ZIP; and
- writes
SHA256SUMS.
The EV private key remains on its hardware token. CI intentionally creates unsigned candidates.
🗂️ Repository map
.
├── src/LISSTech.KeyPaste/ # WinForms application and native input engine
│ ├── Models/ # Immutable user configuration
│ ├── Native/ # Win32 ABI declarations
│ ├── Services/ # Mapping, hooks, input, persistence
│ └── UI/ # Fluent palette, settings, hint, menu renderer
├── tests/LISSTech.KeyPaste.Tests/ # Deterministic behavior tests
├── docs/ # Static landing page and artwork
├── scripts/Build-Release.ps1 # Verify, publish, sign, package
├── .forgejo/workflows/ # Forgejo CI and Pages publication
└── justfile # Repeatable developer entry points
📚 Documentation
- Architecture and native-input lifecycle
- Release, signing, and publication operations
- Interactive landing page
- Security policy
- Release history
🤝 Contributing
- Create a focused branch.
- Keep clipboard text and target details out of logs and test fixtures.
- Add behavior tests for mapping or sequencing changes.
- Run
just ci. - Open a pull request with observed Windows verification.
Issues and pull requests are welcome on the internal Forgejo repository.
📜 License
Copyright © 2026 LISS Consulting Corp.
Licensed under the Apache License 2.0. LISSTech names and artwork remain trademarks of LISS Consulting Corp.; Apache 2.0 does not grant trademark rights.
Built for operators who need the text to land exactly where they clicked.