1 <?xml version="1.0" encoding="utf-8"?>
2 <Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <UsingTask TaskName="AddItemIndices" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>
4 <UsingTask TaskName="ConvertPortablePdbsToWindowsPdbs" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>
5 <UsingTask TaskName="DownloadFilesFromUrl" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>
6 <UsingTask TaskName="ExecWithRetries" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>
7 <UsingTask TaskName="ZipFileExtractToDirectory" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>
8 <UsingTask TaskName="ZipFileGetEntries" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>
9 <UsingTask TaskName="ZipFileInjectFile" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll"/>
12 <SymbolsRequestIntermediateDir Condition="'$(SymbolsRequestIntermediateDir)'==''">$(BaseIntermediateOutputPath)SymbolsRequest\</SymbolsRequestIntermediateDir>
16 Submits a request to index or archive symbols with the Microsoft symbol server. Depends on
17 targets which assemble the request specification file.
19 <Target Name="SubmitSymbolsRequest"
20 DependsOnTargets="CreateSymbolsRequestIni">
22 <CreateRequestCommandLocation>\\symbols\tools\CreateRequest.cmd</CreateRequestCommandLocation>
23 <SymbolsRequestLogDir>$(SymbolsRequestIntermediateDir)Logs\</SymbolsRequestLogDir>
25 <SubmissionArg Condition="'$(IndexSymbols)'=='true'">-s</SubmissionArg>
26 <SubmissionArg Condition="'$(ArchiveSymbols)'=='true'">-a</SubmissionArg>
28 <RequestCommand>$(CreateRequestCommandLocation)</RequestCommand>
29 <RequestCommand>$(RequestCommand) -i $(SymbolsRequestIniPath)</RequestCommand>
30 <RequestCommand>$(RequestCommand) -d $(SymbolsRequestLogDir)</RequestCommand>
31 <RequestCommand>$(RequestCommand) -c</RequestCommand>
32 <RequestCommand Condition="'$(SymbolsRequestDryRun)'!='true'">$(RequestCommand) $(SubmissionArg)</RequestCommand>
35 <Message Text="[$([System.DateTime]::Now.ToString('HH:mm:ss.ff'))] Running request command..." Importance="High"/>
37 <Exec Command="$(RequestCommand)" />
39 <Message Text="[$([System.DateTime]::Now.ToString('HH:mm:ss.ff'))] Running request command... Done." Importance="High"/>
43 Creates a Request.ini file that can be used as an input to the symbol server CreateRequest tool.
45 <Target Name="CreateSymbolsRequestIni"
46 DependsOnTargets="AddRequestProperties;
47 AddArchiveRequestProperties;
48 CreateSymbolsFileList">
50 <SymbolsRequestIniPath>$(SymbolsRequestIntermediateDir)request-$(SymbolsBuildId)-$(SymbolsBuildRemark).ini</SymbolsRequestIniPath>
53 <WriteLinesToFile File="$(SymbolsRequestIniPath)"
54 Lines="@(RequestProperty)"
59 Creates RequestProperty items that apply to all requests.
61 <Target Name="AddRequestProperties">
63 <SymbolsBuildId Condition="'$(SymbolsBuildId)'==''">$(BUILD_DEFINITIONNAME)</SymbolsBuildId>
65 <SymbolsBuildRemark Condition="'$(SymbolsBuildRemark)'=='' and
66 '$(BUILD_BUILDNUMBER)'!='' and
67 '$(BUILD_BUILDID)'!=''"
68 >$(BUILD_BUILDNUMBER)-$(BUILD_BUILDID)</SymbolsBuildRemark>
70 <SymbolsErrorMailOnly Condition="'$(SymbolsErrorMailOnly)'==''">Yes</SymbolsErrorMailOnly>
73 <Error Text="'SymbolsProject' must be defined." Condition="'$(SymbolsProject)'==''" />
74 <Error Text="'SymbolsStatusMail' must be defined." Condition="'$(SymbolsStatusMail)'==''" />
75 <Error Text="'SymbolsUserName' must be defined." Condition="'$(SymbolsUserName)'==''" />
77 <Error Text="'SymbolsBuildId' must be defined, or fallback 'BUILD_DEFINITIONNAME'" Condition="'$(SymbolsBuildId)'==''" />
78 <Error Text="'SymbolsBuildRemark' must be defined, or fallbacks 'BUILD_BUILDNUMBER' and 'BUILD_BUILDID'" Condition="'$(SymbolsBuildRemark)'==''" />
81 <RequestProperty Include="BuildId=$(SymbolsBuildId)" />
82 <RequestProperty Include="BuildRemark=$(SymbolsBuildRemark)" />
83 <RequestProperty Include="ErrorMailOnly=$(SymbolsErrorMailOnly)" />
84 <RequestProperty Include="Project=$(SymbolsProject)" />
85 <RequestProperty Include="StatusMail=$(SymbolsStatusMail)" />
86 <RequestProperty Include="UserName=$(SymbolsUserName)" />
91 Creates RequestProperty items that apply to archive requests.
93 <Target Name="AddArchiveRequestProperties"
94 Condition="'$(ArchiveSymbols)'=='true'">
96 <SymbolsBuild Condition="'$(SymbolsBuild)'==''">$(BUILD_BUILDNUMBER)</SymbolsBuild>
99 <Error Text="'SymbolsRelease' must be defined." Condition="'$(SymbolsRelease)'==''" />
100 <Error Text="'SymbolsProductGroup' must be defined." Condition="'$(SymbolsProductGroup)'==''" />
101 <Error Text="'SymbolsProductName' must be defined." Condition="'$(SymbolsProductName)'==''" />
103 <Error Text="'SymbolsBuild' must be defined for a symbol archive request, or fallback 'BUILD_BUILDNUMBER'" Condition="'$(SymbolsBuild)'==''" />
106 <RequestProperty Include="Build=$(SymbolsBuild)" />
107 <RequestProperty Include="Release=$(SymbolsRelease)" />
108 <RequestProperty Include="ProductGroup=$(SymbolsProductGroup)" />
109 <RequestProperty Include="ProductName=$(SymbolsProductName)" />
110 <RequestProperty Include="SubmitToArchive=ALL" />
111 <RequestProperty Include="SubmitToInternet=Yes" />
116 Creates the list of every symbol file to submit to the symbol server.
118 Creates RequestProperties:
119 * FileList: the newline-separated list of paths on disk or in a share to submit.
120 * PrefixToStrip: specifies the path prefix of all paths in the request. The symbol server
121 replaces 'PrefixToStrip' with 'UNCPath' when calculating the share location of each file.
123 <Target Name="CreateSymbolsFileList"
124 DependsOnTargets="GetAllSymbolFilesToPublish;
125 PublishSymbolFilesToFileShare">
127 <SymbolFileListPath>$(SymbolsRequestIntermediateDir)SymbolFileList.txt</SymbolFileListPath>
131 <RequestProperty Include="FileList=$(SymbolFileListPath)" />
132 <RequestProperty Include="PrefixToStrip=$(SymbolPackageExtractDir)" />
135 <MakeDir Directories="$(SymbolsRequestIntermediateDir)"
136 Condition="!Exists('$(SymbolsRequestIntermediateDir)')" />
138 <WriteLinesToFile File="$(SymbolFileListPath)"
139 Lines="@(SymbolFileToPublish -> '%(FullPath)')"
144 Gets every symbol file to publish onto disk and creates SymbolFileToPublish items.
146 <Target Name="GetAllSymbolFilesToPublish"
147 DependsOnTargets="UnzipSymbolPackagesForPublish;
148 GenerateAdditionalSymbolsForArchive" />
151 Copies symbols to a directory based on the given search glob path. The target should be a file
152 share that the symbol server can access when servicing the request.
154 Creates RequestProperty:
155 * UNCPath: path of the file share root.
157 <Target Name="PublishSymbolFilesToFileShare"
158 DependsOnTargets="UnzipSymbolPackagesForPublish">
159 <Error Text="'SymbolPublishDestinationDir' must be defined." Condition="'$(SymbolPublishDestinationDir)'==''" />
162 <RequestProperty Include="UNCPath=$(SymbolPublishDestinationDir)" />
166 <SymbolPublishCopyRetries Condition="'$(SymbolPublishCopyRetries)'==''">5</SymbolPublishCopyRetries>
169 <ItemGroup Condition="'$(SymbolFileSearchGlob)'!=''">
170 <SymbolFileToPublish Include="$(SymbolFileSearchGlob)" />
174 <SymbolFileToPublish>
175 <DestinationPath>$(SymbolPublishDestinationDir)%(RecursiveDir)%(Filename)%(Extension)</DestinationPath>
176 </SymbolFileToPublish>
179 <Error Text="No symbol files found to publish. No existing 'PublishedSymbolsFile' items, and glob '$(SymbolFileSearchGlob)' found no items."
180 Condition="'@(SymbolFileToPublish)'==''" />
182 <Message Text="Publishing files to '$(SymbolPublishDestinationDir)'."
185 <MakeDir Directories="$(SymbolPublishDestinationDir)"
186 Condition="!Exists('$(SymbolPublishDestinationDir)')" />
188 <Message Text="[$([System.DateTime]::Now.ToString('HH:mm:ss.ff'))] Copying symbols to publish dir..." Importance="High"/>
190 <Copy SourceFiles="@(SymbolFileToPublish)"
191 DestinationFiles="@(SymbolFileToPublish -> '%(DestinationPath)')"
192 Retries="$(SymbolPublishCopyRetries)">
193 <Output TaskParameter="CopiedFiles" ItemName="PublishedSymbolFile"/>
196 <Message Text="[$([System.DateTime]::Now.ToString('HH:mm:ss.ff'))] Copying symbols to publish dir... Done." Importance="High"/>
200 Unzips a set of symbol packages so the symbols inside can be archived/indexed.
203 * AddRequestProperties: uses SymbolsBuildId and SymbolsBuildRemark to create a distinct extract
204 folder for each request.
206 <Target Name="UnzipSymbolPackagesForPublish"
207 DependsOnTargets="AddRequestProperties"
208 Condition="'$(SymbolPackagesToPublishGlob)'!=''">
210 <SymbolPackageExtractDir>$(SymbolsRequestIntermediateDir)ExtractedPackages\</SymbolPackageExtractDir>
214 <SymbolPackageFile Include="$(SymbolPackagesToPublishGlob)" />
217 <!-- Extract to the index of the symbol package, not file name, to avoid exceeding max path. -->
218 <AddItemIndices Input="@(SymbolPackageFile)">
219 <Output TaskParameter="Output" ItemName="SymbolPackageFileWithIndex" />
222 <RemoveDir Directories="$(SymbolPackageExtractDir)"
223 Condition="Exists('$(SymbolPackageExtractDir)')" />
225 <Message Text="[$([System.DateTime]::Now.ToString('HH:mm:ss.ff'))] Extracting symbol packages..." Importance="High"/>
227 <ZipFileExtractToDirectory SourceArchive="%(Identity)"
228 DestinationDirectory="@(SymbolPackageFileWithIndex -> '$(SymbolPackageExtractDir)%(Index)')"
229 OverwriteDestination="true" />
231 <Message Text="[$([System.DateTime]::Now.ToString('HH:mm:ss.ff'))] Extracting symbol packages... Done." Importance="High"/>
234 <IndexedExtensions Include=".dll;.pdb;.exe" Condition="'@(IndexedExtensions)'==''" />
235 <SymbolFileToPublish Include="$(SymbolPackageExtractDir)**\*%(IndexedExtensions.Identity)" />
239 <!-- Generate any extra symbols (e.g. Windows PDBs) that also need to be archived. -->
240 <Target Name="GenerateAdditionalSymbolsForArchive"
241 DependsOnTargets="SetupCreateWindowsPdbsFromPortablePdbs;
242 CreateWindowsPdbsFromPortablePdbs;
243 AddConvertedWindowsPdbsToPublishList" />
246 Set up properties for CreateWindowsPdbsFromPortablePdbs that will generate Windows PDBs for
247 files in the unzipped symbol packages.
249 <Target Name="SetupCreateWindowsPdbsFromPortablePdbs">
251 <PortablePdbToConvertGlob>$(SymbolPackageExtractDir)**\*.pdb</PortablePdbToConvertGlob>
252 <WindowsPdbConversionTargetPath>$(SymbolPackageExtractDir)WindowsPDB\</WindowsPdbConversionTargetPath>
257 Add Windows PDBs created in CreateWindowsPdbsFromPortablePdbs to the list of symbol files to
258 publish. We need to wait until after the conversion: only Portable PDBs will be converted, and
259 we can't tell beforehand which PDBs are portable.
261 <Target Name="AddConvertedWindowsPdbsToPublishList">
263 <SymbolFileToPublish Include="$(WindowsPdbConversionTargetPath)**\*.pdb" />
267 <!-- This will be overridden if we're building with MicroBuild. -->
268 <Target Name="SignFiles">
269 <Message Text="Fake sign target. Would sign: @(FilesToSign)" />
273 Entry point: inject signed symbol catalogs into all specified symbol packages.
275 <Target Name="InjectSignedSymbolCatalogIntoSymbolPackages"
276 DependsOnTargets="GenerateSymbolCatalogs;
278 <MSBuild Targets="InjectSignedSymbolCatalogsForPackage"
279 Projects="$(MSBuildProjectFile)"
280 Properties="SymbolPackageFilePath=%(SymbolPackageFileWithIndex.Identity);
281 SymbolPackageIndex=%(SymbolPackageFileWithIndex.Index);
282 SymbolCatalogIntermediateDir=$(SymbolCatalogIntermediateDir);"
283 Condition="'@(SymbolPackageFileWithIndex)'!=''" />
287 Generate symbol catalogs for all symbol packages specified. Creates FilesToSign items for each
288 catalog so they can be sigend.
290 <Target Name="GenerateSymbolCatalogs">
292 <SymbolCatalogIntermediateDir Condition="'$(SymbolCatalogIntermediateDir)' == ''">$(BaseIntermediateOutputPath)SymbolsCatalog\</SymbolCatalogIntermediateDir>
293 <ExtensionsToCatalog Condition="'$(ExtensionsToCatalog)'==''">.dll;.pdb;.a;.so;.dbg;.dylib;.dwarf</ExtensionsToCatalog>
294 <MakeCatCommand Condition="'$(MakeCatCommand)'==''">makecat -v</MakeCatCommand>
298 <SymbolPackageFile Include="$(SymbolPackagesToPublishGlob)" />
301 <!-- Extract to the index of the symbol package, not file name, to avoid exceeding max path. -->
302 <AddItemIndices Input="@(SymbolPackageFile)">
303 <Output TaskParameter="Output" ItemName="SymbolPackageFileWithIndex" />
306 <RemoveDir Directories="$(SymbolCatalogIntermediateDir)"
307 Condition="Exists('$(SymbolCatalogIntermediateDir)')" />
309 <MSBuild Targets="GenerateSymbolCatalogsForPackage"
310 Projects="$(MSBuildProjectFile)"
311 Properties="SymbolPackageFilePath=%(SymbolPackageFileWithIndex.Identity);
312 SymbolPackageIndex=%(SymbolPackageFileWithIndex.Index);
313 ExtensionsToCatalog=$(ExtensionsToCatalog);
314 SymbolCatalogIntermediateDir=$(SymbolCatalogIntermediateDir);
315 MakeCatCommand=$(MakeCatCommand)" />
317 <!-- Find the catalogs to sign them. -->
318 <Error Text="'SymbolCatalogCertificateId' must be defined."
319 Condition="'$(SymbolCatalogCertificateId)'==''" />
322 <FilesToSign Include="$(SymbolCatalogIntermediateDir)**\*.cat">
323 <Authenticode>$(SymbolCatalogCertificateId)</Authenticode>
329 The OutDir and IntermediateOutputPath properties are required by MicroBuild. MicroBuild only
330 signs files that are under these paths.
332 <OutDir Condition="'$(OutDir)'==''">$(BinDir)</OutDir>
333 <!-- always overwrite IntermediateOutputPath so we know we can sign the catalogs.
334 some repos do weird things with BaseIntermediateOutputPath -->
335 <IntermediateOutputPath>$(SymbolCatalogIntermediateDir)</IntermediateOutputPath>
340 Generates any catalogs needed to sign a specific symbol package.
342 <Target Name="GenerateSymbolCatalogsForPackage">
344 <!-- Create a single item for the symbol package to get metadata about it. -->
345 <SymbolPackageFile Include="$(SymbolPackageFilePath)" />
346 <ExtensionToCatalog Include="$(ExtensionsToCatalog)" />
350 <ExtractBaseDir>$(SymbolCatalogIntermediateDir)$(SymbolPackageIndex)\</ExtractBaseDir>
353 <ZipFileGetEntries TargetArchive="$(SymbolPackageFilePath)">
354 <Output TaskParameter="Entries" ItemName="SymbolPackageEntry" />
358 <!-- files like _.pdb and _._ are empty and makecat doesn't handle empty files -->
359 <FilteredSymbolPackageEntries Include="@(SymbolPackageEntry)" Condition="'%(Filename)' != '_'" />
360 <SymbolPackageEntryCrossExtensionsToCatalog Include="@(FilteredSymbolPackageEntries)">
361 <AttemptMatchExtension>%(ExtensionToCatalog.Identity)</AttemptMatchExtension>
362 </SymbolPackageEntryCrossExtensionsToCatalog>
364 <SymbolFileToCatalog Include="@(SymbolPackageEntryCrossExtensionsToCatalog)"
365 Condition="'%(Extension)'=='%(AttemptMatchExtension)'" />
369 <ZipFileExtractToDirectory SourceArchive="$(SymbolPackageFilePath)"
370 Include="@(SymbolFileToCatalog)"
371 DestinationDirectory="$(ExtractBaseDir)"
372 Condition="'@(SymbolFileToCatalog)'!=''" />
374 <!-- Leave a marker so a package can be associated with its numbered dir. -->
375 <WriteLinesToFile File="$(SymbolCatalogIntermediateDir)%(SymbolPackageFile.Filename)"
376 Lines="$(SymbolPackageIndex)"
378 Condition="'@(SymbolFileToCatalog)'!=''" />
380 <!-- Create the catalog file to feed into makecat. -->
382 <CatalogFileHeaderLines>
388 HashAlgorithms=SHA256;
390 EncodingType=0x00010001;
391 CATATTR1=0x10010001:OSAttr:2:6.4;
393 </CatalogFileHeaderLines>
397 <CatalogFile Include="$(ExtractBaseDir)signatures.cat.cdf"
398 Condition="'@(SymbolFileToCatalog)'!=''">
399 <ContentLines>$(CatalogFileHeaderLines);@(SymbolFileToCatalog -> '<HASH>%(Identity)=%(Identity);<HASH>%(Identity)ATTR1=0x11010001:Filename:%(Identity);')</ContentLines>
403 <Message Text="@(CatalogFile)" />
405 <WriteLinesToFile File="@(CatalogFile)"
406 Lines="%(ContentLines)"
407 Condition="'@(CatalogFile)'!=''" />
409 <!-- Create an easily readable list of files that were cataloged. -->
410 <WriteLinesToFile File="$(ExtractBaseDir)cataloged.txt"
411 Lines="@(SymbolFileToCatalog)"
412 Condition="'@(CatalogFile)'!=''" />
415 Don't include cdf path because it may be too long for makecat.
416 See https://stackoverflow.com/a/18682676
418 <Exec Command="$(MakeCatCommand) %(CatalogFile.Filename)%(CatalogFile.Extension)"
419 WorkingDirectory="%(CatalogFile.RootDir)%(CatalogFile.Directory)"
420 Condition="'@(CatalogFile)'!=''" />
424 Inject all symbol catalogs found in the extracted symbol package dir into a new copy of the
425 symbol package in the intermediate dir.
427 <Target Name="InjectSignedSymbolCatalogsForPackage">
429 <CatalogFile Include="$(SymbolCatalogIntermediateDir)$(SymbolPackageIndex)\**\*.cat" />
431 <ArchivePath>%(RecursiveDir)%(Filename)%(Extension)</ArchivePath>
434 <CatalogedFileManifest Include="$(SymbolCatalogIntermediateDir)$(SymbolPackageIndex)\cataloged.txt">
435 <ArchivePath>cataloged.txt</ArchivePath>
436 </CatalogedFileManifest>
439 <ZipFileInjectFile TargetArchive="$(SymbolPackageFilePath)"
440 InjectFiles="@(CatalogFile);@(CatalogedFileManifest)"
441 Condition="'@(CatalogFile)'!=''" />
445 Generates Windows PDBs from Portable PDBs. PDBs passed that are not Portable are skipped.
448 $(PortablePdbToConvertGlob)
449 * A path glob that matches all portable PDBs to convert. Conversion requires the DLL, and this
450 option assumes that the DLL is in the same directory with the same filename.
451 $(WindowsPdbConversionTargetPath)
452 * Location to place converted PDBs when using PortablePdbToConvertGlob. Recursive directory
453 is preserved, if one is present in the glob.
454 @(ConversionOptions) [optional]
455 * ItemSpec: An entry in the Microsoft.DiaSymReader.Tools.PdbConversionOptions flags enum to
456 use for all conversions performed.
458 <Target Name="CreateWindowsPdbsFromPortablePdbs"
459 Condition="'$(SkipCreateWindowsPdbsFromPortablePdbs)'!='true'">
461 <!-- Early exit for unsupported scenario. See https://github.com/dotnet/buildtools/issues/1607 -->
462 <Error Text="BuildTools does not support Portable PDB conversion to Windows PDB in .NET Core. Run msbuild using the desktop framework."
463 Condition="'$(MSBuildRuntimeType)'=='core'" />
465 <!-- Find DLL/PDB pairs based on the optional path glob given. -->
466 <ItemGroup Condition="'$(PortablePdbToConvertGlob)'!=''">
467 <_PdbCandidate Include="$(PortablePdbToConvertGlob)" />
469 <_ToPublishDllCandidate Include="@(_PdbCandidate -> '%(RootDir)%(Directory)%(Filename).dll')">
470 <PdbPath>%(Identity)</PdbPath>
471 <PdbRecursiveDir>%(RecursiveDir)</PdbRecursiveDir>
472 </_ToPublishDllCandidate>
475 If this target becomes reliable, we could start calling directly in msbuild and define these
478 @(PortableFileToConvert)
479 * ItemSpec: The DLL file associated with a Portable PDB to convert.
480 * PdbPath: The path to the Portable PDB file to convert.
481 * TargetPath: The output path for the generated Windows PDB. Full filename.
483 <PortableFileToConvert Include="@(_ToPublishDllCandidate)"
484 Condition="Exists('%(Identity)')">
485 <TargetPath>$(WindowsPdbConversionTargetPath)%(PdbRecursiveDir)%(Filename).pdb</TargetPath>
486 </PortableFileToConvert>
489 <ConvertPortablePdbsToWindowsPdbs Files="@(PortableFileToConvert)"
490 ConversionOptions="@(ConversionOptions)" />
494 Downloads and unzip symbol packages passed in as an ItemGroup
497 @(SymbolPackagesToDownload)
498 * An ItemGroup with the following characteristics.
499 * ItemSpec: The name of the package. (Not used within the target)
500 * Url [Required]: The url endpoint to download the package from.
501 * DestinationFile [Required]: The file name where the source will be downloaded to, must be a zip. i.e NugetId.symbols.nupkg.zip
502 * UnzipDestinationDir [Required]: This is the directory where the package contents will be extracted to.
503 $(SymbolPackagesDir) [optional]
504 * Location where the packages are going to be downloaded to as a cache. If empty, then will be the working directory.
507 @(SymbolPackagesDownloaded)
508 * ItemSpec: The full path to the downloaded file.
509 Includes the same metadata that was passed in @(SymbolPackagesToDownload)
510 If this itemgroup is empty the task failed to download the files.
512 <Target Name="DownloadAndUnzipSymbolPackage"
513 Condition="'@(SymbolPackagesToDownload)' != ''">
515 <DownloadFilesFromUrl Items="@(SymbolPackagesToDownload)"
516 DestinationDir="$(SymbolPackagesDir)"
517 TreatErrorsAsWarnings="true">
518 <Output TaskParameter="FilesCreated" ItemName="SymbolPackagesDownloaded" />
519 </DownloadFilesFromUrl>
521 <ZipFileExtractToDirectory SourceArchive="%(SymbolPackagesDownloaded.Identity)"
522 DestinationDirectory="%(SymbolPackagesDownloaded.UnzipDestinationDir)"
523 OverwriteDestination="true"
524 Condition="'@(SymbolPackagesDownloaded)' != ''" />