I am using following task to create cab file.
<Exec Command=""$(CabCreatorPath)\CABARC.exe" n "#(CabFile)" "$(DynamicViewDrive)\Source\Output\ClassReference.mshc" "/>
Is there any other alternative way is there to create cab file from mshc?
You could write your own task to simplify the syntax.
Usage would then instead be something like:
<MshcCab nflag="true" Input="#(CabFile)" Output="$(DynamicViewDrive)\Source\Output\ClassReference.mshc" />
Related
I've got an ItemGroup that includes source files from my project:
<ItemGroup>
<SourceFiles Include=".\**\*.h;.\**\*.cpp"/>
</ItemGroup>
There are a few hundred source files. I want to pass them to a command line tool in an Exec task.
If I call the command line tool individually for each file:
<Exec Command="tool.exe %(SourceFiles.FullPath)" WorkingDirectory="."/>
Then, it runs very slowly.
If I call the command line tool and pass all of the files in one go:
<Exec Command="tool.exe #(SourceFiles -> '"%(FullPath)"', ' ')" WorkingDirectory="."/>
Then, I get an error if there are too many files (I'm guessing the command line length exceeds some maximum).
Is there a way I can chunk the items so that the tool can be called a number of times, each time passing up to a maximum number of source file names to the tool?
I'm not aware of any mechanism to do that with well known item metadata. What you could do is load all those paths into their own item group and write a custom task that calls the exec task. Writing a custom task is pretty simple, it can be done inline:
http://msdn.microsoft.com/en-us/library/vstudio/dd722601(v=vs.100).aspx
I am attempting to dynamically generate a SQL script using MSBuild. The script is responsible for updating some tables etc... post-build.
One of the requirements of this script is to retrieve the product's release notes from a text file and place them into an insert statement in the SQL script.
I'm using TemplateFile to replace the values in a template and generate the SQL script, and it's working as expected. My problem begins when I attempt to read the release notes file. The following is my code:
<PropertyGroup>
<SQLFileTemplate>Update Product Table.template</SQLFileTemplate>
<SQLFileName>Update Product Table.sql</SQLFileName>
<ReleaseNotesFile>Release Notes.txt</ReleaseNotesFile>
</PropertyGroup>
<ReadLinesFromFile File="$(ReleaseNotesFile)">
<Output TaskParameter="Lines" ItemName="FileContents" />
</ReadLinesFromFile>
<ItemGroup>
<Tokens Include="releaseDate">
<ReplacementValue>$(buildDate)</ReplacementValue>
</Tokens>
<Tokens Include="releaseNotes">
<!--Escape the CR LF because MSBuild will replace them with semicolon-->
<ReplacementValue>#(FileContents, '%0a%0d')</ReplacementValue>
</Tokens>
<Tokens Include="releaseLevel">
<ReplacementValue>0</ReplacementValue>
</Tokens>
<Tokens Include="currentVersionInts">
<ReplacementValue>#(versionInts)</ReplacementValue>
</Tokens>
<Tokens Include="currentVersion">
<ReplacementValue>$(GuiVersion)</ReplacementValue>
</Tokens>
<Tokens Include="productVersionId">
<ReplacementValue>$(productId)</ReplacementValue>
</Tokens>
</ItemGroup>
<TemplateFile Template="$(SQLFileTemplate)" OutputFileName="$(SQLFileName)" Tokens="#(Tokens)" />
When I do this, the file is read but it's just put into single spacing and the format is completely gone. I've looked at ReadTextFromFile in MSBuild.Community.Tasks.FileSystem but I can't figure out the syntax.
Can someone give me a hand for this?
Looks like you trying to replace tokens in a file? I don't think you need to go through read and write the file.
You can use the detokenise task in the extension pack to achieve the same results. See: http://www.msbuildextensionpack.com/help/4.0.4.0/index.html
Although i do use the community tasks I think the extension pack has a lot more to offer than the community tasks.
This should be simple, but I can't find how to do this (or maybe it's not possible).
In MSBuild I have an ItemGroup that is a list of files.
I want to execute a task only if a particular file is in that ItemGroup
Something like:
<Copy Condition="#(Files) <contains> C:\MyFile.txt" .... />
Any way to do this? Preferably without writing a custom task.
Edit: The list of files is only to do with the condition. Otherwise it has no relation to the task.
Try
<Copy Condition="'%(Files.Identity)' == 'C:\MyFile.txt'" .. />
I need to read the XML from the file. I use following code:
<ItemGroup>
<SourceXsltFile Include="SourceFile.xml" />
</ItemGroup>
<ReadLinesFromFile File="#(SourceXsltFile)">
<Output TaskParameter="Lines" ItemName="FileContents" />
</ReadLinesFromFile>
But I need only the part of the file's content to be copied which resides inside the <XSL> tag.
Any ideas?
In 4.0+ there are XmlPeek, XmlPoke, and XslTransform tasks you can use here. See MSDN.
http://msbuildtasks.tigris.org/ - use RegexMatch task with something like - <XSL\b[^>]*>(.*?)</XSL> (not sure about exact correctness though).
Write your own custom task
I would like to run a task if any file in an item list is missing. How do I do that?
My current script has a list of "source" files #(MyComFiles) that I translate another list of "destination" files #(MyInteropLibs), using the following task:
<CombinePath BasePath="$(MyPath)\interop"
Paths="#(MyComFiles->'%(filename).%(extension)')">
<Output TaskParameter="CombinedPaths"
ItemName="MyInteropLibs" />
</CombinePath>
I want to check if any of the files in #(MyInteropLibs) is missing and run a task that will create them.
If you only need to create the missing files, and not get a list of the files that were missing you can you the touch task, which will create if the files don't exist.
<Touch Files="#(MyInteropLibs)" AlwaysCreate="True" />
If you only want to create the missing files, and avoid changing timestamps of the existing files, then batching can help
<Touch Files="%(MyInteropLibs.FullPath)" AlwaysCreate="True"
Condition=" ! Exists(%(MyInteropLibs.FullPath)) "/>
If you want a list of the files created then
<Touch Files="%(MyInteropLibs.FullPath)" AlwaysCreate="True"
Condition=" ! Exists(%(MyInteropLibs.FullPath)) ">
<Output TaskParameter="TouchedFiles" ItemName="CreatedFiles"/>
</Touch>
<Message Text="Created files = #(CreatedFiles)"/>
I am not very experienced with MSBuild so there may be better solutions than this but you could write a FilesExist task that takes the file list and passes each file to File.Exists returning true if they do exist and false otherwise and thenn react based on the result
Sorry I can't provide code to help out, my knowlege of MSBuild sytax is not strong
You can find out pretty easily using Exec.
To test if ALL of a set of files exists: The DOS FOR /D command accepts a semicolon-separated list of files - i.e. a flattened item array.
<!-- All exist -->
<Exec
Command="for /D %%i in (#(MyFiles)) do if not exist %%i exit 1"
IgnoreExitCode="true">
<Output TaskParameter="ExitCode" PropertyName="ExistExitCode"/>
</Exec>
To test if ANY of a set of files exists: The DOS DIR command accepts a semicolon-separated list of files. It sets the %ERRORLEVEL% to 0 if it finds any files in the list, nonzero if it finds none. (This is the simpler case, but it does not address the original question...)
<!-- Any exists -->
<Exec Command="dir /B #(MyFiles)" IgnoreExitCode="true">
<Output TaskParameter="ExitCode" PropertyName="DirExitCode"/>
</Exec>
Then most likely you will want to define a boolean property based on the output.
EDIT: BTW this is a code smell. Usually when you find yourself wanting to do this, it's an indication that you should set the Outputs property of the target so it will loop over the items.