Capture output of regsvr32 in an InvokeProcess TF Workflow Activity - msbuild

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.GetL‌​astWin32Error() ).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.

Related

nuget command Source Add started to fail out of nowhere with a warning asking for a unique source

I have an c# wpf application and an additional installer project to create an installer of the application. Among many other files, the installer project has a installer.cmd file (I took over it from someone else) and a Product.wxs file. I was able to create an installer by running msbuild tools\installer.cmd /P:Library=net461 /P:Platform=x64 command on the developper comand prompt.
I was trying to create a desktop shortcut in all user's desktops and was playing with *.wxs file for that. I know you guys will roast me because of the following sentence but I don't know what else can I say. Something I did break something and somehow the msbuild starts to give error. I cannot say what I did because I tried many different things.. I went back to original project but it didn't help. So what is done is done. I will talk about the error now.
The error itself doesn't tell much:
C:\workspace\QToolInstaller\tools\installer.cmd(117,5): error MSB3073: The command "nuget Source Add -Name PkgSrc_638107674121812897 -Source C:\workspace\QToolInstaller\exports" exited with code 1.
I checked online to understand this error code but there wasn't much. However there is another line just before this erorr line:
The source specified has already been added to the list of available package sources. Provide a unique source.
Well, this wasn't in usual warning color or marked as a warning. But I think it is worth to investigate.
So the "source" mentioned here is PkgSrc_638107674121812897. I scanned the installer.cmd to see where is this coming form and saw that this file is named by using time ticks as:
<LocalSource>PkgSrc_$([System.DateTime]::UtcNow.Ticks)</LocalSource>
Although I ran the msbuild command multiple times, the name of the source is always different. I ran the command in diagnostic mode by using -verbosity:diag option. And I checked the file name among all the logs. There is no match. I tried to change the name to something ridicolous that cannot be listed anywhere but got the same error. Removed alll the files, created them again, restarted the PC etc. Nothing have changed. This name is really unique and but still I am getting this message. I wish I had logs form previous successfull runs. I cannot tell if this is the cause of the failure or not. Does any of these ring any bell fellas?
It is solved! Luckily a colleague of mine have faced with this before. I hope no one will have to deal with this problem again.
So apparently there is a bug(?). Altought that name is unique it thinks the opposite. When I do list the sources with thw followng command
nuget source
among the one that should be there, there is one extra line as PkgSrc_638107643440982987. Although my installer.cmd suppose to remove the source every time after it is done, it didn't for once. And although the new source is named differently, it doesn't care and gives that non-warning, non-error message followed by a meaningless error code 1 message. How to solve it?
We tried to remove the source by command prompt like this:
nuget source delete -Name PkgSrc_638107643440982987
But it is not deleted. So we went to the Visual Studio->Tools->NuGet Package Manager->Package Manager Settings->Package Sources. Found the guilty source and remove it. And then it is resolved.

The specified procedure could not be found - how to identify?

I'm developing plugins for a program. Whenever I try to load my plugin in that program it crashes with an the specified procedure could not be foundbut nothing more.
Well to have an insight I tracked with Process Monitor (or ProcMon). I set the filter to just print messages for the process of my main program. However that application shows me including the libraries ends (after wandering through PATH) at the right file - i.e. Result: SUCCESS.
So my computer left me pretty clueless, yet refuses to work. Has anyone an idea how identify the missing procedure?
N.B.: Additionally I ran the DependencyWalker which gave me the usual error message because it's deprecated (dependency walker gives me errors on the system that runs correctly) - which could indicate that all dependencies are found.

Build process xaml file cannot find Workspace

I am attempting to follow the tutorial for CI with Azure and a Team Foundation Build Server located here, but am running into an issue with the configuration of the build configuration template XAML file, in Step 5. In trying to configure a new ConvertWorkSpaceItem, and add it to the modified build template TFS provides (TfvsTemplate.12.xaml) so that a custom script can be run on a TFS build agent, I attempt to set the property Workspace = "Workspace", but am given a compiler error: 'Workspace' is a type and cannot be used as an expression.
I've done some troubleshooting already, and the errors that have happened to others -- not scoping the CreateWorkSpaceItem, or using the wrong version of TFS or Visual Studio -- do not seem to be issues. I placed the logic correctly inside the "Run on Agent" block, so the scope should be right, and Visual Studio and my TFS Server are both running 2013. My only thought is that the instructions are out of date, and there is some other step that needs to be taken that I am missing. Any ideas?
EDIT:
Here are the parameters for the first failed convert item. The second failed Convert item is similar. The Input and Result variables are parameters defined by me for the workflow as part of the instructions for the tutorial. The error displayed is: "Compiler error(s) encountered processing expression "Workspace". 'Workspace' is a type and cannot be used as an expression."
ok this has come up a couple of times now, for TFS 2013.
Built in variables used to be available for
SourcesDirectory, Binaries Directory and Workspace
these are no longer available in TFS 2013 you now have to use
Microsoft.TeamFoundation.Build.Activities.Extensions.WellKnownEnvironmentVariables
to access these.
Getting the workspace is a little more complicated but if you assign some local variables you should be able to get the workspace object.
Declare local variables for sourcesDirectory (string) and buildDetail (IBuildDetail) and workSpace(Workspace) set their scope to the whole workflow
Create an GetEnvironmentVariable Activity and set its Result value to be sourcesDirectory and use Microsoft.TeamFoundation.Build.Activities.Extensions.WellKnownEnvironmentVariables.SourcesDirectory.
Repeat the same for buildDetail = WellKnownEnvironmentVariables.BuildDetail
Create an assign task for the workSpace object, set this one as
workSpace =
"[buildDetail.BuildServer.TeamProjectCollection.GetService().GetWorkspace(sourcesDirectory)]"
This should then give you a Workspace object to use.
note: syntax might be slightly out.
To compliment the removal of these variables MS have added a new Activity
GetLocalPath
which may be of use to you instead

