Can you use CruiseControl to build Cocoa/Objective-C projects? - cocoa

Has anyone ever set up Cruise Control to build an OS X Cocoa/Objective-C project?
If so, is there a preferred flavor of CruiseControl (CruiseControl.rb or just regular CruiseControl) that would be easier to do this with.
I currently have a Ruby rake file that has steps for doing building and running tests, and wanted to automate this process after doing a checkin.
Also, does CruiseControl have support for git? I couldn't find anything on the website for this.

Yes, you just run xcode builds via the command line (xcodebuild) which makes it simple to target from CC via an ant <exec>. I've been using just regular CC, not the ruby version and it works fine. Here's a barebones example:
<project name="cocoathing" default="build">
<target name="build">
<exec executable="xcodebuild" dir="CocoaThing" failonerror="true">
<arg line="-target CocoaThing -buildstyle Deployment build" />
</exec>
</target>
</project>
More info on xcodebuild
And there does appear to be a standard git object here, but I don't use git so I can't tell you much more than that!

Yes, CruiseControl has a support for git.

Related

How to prioritize a project in a VisualStudio-solution?

We have a solution with around 70 projects. One of them takes relatively long (~10min) but does not use system resources. We also employ parallel build to speed things up.
When I (re)add this project to the solution, it is at the end of the build order. The machine is 100% busy when compilong 69 projects and then 10min idle when compiling the 70th. When I manually edit the .sln-file so that the project comes first in all lists, it is somewhere in the middle. How can I move it to the beginning?
This is not about dependencies. This project A has only one to another project B and I am fine if B is first as long as A is second. Also, no other projects depends on project A.
It sounds like you have already tried editing project dependencies in visual studio. If you have already edited it to make the project first, but it still takes a while then you probably should just take it out of the solution file. Then put the building of it into your own msbuild script where you can use the MSBuildExtensions parallel tasks to make it build at the same time as everything else:
See https://mikefourie.wordpress.com/2012/02/29/executing-msbuild-targets-in-parallel-part-1/
And I'm pretty sure the MSBuildExtensions library is a nuget package now as well.
VisualStudios sln-files are very limited and are written in a format defined decades ago. In fact, it is converted to a msbuild-script before doing anything useful.
To have more flexibility, I added an msbuild-script (master.msbuild) with something similar to this (untested but proper documentation is available)
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectsToBuild Include="longrunningproject.proj" />
<ProjectToBuild
Include="SolutionWithTheOther69Projects.sln"
Properties="Configuration=Debug;Platform=x86"/>
</ItemGroup>
<Target Name="Build" >
<MSBuild
Projects="#(ProjectsToBuild)"
Targets="Build"
BuildInParallel="true"
ContinueOnError="false"
Properties="VeloxVersion=$(VeloxVersion);RootDir=$(RootDir)"
/>
</Target>
</Project>
Projects are executed in order they are defined. Still no control what happens in the solution but I can put projects in front or behind it and can so influence the build order.
If the long-running task is called by an msbuild-exec-task, it is important to set the YieldDuringToolExecution-flag of this task. E.g.
<Exec
Command="..."
YieldDuringToolExecution="true"
/>
Otherwise, things are starting in parallel and then slowly dying off until the exec-task is done. I could not decode the logic behind that but honestly, I do not care.
After several days of try and error, the build machine screams at 100%-cpu-load, slowly come down to the one long-running task and then is done. Speedup-factor 2.5 :D
How can I move it to the beginning?
You can create a MSBuild project file named "before.<SolutionName>.sln.targets" in the same folder as your solution.
Then build the solution with command line (Visual Studio will ignore this file.), the before.<SolutionName>.sln.targets will be built before all of the Visual Studio projects in the solution.
In this case, we just need to build that special project in the before.<SolutionName>.sln.targets file, that special project will be built before all of projects in the solution.
The content of before.<SolutionName>.sln.targets like:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="BuildSpecialProject" BeforeTargets="Build">
<Message Text="Build My Specify Project" />
<MSBuild Projects="Path\YouSpecialName.csproj"/>
</Target>
</Project>
Then build the solution file with command line with MSBuild or dotnet:
msbuild /t:build "<SolutionPath>\<SolutionName>.sln"
dotnet build "<SolutionPath>\<SolutionName>.sln"
Check this thread for some more details.
Hope this helps.

