for activating a virtual environment, I highly recommend checking out direnv. It has good integration with Emacs through direnv-mode, but also will handle your shell stuff for you. Pretty much fixed a lot of my tooling problems.
I am a bit curious about how one could do the shell-command thing though. In dir-locals you can exec code, but I think that would execute on every file that you open (which is probably not what you want)
One thing I found is that projectile-switch-project-action is the action invoked after switching to a project. This defaults to projectile-file-file, but you might be able to make a function that spawns the process (if it doesn't exist already of course) and then call projectile-find-file.
(figured this out by scrolling through projectile.el and looking for switch-project)