I was only able to be successful by doing the msbuild/publish once, then write a separate "deploy" program to change and re-sign the manifests as they moved to each environment. It will deploy to QA giving it a new name and config file. Then later "deploy" again to production, giving it a new name and config file at that time as well.
The process requires renaming to remove the .deploy extension, replacing the config file, change the app manifest, change the deployment manifest, (also in my case, update the .xlsx file because I was doing an vsto excel add-in), then resign app manifest, restore the .deploy extension, resign the deployment manifest, and finally copy the results out to the deploy location.
This results in a deploy to QA that when "click-once'd" creates an "Application-QA" in add/remove programs, and a production deploy that when "click-once'd" creates an "Application-PROD". The two can run concurrently because the assembly name and "solutionId" guid have been updated to be different in each environment.
Below is some code on how to change the app and deployment manifests to give them unique names in each environment. If you decide on this approach and would like code for resigning as well I can help.
Private Function UpdateAppManifestBasedOnTarget(caller As IReleaseExecutionCaller, appName As String, appManifestFileInfo As IO.FileInfo) As String
Log.Write(Me.Name, String.Format("update the app manifest based on the target environment..."))
Dim appManifestXML As New Xml.XmlDocument()
Dim appManifestNamespaces As New Xml.XmlNamespaceManager(appManifestXML.NameTable)
appManifestNamespaces.AddNamespace("asmv1", "urn:schemas-microsoft-com:asm.v1")
appManifestNamespaces.AddNamespace("vstav3", "urn:schemas-microsoft-com:vsta.v3")
appManifestNamespaces.AddNamespace("vstov4", "urn:schemas-microsoft-com:vsto.v4")
appManifestXML.Load(appManifestFileInfo.FullName)
'assemblyIdentity
Dim assemblyNode = appManifestXML.SelectSingleNode("/asmv1:assembly/asmv1:assemblyIdentity", appManifestNamespaces)
assemblyNode.Attributes("name").Value = appName & "-" & caller.Release.EnvironmentCode & ".dll"
'description
Dim descNode = appManifestXML.SelectSingleNode("/asmv1:assembly/asmv1:description", appManifestNamespaces)
descNode.InnerXml = appName & "-" & caller.Release.EnvironmentCode
'soluionid guid
Dim custNode = appManifestXML.SelectSingleNode("/asmv1:assembly/vstav3:addIn/vstav3:application/vstov4:customizations/vstov4:customization/vstov4:document", appManifestNamespaces)
Dim currentGUID = custNode.Attributes("solutionId").Value
Dim newGuid As String = String.Format("{0:x8}{1}", caller.Release.EnvironmentCode.ToLower.GetHashCode(), currentGUID.Substring(8))
custNode.Attributes("solutionId").Value = newGuid
appManifestXML.Save(appManifestFileInfo.FullName)
Return newGuid
End Function
Private Sub UpdateDeploymentManifestBasedOnTarget(caller As IReleaseExecutionCaller, appName As String, vstoFileInfo As IO.FileInfo)
Log.Write(Me.Name, String.Format("update the deployment manifest based on the target environment..."))
Dim vstoXML As New Xml.XmlDocument
Dim vstoManifestNamespaces As New Xml.XmlNamespaceManager(vstoXML.NameTable)
vstoManifestNamespaces.AddNamespace("asmv1", "urn:schemas-microsoft-com:asm.v1")
vstoManifestNamespaces.AddNamespace("asmv2", "urn:schemas-microsoft-com:asm.v2")
vstoXML.Load(vstoFileInfo.FullName)
'assemblyIdentity
Dim assemblyNode = vstoXML.SelectSingleNode("/asmv1:assembly/asmv1:assemblyIdentity", vstoManifestNamespaces)
assemblyNode.Attributes("name").Value = appName & "-" & caller.Release.EnvironmentCode & ".vsto"
'description
Dim descNode = vstoXML.SelectSingleNode("/asmv1:assembly/asmv1:description", vstoManifestNamespaces)
descNode.Attributes("asmv2:product").Value = appName & "-" & caller.Release.EnvironmentCode
'dependancy assemblyIdentity
Dim depAssmblyIdentityNode = vstoXML.SelectSingleNode("/asmv1:assembly/asmv2:dependency/asmv2:dependentAssembly/asmv2:assemblyIdentity", vstoManifestNamespaces)
depAssmblyIdentityNode.Attributes("name").Value = appName & "-" & caller.Release.EnvironmentCode & ".dll"
vstoXML.Save(vstoFileInfo.FullName)
End Sub