How make Copy/Paste on VNC kvm in proxmox

Old thread but for anyone still fighting with this I created a little autohotkey v2 script that essentially simulates the keypresses of what's in the clipboard effectively automating typing the content into the VM for you. Been working great for this. I have the hotkey bound to ctrl+alt+v but you can set it to whatever you like by altering the first line. In autohotkey script ^ is ctrl, ! is alt, + is shift, and # is the win key.

Code:
^!v:: { ; Ctrl+Alt+V will trigger this script
    text := A_Clipboard
    if (text == "") {
        MsgBox "Clipboard is empty or not accessible."
    } else {
        text := StrReplace(text, "`r`n", "`n")  ; Normalize line endings
        Loop Parse, text
        {
            SendText(A_LoopField)
            Sleep 10  ; Add a small delay between each keypress to avoid overwhelming the VM
        }
    }
}
 
  • Like
Reactions: chillbird
How I have got it working in Windows VM's and otherwise is as follows in just a couple steps.

  1. select the VM while powered down > Hardware > Display, Advanced enabled. Set to VNC versus default.
  2. Power it up and install spice guest tools like from https://www.spice-space.org/download/windows/spice-guest-tools/spice-guest-tools-latest.exe

Instantly copy and paste support works, even in a Win11 PE it works, so in less than the norm situations as well.
 
@Onoitsu2 Do you know if this works also in Debian guests?

I tried quite a lot of different ways, but didn't find a way to paste something into the guest without installing additional software. How are the spice guest tools supposed to work? Do you need special key combinations?
 
@Onoitsu2 Do you know if this works also in Debian guests?

I tried quite a lot of different ways, but didn't find a way to paste something into the guest without installing additional software. How are the spice guest tools supposed to work? Do you need special key combinations?
Enable it in settings for your VM as I instructed in Step 1, then simply install it. I have only tested on Windows personally. But it likely would work the same way, but should work pretty much the same in the noVNC viewer as for working on a windows system.

Some steps for installing Spice Guest tools on Debian, that explain multiple methods.
https://medium.com/@max.kombarov/in...s-on-a-debian-based-system-in-vm-2bc66fc2d95b
 
AFAIK, those tools only help with the SPICE display. I cannot imagine how they should work with VNC.
Don't ask me HOW it works. Just that it does with the noVNC Proxmox uses. When installing it, and enabling options as I have cited, you can copy and paste into a Windows VM using the option in the noVNC pull out. I stumbled across it posted on some obscure blog back in '21 (offline now, I tried to find it), and have been using it since. So thought I'd put that knowledge out there where some may look most often.
 
I just use SSH with MobaXterm and I can copy and paste to my heart's content. Plus you can open new screens in tabs
 
m2c / just for login or passphrases:

as we need that very rarly and not generic but only for login or luks passphrases in emergency cases -> we go with keepassxc autofill, create entry with passphrase and let keepassxc autofill
I used to use keepassxc autofill as well but it started to only enter aaaaaaaa for each character of the saved passphrase
 
This very much annoyed me, so I made a Tampermonkey user script to solve the problem:

https://gist.github.com/amunchet/4cfaf0274f3d238946f9f8f94fa9ee02

(leave a star if this helps or a comment if something doesn't work for you :) )
This worked very well, thank you. I modified it a bit to work with my workflow and maybe someone else will find it useful:
  • I use the right click and this code would replace that functionality. I know there are keyboard alternatives but it's not my typical workflow.
  • I used Userscripts instead of Tampermonkey as Userscripts is free to download.
JavaScript:
(function () {
  const CANVAS_SELECTOR = "canvas";
  const MIDDLE_MOUSE_BUTTON = 1;

  let canvas;

  function waitForCanvas() {
    canvas = document.querySelector(CANVAS_SELECTOR);

    if (canvas) {
      initCanvas();
    } else {
      console.log("NoVNC canvas not found. Retrying...");
      setTimeout(waitForCanvas, 1000);
    }
  }

  function initCanvas() {
    console.log("NoVNC detected. Middle-click paste enabled.");
    canvas.id = "canvas-id";

    canvas.addEventListener("mousedown", handleMouseDown);
  }

  function handleMouseDown(event) {
    if (event.button === MIDDLE_MOUSE_BUTTON) {
      console.log("Middle-click detected. Pasting clipboard content...");
      event.preventDefault();
      pasteClipboardContent();
    }
  }

  async function pasteClipboardContent() {
    try {
      const text = await navigator.clipboard.readText();
      sendString(text);
    } catch (error) {
      console.error("Clipboard read failed:", error);
    }
  }

function sendString(text) {
  text.split("").forEach((char, index) => {
    setTimeout(() => {
      const needsShift = /[A-Z!@#$%^&*()_+{}:\"<>?~|]/.test(char);
      const event = new KeyboardEvent("keydown", { key: char, shiftKey: needsShift });

      if (needsShift) {
        const shiftDownEvent = new KeyboardEvent("keydown", { keyCode: 16 });
        canvas.dispatchEvent(shiftDownEvent);
      }

      canvas.dispatchEvent(event);

      // Add a keyup event for the shift key if necessary
      if (needsShift) {
        const shiftUpEvent = new KeyboardEvent("keyup", { keyCode: 16 });
        canvas.dispatchEvent(shiftUpEvent);
      }

      // Add a keyup event for the character key
      const keyUpEvent = new KeyboardEvent("keyup", { key: char });
      canvas.dispatchEvent(keyUpEvent);
    }, index * 10);
  });
}

  waitForCanvas();
})();