Using MSBuild.exe to "Publish" a ASP.NET MVC 4 project with the cmd line

I'm looking for a command to run against the MSBuild.exe that just takes a MVC 4 project and publishes it to a given directory.
For example,
MSBuild <solution>/<project>.csproj -publish -output=c:/folder
This is obviously incorrect syntax. I'm trying to simplify my question.
This question talks of a build XML, but I'm not trying to do anything with that much detail.
I'm simply trying to do a deploy.
Further down in that question, someone speaks of "MSDeploy". I can look into that, but is it the only option? I do not have the ability to install web deploy on the server. In which case, all I really need to do is "Publish" and send the contents of the published project to a given directory on the server/file-system.
Does anyone have a one liner I can use?
Do I have to use MSDeploy?
Does MSDeploy require web deploy to be installed on the server?
Doesn't setting up web deploy on the server require setting up some ports, permissions, and installing some IIS add-ons?
I'd love to just execute something simple.
In VS 2012 (as well as the publish updates available in the Azure SDK for VS 2010) we have simplified command line publishing for web projects. We have done that by using Publish Profiles.
In VS for a web project you can create a publish profile using the publish dialog. When you create that profile it is automatically stored in your project under Properties\PublishProfiles. You can use the created profile to publish from the command line with a command line the following.
msbuild mysln.sln /p:DeployOnBuild=true /p:PublishProfile=<profile-name>
If you want to store the publish profile (.pubxml file) in some other location you can pass in the path to the PublishProfile.
Publish profiles are MSBuild files. If you need to customize the publish process you can do so directly inside of the .pubxml file.
If your end goal is to pass in properties from the command line. I would recommend the following. Create a sample publish profile in VS. Inspect that publish profile to determine what MSBuild properties you need to pass in on the command line. FYI not all publish method support command line publishing (i.e. FTP/FPSE).
FYI if you are building the .csproj/.vbproj instead of the .sln and you are using VS 2012 you should also pass in /p:VisualStudioVersion=11.0. For more details as to why see http://sedodream.com/2012/08/19/VisualStudioProjectCompatabilityAndVisualStudioVersion.aspx.
Create a build.xml file thats look like below
Start Visual Studio command prompt
Run msbuild build.xml
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0" DefaultTargets="Build">
<PropertyGroup>
<Build>$(MSBuildProjectDirectory)\Build</Build>
<ProjectFile>MyProject.csproj</ProjectFile>
<ProjectName>MyProjectNameInVisualStudio</ProjectName>
<CopyTo>$(MSBuildProjectDirectory)\CopyTo</CopyTo>
</PropertyGroup>
<Target Name="Build">
<RemoveDir Directories="$(Build)"/>
<MSBuild Projects="$(ProjectFile)" Properties="Configuration=Release;OutputPath=$(Build);OutDir=$(Build)/"></MSBuild>
<Exec Command="robocopy.exe $(Build)\_PublishedWebsites\$(ProjectName) $(CopyTo) /e /is
if %errorlevel% leq 4 exit 0 else exit %errorlevel%"/>
</Target>
</Project>
The command below works perfect:
msbuild Myproject.sln /t:Rebuild /p:outdir="c:\outproject\\" /p:Configuration=Release /p:Platform="Any CPU"
I found Sayed's answer was deploying the default configuration i.e. Debug. The configuration selected in the Publishing Profile seems to get ignored by MSBuild. Accordingly I changed the command to specify the correct configuration for the deployment...
msbuild mysln.sln /p:Configuration=[config-name] /p:DeployOnBuild=true /p:PublishProfile=[profile-name]
where config-name = Release or some other build configuration you've created
With web projects you need to build, as per above, but then you also need to package/copy. We use a file copy, rather than the "publish"...
Also; we use DEBUG/RELEASE to build the website; but then actual environments, ie "QA" or "PROD" to handle the web.config transforms.
So we build it initially with RELEASE, and then package it with QA - in the example below.
<PropertyGroup>
<SolutionName>XXX.Website</SolutionName>
<ProjectName>XXX.Website</ProjectName>
<IisFolderName>XXX</IisFolderName>
<SolutionConfiguration>QA</SolutionConfiguration> <!--Configuration will be set based on user selection-->
<SolutionDir>$(MSBuildThisFileDirectory)..</SolutionDir>
<OutputLocation>$(SolutionDir)\bin\</OutputLocation>
<WebServer>mywebserver.com</WebServer>
</PropertyGroup>
<Target Name="BuildPackage">
<MSBuild Projects="$(SolutionDir)\$(SolutionName).sln" ContinueOnError="false" Targets="Clean;Rebuild" Properties="Configuration=Release" />
<MSBuild Projects="$(SolutionDir)\$(ProjectName)\$(ProjectName).csproj" ContinueOnError="false" Targets="Package" Properties="Configuration=$(SolutionConfiguration);AutoParameterizationWebConfigConnectionStrings=False" />
</Target>
<Target Name="CopyOutput">
<ItemGroup>
<PackagedFiles Include="$(SolutionDir)\$(ProjectName)\obj\$(SolutionConfiguration)\Package\PackageTmp\**\*.*"/>
</ItemGroup>
<Copy SourceFiles="#(PackagedFiles)" DestinationFiles="#(PackagedFiles->'\\$(WebServer)\$(IisFolderName)\$(SolutionConfiguration)\%(RecursiveDir)%(Filename)%(Extension)')"/>
</Target>
So;
Setup your properties
Call the BuildPackage target
Call the CopyOutput target
And voila!

