2009-07-06 17 views

risposta

1

Oltre all'attività WebDownload nel progetto Attività comunità di MSBuild, il pacchetto di estensione MSBuild (versione corrente: 4.x) ha una classe WebClient che può essere utilizzata per scaricare un file. È possibile scaricare l'estensione pacchetto MSBuild qui:

Ecco un esempio di utilizzo del pacchetto MSBuild Extension 4 per scaricare un file:

<Project ToolsVersion="4.0" DefaultTargets="Default" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
<PropertyGroup> 
    <TPath>$(MSBuildProjectDirectory)\..\MSBuild.ExtensionPack.tasks</TPath> 
    <TPath Condition="Exists('$(MSBuildProjectDirectory)\..\..\Common\MSBuild.ExtensionPack.tasks')">$(MSBuildProjectDirectory)\..\..\Common\MSBuild.ExtensionPack.tasks</TPath> 
</PropertyGroup> 
<Import Project="$(TPath)"/> 
<Target Name="Default"> 
    <!-- Download a File--> 
    <MSBuild.ExtensionPack.Web.WebClient TaskAction="DownloadFile" Url="http://hlstiw.bay.livefilestore.com/y1p7GhsJWeF4ig_Yb-8QXeA1bL0nY_MdOGaRQ3opRZS0YVvfshMfoZYe_cb1wSzPhx4nL_yidkG8Ji9msjRcTt0ew/Team%20Build%202008%20DeskSheet%202.0.pdf?download" FileName="C:\TFS Build 2008 DeskSheet.pdf"/> 
    <!-- Get the contents of a Url--> 
    <MSBuild.ExtensionPack.Web.WebClient TaskAction="OpenRead" Url="http://www.msbuildextensionpack.com"> 
     <Output TaskParameter="Data" PropertyName="Out"/> 
    </MSBuild.ExtensionPack.Web.WebClient> 
    <Message Text="$(Out)"/> 
</Target> 

Come menzionato in una risposta diversa, WebClient non sembra avere la capacità di scaricare da un sicuro (proteggere con password ndr) server web.

10

Se si sta tentando di scaricare un file che richiede l'autenticazione (come TFS Web o un server IIS collegato a un dominio), né il pacchetto MSBuild Extension Pack né i task della community di MSBuild sembrano avere la capacità di fornire un nome utente o password per il server HTTP. In questo caso, ho finito per scrivere un'attività MSBuild personalizzata. Ecco cosa ho fatto.

Ho seguito il consiglio dell'utente Stack Overflow Doug, nella sua risposta per Download a file which requires authentication using vb.net/c#?, in cui suggerisce un codice da aggiungere a un metodo scritto da Tom Archer sul sito Web Code Guru.

così ho usato MS Visual Studio 2010 per creare un nuovo progetto C# con il seguente codice per creare un target di MSBuild nome Wget (il codice sorgente completo mostrato):

// Include references to the following frameworks in your solution: 
// - Microsoft.Build.Framework 
// - Microsoft.Build.Utilities.v4.0 
// - System 
// - System.Net 

using System; 
using System.Net; 
using System.IO; 

using Microsoft.Build.Framework; 
using Microsoft.Build.Utilities; 

namespace Wget 
{ 
    public class Wget: Task 
    { 
     [Required] 
     public String Address // HTTP address to access 
     { get; set; } 

     [Required] 
     public String LocalFilename // Local file to which the downloaded page will be saved 
     { get; set; } 

     public String Username // Credential for HTTP authentication 
     { get; set; } 

     public String Password // Credential for HTTP authentication 
     { get; set; } 

     public override bool Execute() 
     { 
      int read = DownloadFile(Address, LocalFilename, Username, Password); 

      Console.WriteLine("{0} bytes written", read); 

      return true; 
     } 

