Various kill commands use a little trick to decide whether to add or not to add. If the previous command matches the current command, it will add; if not, it is not. Functions use a value for this last-command, and manipulating that value is the key to getting what you want.
(defun copy-region-as-kill-append (beg end)
(interactive "r")
(let ((last-command 'kill-region))
(copy-region-as-kill beg end)))
source
share