Immer wenn ich mit den Standard Boardmitteln von MSBuild
versuche alle Verzeichnisse aufzulisten, so könnte ich verzweifeln. Immer die
Verzeichnisse mittels DIR-Befehl in eine Datei schreiben und anschließend
mittels ReadLine-Task auslesen.
1
<Exec
Command
=
"dir
"
$(RefItemsPath)
"
/b
/A:D /S>
"
$(SourceFolder)\refFolders.bbb
"
"
Condition
=
"'$(RefItemsPath)'!=''
and '$(ReferencePath)'==''"
/>
2
<Exec
Command
=
"echo
$(RefItemsPath)>>
"
$(SourceFolder)\refFolders.bbb
"
"
Condition
=
"'$(RefItemsPath)'!=''
and '$(ReferencePath)'==''"
/>
3
<CreateItem
Include
=
"$(SourceFolder)\refFolders.bbb"
Condition
=
"'$(ReferenceFolder)'!=''
and '$(ReferencePath)'==''"
>
4
<Output
TaskParameter
=
"Include"
ItemName
=
"refs"
/>
5
</CreateItem>
6
<ReadLinesFromFile
File
=
"@(refs)"
Condition
=
"'$(ReferenceFolder)'!=''
and '$(ReferencePath)'==''"
>
7
<Output
TaskParameter
=
"Lines"
PropertyName
=
"readedLines"
/>
8
</ReadLinesFromFile>
Aus meiner Sicht nicht wirklich schön, wenn man nur
Verzeichnisse haben möchte, daher habe ich (endlich) einen neuen Task erstellt,
da ich immer noch keinen in den CommunityTools
gefunden habe. Der Task ist so super einfach, erspart mir aber immer einige
Hacks, außerdem werden Build-Files verständlicher.
3
using
System;
4
using
System
.
Collections
.
Generic;
5
using
System
.
Text;
6
using
Microsoft
.
Build
.
Framework;
7
using
Microsoft
.
Build
.
Utilities;
8
using
System
.
Xml;
9
using
System
.
IO;
10
using
System
.
Collections;
11
using
System
.
Diagnostics;
12
13
namespace
DE
.
CapeVision
.
MSBuild
.
Tasks
14
{
15
public
class
DiretoryListingTask
:
Task
16
{
17
private
string
baseFolder;
18
public
bool
IncludeSubFolders {
get
;
set
; }
19
public
string
SearchPattern {
get
;
set
; }
20
[
Output
]
21
public
string
[]
FolderContent {
get
;
set
; }
22
[
Required
]
23
public
string
BaseFolder
24
{
25
get
{
return
baseFolder; }
26
set
{ baseFolder
=
value
; }
27
}
28
public
override
bool
Execute()
29
{
30
//#if(DEBUG)
31
//
Debugger.Launch();
32
//#endif
33
if
(
!
Directory
.
Exists(
this
.
baseFolder))
34
return
true
;
35
string
[] folders
=
Directory
.
GetDirectories(
36
this
.
baseFolder
37
,
string
.
IsNullOrEmpty(
this
.
SearchPattern)
?
"*"
:
this
.
SearchPattern
38
,
this
.
IncludeSubFolders
?
SearchOption
.
AllDirectories :
SearchOption
.
TopDirectoryOnly
39
);
40
this
.
FolderContent
=
folders;
41
return
true
;
42
}
43
}
44
}
Das 2. Thema, was ich in dem Zuge
angehen wollte, war das Batching mal zu überprüfen. MsBuild ist in der Lage Befehle
die mit TaskItems (array) aufgerufen werden zu parallelisieren, bzw. den Befehl
immer wieder auszuführen. Das Batching wird mittels des „%“-Operators
angekündigt und alles weitere und ggf. Typenkonvertierungen für den Task macht
MsBuild. Man kann das sehr gut mit einem einfachen Message-Task testen und
nachstellen. Leider hatte meine Ausgabe nie wirklich geklappt, immer wenn 2 Listen
verknüpft werden sollten, so kam folgendes raus:
iis ()
---
BROWSER_VIEW
iis () --- LOG_VIEW
iis () --- FILE_VIEW
iis () --- CHANGESET_VIEW
iis () --- TICKET_ADMIN
iis () --- MILESTONE_ADMIN
iis () --- ROADMAP_ADMIN
iis () --- REPORT_ADMIN
iis () --- WIKI_ADMIN
iis () --- TIMELINE_VIEW
iis () --- SEARCH_VIEW
iis () --- TRAC_ADMIN
iis (D:\Cache\Msdn\AdvancedBasics) ---
iis (D:\Cache\Msdn\ContinuousIntegration) ---
iis (D:\Cache\Msdn\DataPoints) ---
iis (D:\Cache\Msdn\DependencyInjection) ---
iis (D:\Cache\Msdn\ExtremeASPNET) ---
iis (D:\Cache\Msdn\Foundations) ---
iis (D:\Cache\Msdn\MVCFramework) ---
iis (D:\Cache\Msdn\OfficeSpace) ---
iis (D:\Cache\Msdn\TestRun) ---
12
<Message
Importance
=
"high"
Text
=
"iis
(%(folder.FullPath)) --- %(permission.Identity)"
></Message>
Nach etwas recherche fand ich auch ähnlich Probleme und
irgendwo auch eine Lösung (Gute Erklärung http://blogs.msdn.com/aaronhallberg/archive/2006/09/05/msbuild-batching-generating-a-cross-product.aspx).
Man muss die Ausgabe mittels MsBuild-Task in 2
Targets teilen, so dass der MsBuild-Tasks als Batch durchlaufen wird und
anschließend der 2. Taks. Mein Skript sieht komplett so aus:
1
<?xml
version
=
"1.0"
encoding
=
"utf-8"
?>
2
<Project
DefaultTargets
=
"Test"
xmlns
=
"http://schemas.microsoft.com/developer/msbuild/2003"
>
3
<UsingTask
AssemblyFile
=
"DE.CapeVision.MSBuild.Tasks.dll"
TaskName
=
"DE.CapeVision.MSBuild.Tasks.DiretoryListingTask"
/>
4
<ItemGroup>
5
<permission
Include
=
"BROWSER_VIEW;LOG_VIEW;FILE_VIEW;CHANGESET_VIEW;TICKET_ADMIN;MILESTONE_ADMIN;ROADMAP_ADMIN;REPORT_ADMIN;WIKI_ADMIN;TIMELINE_VIEW;SEARCH_VIEW;TRAC_ADMIN"
/>
6
</ItemGroup>
7
<Target
Name
=
"Test"
>
8
<DiretoryListingTask
BaseFolder
=
"D:\Cache\Msdn"
>
9
<Output
TaskParameter
=
"FolderContent"
ItemName
=
"folder"
/>
10
</DiretoryListingTask>
11
<Message
Importance
=
"high"
Text
=
"iis
(%(folder.FullPath)) --- %(permission.Identity)"
></Message>
12
<Message
Importance
=
"high"
Text
=
"second:"
></Message>
13
<MSBuild
Projects
=
"$(MSBuildProjectFile)"
Targets
=
"InternalAddPermission"
Properties
=
"Folder=%(folder.FullPath)"
/>
14
</Target>
15
<Target
Name
=
"InternalAddPermission"
>
16
<Message
Importance
=
"high"
Text
=
"third:"
></Message>
17
<Message
Importance
=
"high"
Text
=
"trac-admin
$(folder) permission add tester %(permission.Identity)"
></Message>
18
</Target>
19
</Project>
Gebraucht habe ich beides um die Berechtigungen an den
TRAC-Repositories anzupassen, die wir haben. (Dann natürlich nicht mit
Message-Task ;))