     public static int DownloadFile(String remoteFilename, String localFilename, String httpUsername, String httpPassword) 
     { 
      // Function will return the number of bytes processed 
      // to the caller. Initialize to 0 here. 
      int bytesProcessed = 0; 

      // Assign values to these objects here so that they can 
      // be referenced in the finally block 
      Stream remoteStream = null; 
      Stream localStream = null; 
      WebResponse response = null; 

      // Use a try/catch/finally block as both the WebRequest and Stream 
      // classes throw exceptions upon error 
      try 
      { 
       // Create a request for the specified remote file name 
       WebRequest request = WebRequest.Create(remoteFilename); 
       if (request != null) 
       { 
        // If a username or password have been given, use them 
        if (httpUsername.Length > 0 || httpPassword.Length > 0) 
        { 
         string username = httpUsername; 
         string password = httpPassword; 
         request.Credentials = new System.Net.NetworkCredential(username, password); 
        } 

        // Send the request to the server and retrieve the 
        // WebResponse object 
        response = request.GetResponse(); 
        if (response != null) 
        { 
         // Once the WebResponse object has been retrieved, 
         // get the stream object associated with the response's data 
         remoteStream = response.GetResponseStream(); 

         // Create the local file 
         localStream = File.Create(localFilename); 

         // Allocate a 1k buffer 
         byte[] buffer = new byte[1024]; 
         int bytesRead; 

         // Simple do/while loop to read from stream until 
         // no bytes are returned 
         do 
         { 
          // Read data (up to 1k) from the stream 
          bytesRead = remoteStream.Read(buffer, 0, buffer.Length); 

          // Write the data to the local file 
          localStream.Write(buffer, 0, bytesRead); 

          // Increment total bytes processed 
          bytesProcessed += bytesRead; 
         } while (bytesRead > 0); 
        } 
       } 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.Message); 
      } 
      finally 
      { 
       // Close the response and streams objects here 
       // to make sure they're closed even if an exception 
       // is thrown at some point 
       if (response != null) response.Close(); 
       if (remoteStream != null) remoteStream.Close(); 
       if (localStream != null) localStream.Close(); 
      } 

      // Return total bytes processed to caller. 
      return bytesProcessed; 
     } 
    } 
} 

Con questo in luogo, posso aggiungere il seguente compito al mio progetto MSBuild:

<!-- Get the contents of a Url--> 
<Wget 
    Address="http://mywebserver.com/securepage" 
    LocalFilename="mydownloadedfile.html" 
    Username="myusername" 
    Password="mypassword"> 
</Wget> 

il compito Wget scarica la pagina servita da mywebserver.com e lo salva in un file nella directory di lavoro corrente come mydownloadedfile.html, utilizzando il nome utente "myusername" e la password "la mia password".

Tuttavia, per utilizzare l'attività Wget MSBuild personalizzata, devo dire a MSBuild dove trovare il file di assieme Wget (.dll). Questo viene fatto con l'elemento di MSBuild:

<!-- Import your custom MSBuild task --> 
<UsingTask AssemblyFile="MyCustomMSBuildTasks\Wget\bin\Release\Wget.dll" TaskName="Wget" /> 

Se si desidera ottenere fantasia, si può anche avere il vostro progetto MSBuild costruire Wget prima si chiama. Per fare questo, costruire la soluzione con il compito <MSBuild Projects>, e importarlo con il compito <UsingTaks AssemblyFile>, qualcosa di simile:

<!-- Build the custom MSBuild target solution--> 
<MSBuild Projects="MyCustomMSBuildTasks\CustomBuildTasks.sln" Properties="Configuration=Release" /> 

<!-- Import your custom MSBuild task --> 
<UsingTask AssemblyFile="MyCustomMSBuildTasks\Wget\bin\Release\Wget.dll" TaskName="Wget" /> 

<!-- Get the contents of a Url--> 
<Wget 
    Address="http://mywebserver.com/securepage" 
    LocalFilename="mydownloadedfile.html" 
    Username="myusername" 
    Password="mypassword"> 
</Wget> 

Se non hai mai creato un target di MSBuild personalizzato prima, non è troppo difficile - una volta conosci le basi.Guarda il codice C# sopra, dai un'occhiata alla documentazione ufficiale di MSDN e cerca sul web altri esempi. Un buon punto di partenza è:

+0

WebDownload di communitytask ora supporta l'autenticazione. – rasjani

25

In MSBuild 4.0 è possibile utilizzare le attività in linea al fine di evitare la necessità di compilare e distribuire un compito personalizzato in un assembly separato.

<UsingTask TaskName="DownloadFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> 
    <ParameterGroup> 
     <Address ParameterType="System.String" Required="true"/> 
     <FileName ParameterType="System.String" Required="true" /> 
    </ParameterGroup> 
    <Task> 
     <Reference Include="System" /> 
     <Code Type="Fragment" Language="cs"> 
     <![CDATA[ 
      new System.Net.WebClient().DownloadFile(Address, FileName); 
     ]]> 
     </Code> 
    </Task> 
    </UsingTask> 

    <Target Name="DownloadSomething"> 
    <DownloadFile Address="http://somewebsite/remotefile" FileName="localfilepath" /> 
    </Target> 
+1

Quando ho letto per la prima volta non era ovvio dove mettere i due elementi. Ho aggiunto sopra il contenente i miei file di progetto e ho messo in . –

+0

Sfortunatamente questo non funziona con la versione core dotnet di MSBuild. – sakra

Problemi correlati