How to use StyleCop with TeamCity

Has anyone had any success with running StyleCop from TeamCity?
I know StyleCop supports a command line mode, however i am not sure how this will integrate into the report output by TeamCity.
I've checked out this plugin found here: https://bitbucket.org/metaman/teamcitydotnetcontrib/src/753712db5df7/stylecop/
However could not get it running.
I am using TeamCity 6.5.1 (latest).
I don't know how familiar you are with MSBuild, but you should be able to add a new Build Step in TC 6 and above, and set MSBuild as the build runner, and point it to a .proj file which does something similar to the following:
<Target Name="StyleCop">
<!-- Create a collection of files to scan -->
<CreateItem Include="$(SourceFolder)\**\*.cs">
<Output TaskParameter="Include" ItemName="StyleCopFiles" />
</CreateItem>
<StyleCopTask
ProjectFullPath="$(MSBuildProjectFile)"
SourceFiles="#(StyleCopFiles)"
ForceFullAnalysis="true"
TreatErrorsAsWarnings="true"
OutputFile="StyleCopReport.xml"
CacheResults="true" />
<Xslt Inputs="StyleCopReport.xml"
RootTag="StyleCopViolations"
Xsl="tools\StyleCop\StyleCopReport.xsl"
Output="StyleCopReport.html" />
<XmlRead XPath="count(//Violation)" XmlFileName="StyleCopReport.xml">
<Output TaskParameter="Value" PropertyName="StyleCopViolations" />
</XmlRead>
<Error Condition="$(StyleCopViolations) > 0" Text="StyleCop found $(StyleCopViolations) broken rules!" />
</Target>
If you don't want to fail the build on a StyleCop error, then set the Error task to be Warning instead.
You'll also need to add the following to your .proj file:
<UsingTask TaskName="StyleCopTask" AssemblyFile="$(StyleCopTasksPath)\Microsoft.StyleCop.dll" />
Microsoft.StyleCop.dll is included in the StyleCop installation, and you'll need to set your paths appropriately.
To see the outputted StyleCop results in TeamCity, you will need to transform the .xml StyleCop report to HTML using an appropriate .xsl file (called StyleCopReport.xsl in the script above).
To display the HTML file in TeamCity, you'll need to create an artifact from this .html output, and then include that artifact in the build results.
The Continuous Integration in .NET book is a great resource.
Did you know that teamcity provides specific properties just from msbuild?
No need for the service messages, see:
http://confluence.jetbrains.net/display/TCD65/MSBuild+Service+Tasks
So you dont have to add a custom report page.
Use the build stats e.g.
<TeamCitySetStatus Status="$(AllPassed)" Text="Violations: $(StyleCopViolations)" />
you can then log the statistic too:
<TeamCityReportStatsValue Key="StyleCopViolations" Value="$(StyleCopViolations)" />
And then create a custom graph to display, and you already have the violations in your msbuild output.
edit main-config.xml and add:
<graph title="Style Violations" seriesTitle="Warning">
<valueType key="StyleCopViolations" title="Violations" buildTypeId="bt20"/>
</graph>
Where buildTypeId="bt20" bt20 is your style build.
I'm late to the show here but a very easy way to achieve this is to install the StyleCop.MSBuild NuGet package in any project which you want to analyse with StyleCop.
After installing the package, StyleCop analysis will run on every build you do, regardless of where or how it is invoked, e.g VS, command line, msbuild, psake, rake, fake, bake, nant, build server, etc. No special actions are required.
If you want the build to fail when StyleCop rules are broken you just need to add the following element to your project file under each appropriate build configuration, E.g.
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<StyleCopTreatErrorsAsWarnings>false</StyleCopTreatErrorsAsWarnings>
...
Again, this will work on every build, regardless of where and how it is invoked.
There's a (new?) third-party TeamCity plugin for StyleCop here, (though I haven't tried it yet).
UPDATE: as far as I can tell, the latest version only works with TeamCity 7 (or I did something wrong). Also, I have a very slow (virtual) build server, so even after the services were restarted, it took a while for the StyleCop runner to appear in the web interface.
Another stupid thing I did was not read the readme properly: you have to unzip the downloaded zip, and use the zip inside.
I also originally started with just a list of .cs files in the "Include" option (for the build step), but that didn't work; links to sln or csproj files do work though.

