2009-07-06 14 views

Respuesta

1

Además de la tarea de descarga web en el proyecto MSBuild Community Tasks, el paquete MSBuild Extension (versión actual: 4.x) tiene una clase WebClient que se puede usar para descargar un archivo. Puede descargar el paquete de extensión de MSBuild aquí:

Aquí es un ejemplo del uso del MSBuild Extension Pack 4 para descargar un archivo:

<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> 

Como mencionado en una respuesta diferente, WebClient no parece tener la capacidad de descargar de forma segura (contraseña de protección ed) servidor web.

10

Si está intentando descargar un archivo que requiere autenticación (como TFS Web o un servidor IIS conectado a un dominio), ni el MSBuild Extension Pack ni las tareas de comunidad de MSBuild parecen tener la capacidad de proporcionar un archivo. nombre de usuario o contraseña al servidor HTTP. En este caso, terminé escribiendo una tarea personalizada de MSBuild. Esto es lo que hice.

Seguí el consejo del usuario de Stack Overflow Doug, en su respuesta para Download a file which requires authentication using vb.net/c#?, en la que sugiere algún código para agregar a un método escrito por Tom Archer en el sitio web de Code Guru.

por lo que utiliza MS Visual Studio 2010 para crear un nuevo proyecto de C# con el siguiente código para crear un objetivo de MSBuild llamado Wget (código fuente completo se muestra):

// 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 esto en su lugar, puedo añadir la siguiente tarea a mi proyecto de MSBuild:

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

la tarea Wget descarga la página servida por mywebserver.com y lo guarda en un archivo en el directorio de trabajo actual como mydownloadedfile.html, utilizando el nombre de usuario "miusuario" y la contraseña "mi contraseña".

Sin embargo, para usar la tarea Wget MSBuild personalizada, debo decirle a MSBuild dónde encontrar el archivo de ensamblaje Wget (.dll). Esto se hace con el elemento de MSBuild:

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

Si usted desea conseguir la suposición, que incluso puede tener su proyecto MSBuild Wget antes de que se llama. Para ello, la construcción de la solución con la tarea <MSBuild Projects>, y la importación a la tarea <UsingTaks AssemblyFile>, algo como esto:

<!-- 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> 

Si usted no ha elaborado un MSBuild objetivo personalizado antes, no es demasiado difícil - una vez usted sabe lo básico.Mire el código C arriba, eche un vistazo a la documentación oficial de MSDN y busque en la web más ejemplos. Un buen punto de partida es:

+0

La descarga de la comunidad de communitytask ahora es compatible con la autenticación. – rasjani

25

En MSBuild 4.0 Puede utilizar las tareas en línea para evitar la necesidad de compilar y desplegar una tarea personalizada en un ensamblado independiente.

<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

Cuando lo leí por primera vez, no era obvio dónde colocar los dos elementos. Agregué sobre el que contiene mis archivos de proyecto y puse en . –

+0

Desafortunadamente, esto no funciona con la versión de núcleo de dotnet de MSBuild. – sakra

Cuestiones relacionadas