Max number of times a DLL can be registered/unregistered?

Is there a maximum number of times that a DLL can be registered and unregistered in a specific time period?
Here's what I mean and why: I have a Continuous Integration package that builds my VB6 applications and in order to build each of the 80 components of the solution, I:
retrieve each project's dependencies
in turn
register the dll (in NAnt
using < comregister unRegister="false" ... ... >)
build the project
publish the output .dll or .exe
somewhere safe
un-register the dll (in NAnt using
< comregister unRegister="true" ...
... >)
Now, this all works 100% of the time, IF I build each of the 80 projects manually; however, if I get my NAnt script to build all 80 projects in turn (in the correct order) then the build fails, giving me this error in CruiseControls' output...
[comregister] Unregistering 1 files
[comregister] c:\location\myBuild.include(301,4): Error while unregistering 'c:\\[project-location]\lib\myDependentDLLFile.dll' Unable to find an entry point named '**DllUnregisterServer**' in DLL 'c:\\[project-location]\lib\myDependentDLLFile.dll'.
(I don't know where 'DllUnregisterServer' comes from though!)
The same error then appears for every subsequent project that I build past the point of failure, which is around the 50-projects-built area. What I mean, is that the first 50 projects build fine, then the rest fail in-turn.
I have mitigated this by using the failonerror="false" attribute within the comregister call inside NAnt, but this then throws doubt in my mind as to whether this is ok or not...!
Ideally, I'd like to remove the failonerror attribute and report genuine errors back to CruiseControl's logging facilities. Any thoughts or suggestions?
No there's no maximum. Use Dumpbin.exe or Depends.exe to take a look inside that DLL and check that DllUnRegisterServer entry point is actually defined.
I dont think teher is any limit to the no of DLL register/unregister.

"File Not Found" in MSBuild Community Tasks -- Which File?

I'm trying to use the VssGet task of the MSBuild Community Tasks, and the error message "File or project not found" is beating me with a stick. I can't figure out what in particular the error message is referring to. Here's the task:
<LocalFilePath Include="C:\Documents and Settings\michaelc\My Documents\Visual Studio 2005\Projects\Astronom\Astronom.sln" />
<VssGet DatabasePath="\\ofmapoly003\Individual\michaelc\VSS\Astronom_VSS\srcsafe.ini"
Path="$/Astronom_VSS"
LocalPath="#(LocalFilePath)"
UserName="build" Password="build"
Recursive="True" />
If I write a Streamreader to read to either the database path or the local path, it succeeds fine. So the path to everything appears to be accessible. Any ideas?
Two thoughts. One, sometimes a type load exception manifests as a FNF - let's hope that's not it. But if the code is actually being honest, you can track the problem using Procmon or Filemon. Start one of those utilities and then run your task again. You should be able to track down a record of a file that couldn't be located.
#famoushamsandwich that's a great response -- I had not previously heard of procmon or filemon. Tried procmon on the problem, but even after sifting through the relevant output (my gosh the machine does a lot more stuff behind the screen than I was aware of) I couldn't find where a file I'm referencing wasn't being found.
Procmon and Filemon are good suggestions - just make sure you filter the results to only show errors. Otherwise the success messages will bury the problem entries. Also, you can filter out processes that are not at fault (either through the filter dialog or by right-clicking the entry and choosing "Exclude Process".)
A couple other thoughts:
In the LocalFilePath, you are specifying a single file as opposed to a folder. The task, on the other hand, specifies to get files recursively. Perhaps you need to remove "\Astronom.sln" from the LocalFilePath?
Is the build task being run under your account or another? It's possible you have a permissions issue
Do you already have a copy of the code pulled down in the same location? Perhaps there is a failure to overwrite an existing file/folder?