VS2010 Web Publish command line version of File System deploy

Folks,
In a nutshell, I want to replicate this dialog:
It's a Visual Studio 2010 ASP.Net MVC project. If I execute this command, I get all the files I want, including the transformed web.configs in the "C:\ToDeploy" directory.
I want to replicate this on the command line so I can use it for a QA environment build.
I've seen various articles on how to do this on the command line for Remote Deploys, but I just want to do it for File System deploys.
I know I could replicate this functionality using nAnt tasks or rake scripts, but I want to do it using this mechanism so I'm not repeating myself.
I've investigated this some more, and I've found these links, but none of them solve it cleanly:
VS 2008 version, but no Web.Config transforms
Creates package, but doesn't deploy it..do I need to use MSDeploy on this package?
Deploys package after creating it above...does the UI really do this 2 step tango?
Thanks in advance!
Ok, finally figured this out.
The command line you need is:
msbuild path/to/your/webdirectory/YourWeb.csproj /p:Configuration=Debug;DeployOnBuild=True;PackageAsSingleFile=False
You can change where the project outputs to by adding a property of outdir=c:\wherever\ in the /p: section.
This will create the output at:
path/to/your/webdirectory/obj/Debug/Package/PackageTmp/
You can then copy those files from the above directory using whatever method you'd like.
I've got this all working as a ruby rake task using Albacore. I am trying to get it all done so I can actually put it as a contribution to the project. But if anyone wants the code before that, let me know.
Another wrinkle I found was that it was putting in Tokenized Parameters into the Web.config. If you don't need that feature, make sure you add:
/p:AutoParameterizationWebConfigConnectionStrings=false
I thought I'd post a another solution that I found, I've updated this solution to include a log file.
This is similar to Publish a Web Application from the Command Line, but just cleaned up and added log file. also check out original source http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
Create an MSBuild_publish_site.bat (name it whatever) in the root of your web application project
set msBuildDir=%WINDIR%\Microsoft.NET\Framework\v4.0.30319
set destPath=C:\Publish\MyWebBasedApp\
:: clear existing publish folder
RD /S /Q "%destPath%"
call %msBuildDir%\msbuild.exe MyWebBasedApp.csproj "/p:Configuration=Debug;PublishDestination=%destPath%;AutoParameterizationWebConfigConnectionStrings=False" /t:PublishToFileSystem /l:FileLogger,Microsoft.Build.Engine;logfile=Manual_MSBuild_Publish_LOG.log
set msBuildDir=
set destPath=
Update your Web Application project file MyWebBasedApp.csproj by adding the following xml under the <Import Project= tag
<Target Name="PublishToFileSystem" DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
<Error Condition="'$(PublishDestination)'==''" Text="The PublishDestination property must be set to the intended publishing destination." />
<MakeDir Condition="!Exists($(PublishDestination))" Directories="$(PublishDestination)" />
<ItemGroup>
<PublishFiles Include="$(_PackageTempDir)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(PublishFiles)" DestinationFiles="#(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="True" />
</Target>
this works better for me than other solutions.
Check out the following for more info:
1) http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
2) Publish a Web Application from the Command Line
3) Build Visual Studio project through the command line
My solution for CCNET with the Web.config transformation:
<tasks>
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
<workingDirectory>E:\VersionesCC\Trunk_4\SBatz\Gertakariak_Orokorrak\GertakariakMS\Web</workingDirectory>
<projectFile>GertakariakMSWeb2.vbproj</projectFile>
<targets>Build</targets>
<timeout>600</timeout>
<logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MSBuild.dll</logger>
<buildArgs>
/noconsolelogger /p:Configuration=Release /v:diag
/p:DeployOnBuild=true
/p:AutoParameterizationWebConfigConnectionStrings=false
/p:DeployTarget=Package
/p:_PackageTempDir=E:\Aplicaciones\GertakariakMS2\Web
</buildArgs>
</msbuild>
</tasks>
On VS2012 and above, you can refer to existing publish profiles on your project with msbuild 12.0, this would be equivalent to right-click and publish... selecting a publish profile ("MyProfile" on this example):
msbuild C:\myproject\myproject.csproj "/P:DeployOnBuild=True;PublishProfile=MyProfile"
I've got a solution for Visual Studio 2012: https://stackoverflow.com/a/15387814/2164198
However, it works with no Visual Studio installed at all! (see UPDATE).
I didn't checked yet whether one can get all needed stuff from Visual Studio Express 2012 for Web installation.
A complete msbuild file with inspiration from CubanX
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Publish">
<RemoveDir Directories="..\build\Release\Web\"
ContinueOnError="true" />
<MSBuild Projects="TheWebSite.csproj"
Targets="ResolveReferences;_CopyWebApplication"
Properties="Configuration=Release;WebProjectOutputDir=..\build\Release\Web;OutDir=..\build\Release\Web\bin\"
/>
</Target>
<Target
Name="Build"
DependsOnTargets="Publish;">
</Target>
</Project>
This places the published website in the Web..\build\Release folder

