I have a build process setup to build a managed solution using team build. This solution requires an unmanaged component be registered with the server before we build the solution as we interface with it via COM.
The activity (InvokeProcess) I use to register the ComObject looks something like this
regsvr32.exe /s ComObject.ocx
The activity (InvokeProcess) I use to unregister it looks something like this
regsvr32.exe /u /s ComObject.ocx
I have also added the WriteBuildMessage
and WriteBuildError
to both InvokeProcess
activities using stdOutput and errOutput as the message for each action. I also make sure to set the build message importance to high.
It's my understanding that this should redirect the standard output and error output into these logging activities.
The registrion, build, and unregistrion works just fine as long as I do not set the /maxcpucount
argument of MSBuild to anything greater than 1.
Once I set it to something greater than 1, our cleanup script at the end of the process fails with this error message when attempting to delete the file in question.
Access to the path '...\ComObject.ocx' is denied.'
I think what's happening is that the unregister activity is failing to unregister ComObject.ocx from the server because MSBuild isn't done with it when it's running across multiple cpu's. Then when I get down to try and delete it from the build server, it's still registered with the system and will fail with the access denied error.
So how do I get regsvr32 output to the stdOutput and errOutput so that the WriteBuildMessage and writeBuildError activities will properly display it in the build logs. If I call regsvr32 with a file that doesn't exist, I see nothing in the build log.
I hope this is makes sense.
Update
The solution to this problem came from a minor tweak of pantelif's solution. What I did was in the if block that throws an exception, I do a WriteBuildError using this as the message:
String.Format("ErrorMessage: {0}", New System.ComponentModel.Win32Exception( System.Runtime.InteropServices.Marshal.GetLastWin32Error() ).ToString() )
This allows me to get the error from regsvr32.exe and write it to the build log.
As for your first question:
I believe it's possible to capture the output, by applying the technique presented by E.Hofman here.
More specifically, if you construct within your 'InvokeProcess' a sequence like presented (pic also from Ewald's post):
& then assign 'WriteBuildMessage' to stamp the 'ErrorMessage', you shall probably end up with getting the output you desire in the generated build log.