If you are installing services then I think you must have custom actions because that's the way Visual Studio installs services, and that's what the installer classes do. You might not have any of your own code in the service/project installer classes, but you do have custom actions in the custom actions view in the setup project's IDE, right?
It's as-designed because once an assembly is loaded, an attempt to load another identical assembly doesn't do a load. In other environments it might be more obvious, but the old and new assemblies are identical in name, version, publickeytoken, but the code is in fact different. In .NET if you generate a new assembly with different code you're supposed to change something like the publickeytoken otherwise as far as .NET is concerned the assemblies are identical.
IMO the larger design issue here is the use of .NET managed code custom actions to install services. Windows Installer has built in support for installing and starting services (ServiceInstall and ServiceControl tables) that Visual Studio doesn't use, although every other setup tool does.
See
http://installsite.org/pages/en/msi/tips.htmInstalling Secvices with Visual Studio for more history and another way to ge services installed and started.