How do I tell MSTEST to run all test projects in a Solution?

I need to know how to tell MSTEST to run all test projects in a solution file. This needs to be done from the command line. Right now I have to pass it a specific project file, I'm trying to get it to run from a SOLUTION file.
I'm hoping this is possible, because in Visual Studio, hitting Ctrl+R, A, runs ALL tests in the currently opened solution.
The way I've interpretted the help files, you have to pass in each DLL specifically.
I want to run this from the command line from my CruiseControl.NET server, so I can write other utilities to make this happen. If there is a wierd way of getting this to happen through some OTHER method, let me know.
How do I tell MSTEST to run all test projects for a solution?
<exec>
<!--MSTEST seems to want me to specify the projects to test -->
<!--I should be able to tell it a SOLUTION to test!-->
<executable>mstest.exe</executable>
<baseDirectory>C:\projects\mysolution\</baseDirectory>
<buildArgs>/testcontainer:testproject1\bin\release\TestProject1.dll
/runconfig:localtestrun.Testrunconfig
/resultsfile:C:\Results\testproject1.results.trx</buildArgs>
<buildTimeoutSeconds>600</buildTimeoutSeconds>
</exec>
To elaborate on VladV's answer and make things a bit more concrete, following the suggested naming convention running your tests can be easily be automated with MSBuild. The following snippet from the msbuild file of my current project does exactly what you asked.
<Target Name="GetTestAssemblies">
<CreateItem
Include="$(WorkingDir)\unittest\**\bin\$(Configuration)\**\*Test*.dll"
AdditionalMetadata="TestContainerPrefix=/testcontainer:">
<Output
TaskParameter="Include"
ItemName="TestAssemblies"/>
</CreateItem>
</Target>
<!-- Unit Test -->
<Target Name="Test" DependsOnTargets="GetTestAssemblies">
<Message Text="Normal Test"/>
<Exec
WorkingDirectory="$(WorkingDir)\unittest"
Command="MsTest.exe #(TestAssemblies->'%(TestContainerPrefix)%(FullPath)',' ') /noisolation /resultsfile:$(MSTestResultsFile)"/>
<Message Text="Normal Test Done"/>
</Target>
Furthermore integrating MsBuild with CruiseControl is a piece of cake.
Edit
Here's how you can 'call' msbuild from your ccnet.config.
First if you do not already use MSBuild for your build automation add the following xml around the snippet presented earlier:
<Project DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
..... <insert snippet here> .....
</Project>
Save this in e.g. RunTests.proj next to your solution in your source tree. Now you can modify the bit of ccnet.config above to the following:
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable>
<workingDirectory>C:\projects\mysolution\</workingDirectory>
<baseDirectory>C:\projects\mysolution\</baseDirectory>
<projectFile>RunTests.proj</projectFile>
<targets>Test</targets>
<timeout>600</timeout>
<logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>
This is an old thread, but I have been struggling with the same issue and I realized that you can really just run MSTest on every dll in the whole solution and it doesn't really cause any problems. MSTest is looking for methods in the assemblies marked with the [TestMethod] attribute, and assemblies that aren't "test" assemblies just won't have any methods decorated with that attribute. So you get a "No tests to execute." message back and no harm done.
So for example in NAnt you can do this:
<target name="default">
<foreach item="File" property="filename">
<in>
<items>
<include name="**\bin\Release\*.dll" />
</items>
</in>
<do>
<echo message="${filename}" />
<exec program="C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe">
<arg value="/testcontainer: ${filename}" />
<arg value="/nologo" />
</exec>
</do>
</foreach>
</target>
and it will run all the test methods in every dll in every bin\Release folder in the solution. Those which are not test dlls will return a "No tests to execute." and those that have tests will have the tests run. The only part I haven't figured out yet is that (in NAnt) execution stops the first time a command returns a non-zero value. So if any unit tests fail it doesn't keep going to execute any tests in subsequent assemblies. That is not great, but if all the tests pass, then they will all run.
I just resolve this problem recently. Here is my proposal: Use testmetadata + testlist option of mstest
First you should create a testlist in testmetadata file(vsmdi)
the commandline should be mstest /testmetadata:....vsmdi /testlist:<name>
Then use ccnet config to run mstest
i know this thread is quite Old, but its still high on Google so i thought i might help one or two.
Anyway, since there is no satisfactory solution for this.
I've written an msbuild task for this.
details can be found here:
http://imistaken.blogspot.com/2010/08/running-all-tests-in-solution.html
You could enforce some convention on the naming and location of test projects, then you could run MSTest on, say, all *Test.dll below the location of your solution.
As far as I know, there is no way to tell a test project from a 'normal' DLL project based soleley on a solution file. So, an alternative could be to analyze the project files and/or .vsmdi files to find the test projects, but that could be rather tricky.
I don't know directly but this is where VSMDI [fx:spits in a corner] can help. In your solution add all the tests to the VSMDI. And then pass the VSMDI to mstest using /testmetadata.
However I would suggest that you follow the conventions above. And use a naming convention and dump that out from the SLN file using say a for loop in the command script
I would just write a target that calls it the way you want, then whip up a batch file that calls the target that contains all the DLL's to be tested.
Unless you're adding test projects all the time, you'll very rarely need to modify it.
Why not just have msbuild output all the test assemblies to a folder.
Try setting OutputPath,OutputDir,OutDir properties in msbuild to accomplish this.
then have mstest execute against all assemblies in that folder.

Resources