/// <summary> /// Download data from remote via uri query. /// </summary> /// <param name="fileName">A file to store the downloaded data.</param> /// <param name="query">Uri query</param> /// <param name="request">An object passed in from the PackageManagement platform that contains APIs that can be used to interact with it </param> /// <param name="networkCredential">Credential to pass along to get httpclient</param> /// <param name="progressTracker">Utility class to help track progress</param> /// <returns></returns> internal static async Task <long> DownloadDataToFileAsync(string fileName, string query, PackageSourceListRequest request, NetworkCredential networkCredential, ProgressTracker progressTracker) { request.Verbose(Resources.Messages.DownloadingPackage, query); // try downloading for 3 times int remainingTry = 3; long totalDownloaded = 0; CancellationTokenSource cts; Stream input = null; FileStream output = null; while (remainingTry > 0) { // if user cancel the request, no need to do anything if (request.IsCanceled) { break; } input = null; output = null; cts = new CancellationTokenSource(); totalDownloaded = 0; try { // decrease try by 1 remainingTry -= 1; var httpClient = request.Client; httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "text/html; charset=iso-8859-1"); input = await httpClient.GetStreamAsync(query); // buffer size of 64 KB, this seems to be preferable buffer size, not too small and not too big byte[] bytes = new byte[1024 * 64]; output = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read); int current = 0; // here we read content that we got from the http response stream into the bytes array current = await input.ReadAsync(bytes, 0, bytes.Length, cts.Token); int progressPercentage = progressTracker.StartPercent; // report initial progress request.Progress(progressTracker.ProgressID, progressPercentage, Resources.Messages.BytesRead, current); int i = progressTracker.StartPercent; while (current > 0) { totalDownloaded += current; // here we write out the bytes array into the file await output.WriteAsync(bytes, 0, current, cts.Token); // report the progress request.Progress(progressTracker.ProgressID, progressPercentage < progressTracker.EndPercent?progressPercentage++:progressTracker.EndPercent, Resources.Messages.BytesRead, totalDownloaded); // continue reading from the stream current = await input.ReadAsync(bytes, 0, bytes.Length, cts.Token); } if (totalDownloaded > 0) { // report that we finished the download request.Progress(progressTracker.ProgressID, progressTracker.EndPercent, Resources.Messages.BytesRead, totalDownloaded); request.CompleteProgress(progressTracker.ProgressID, true); return(totalDownloaded); } // if request is canceled, don't retry if (request.IsCanceled) { return(0); } } catch (Exception ex) { request.CompleteProgress(progressTracker.ProgressID, true); request.Verbose(ex.Message); request.Debug(ex.StackTrace); } finally { // dispose input and output stream if (input != null) { input.Dispose(); } // dispose it if (output != null) { output.Dispose(); } // delete the file if created and nothing has downloaded if (totalDownloaded == 0 && File.Exists(fileName)) { fileName.TryHardToDelete(); } if (cts != null) { cts.Dispose(); } } // we have to retry again request.Verbose(Resources.Messages.RetryingDownload, query, remainingTry); } return(totalDownloaded); }
internal static bool InstallExePackage(PackageJson package, string fastPath, PackageSourceListRequest request) { ProgressTracker tracker = new ProgressTracker(request.StartProgress(0, Resources.Messages.Installing)); var providerType = package.Type.ToLowerInvariant(); var exePackage = Path.ChangeExtension(Path.GetTempFileName(), providerType); if (!string.IsNullOrWhiteSpace(package.Destination)) { request.Verbose(Resources.Messages.DestinationNotSupported, package.Type); } try { WebDownloader.DownloadFile(package.Source, exePackage, request, tracker); if (File.Exists(exePackage)) { request.Verbose("Package: '{0}'", exePackage); // validate the file if (!WebDownloader.VerifyHash(exePackage, package, request)) { return(false); } if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source)) { request.Warning(Constants.Messages.UserDeclinedUntrustedPackageInstall, package.Name); return(false); } // Prepare the process to run var processArguments = string.IsNullOrWhiteSpace(package.InstallArguments) ? "/VERYSILENT /CLOSEAPPLICATIONS /NORESTART /NOCANCEL /SP /qn" : package.InstallArguments; var start = new ProcessStartInfo { FileName = exePackage, Arguments = processArguments, UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, //LoadUserProfile = true, }; double percent = tracker.StartPercent; Timer timer = null; object timerLock = new object(); bool cleanUp = false; Action cleanUpAction = () => { lock (timerLock) { // check whether clean up is already done before or not if (!cleanUp) { try { if (timer != null) { // stop timer timer.Change(Timeout.Infinite, Timeout.Infinite); // dispose it timer.Dispose(); } } catch { } cleanUp = true; } } }; // Run the external process & wait for it to finish using (var proc = Process.Start(start)) { var timer1 = timer; timer = new Timer(_ => { percent += 0.025; // percent between startProgress and endProgress var progressPercent = tracker.ConvertPercentToProgress(percent); if (progressPercent < 90) { request.Progress(tracker.ProgressID, (int)progressPercent, Resources.Messages.InstallingPackage, package.Source); } if (request.IsCanceled) { cleanUpAction(); } }, null, 100, 3000); proc.WaitForExit(); // Retrieve the app's exit code var exitCode = proc.ExitCode; if (exitCode != 0) { request.WriteError(ErrorCategory.InvalidOperation, fastPath, Resources.Messages.InstallFailed, package.Name, proc.StandardError.ReadToEnd()); request.CompleteProgress(tracker.ProgressID, false); return(false); } else { request.CompleteProgress(tracker.ProgressID, true); request.YieldFromSwidtag(package, fastPath); request.Verbose(Resources.Messages.SuccessfullyInstalled, package.Name); } cleanUpAction(); } return(true); } else { request.WriteError(ErrorCategory.InvalidOperation, Constants.ProviderName, Resources.Messages.FailedToDownload, Constants.ProviderName, package.Source); } return(false); } catch (Exception ex) { request.Error(ErrorCategory.InvalidOperation, "install-package", ex.Message); ex.Dump(request); return(false); } finally { if (File.Exists(exePackage)) { exePackage.TryHardToDelete(); } } }
/// <summary> /// Download data from remote via uri query. /// </summary> /// <param name="fileName">A file to store the downloaded data.</param> /// <param name="query">Uri query</param> /// <param name="request">An object passed in from the PackageManagement platform that contains APIs that can be used to interact with it </param> /// <param name="networkCredential">Credential to pass along to get httpclient</param> /// <param name="progressTracker">Utility class to help track progress</param> /// <returns></returns> internal static async Task<long> DownloadDataToFileAsync(string fileName, string query, PackageSourceListRequest request, NetworkCredential networkCredential, ProgressTracker progressTracker) { request.Verbose(Resources.Messages.DownloadingPackage, query); // try downloading for 3 times int remainingTry = 3; long totalDownloaded = 0; CancellationTokenSource cts; Stream input = null; FileStream output = null; while (remainingTry > 0) { // if user cancel the request, no need to do anything if (request.IsCanceled) { break; } input = null; output = null; cts = new CancellationTokenSource(); totalDownloaded = 0; try { // decrease try by 1 remainingTry -= 1; var httpClient = request.Client; httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "text/html; charset=iso-8859-1"); input = await httpClient.GetStreamAsync(query); // buffer size of 64 KB, this seems to be preferable buffer size, not too small and not too big byte[] bytes = new byte[1024 * 64]; output = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read); int current = 0; // here we read content that we got from the http response stream into the bytes array current = await input.ReadAsync(bytes, 0, bytes.Length, cts.Token); int progressPercentage = progressTracker.StartPercent; // report initial progress request.Progress(progressTracker.ProgressID, progressPercentage, Resources.Messages.BytesRead, current); int i = progressTracker.StartPercent; while (current > 0) { totalDownloaded += current; // here we write out the bytes array into the file await output.WriteAsync(bytes, 0, current, cts.Token); // report the progress request.Progress(progressTracker.ProgressID, progressPercentage<progressTracker.EndPercent?progressPercentage++:progressTracker.EndPercent, Resources.Messages.BytesRead, totalDownloaded); // continue reading from the stream current = await input.ReadAsync(bytes, 0, bytes.Length, cts.Token); } if (totalDownloaded > 0) { // report that we finished the download request.Progress(progressTracker.ProgressID, progressTracker.EndPercent, Resources.Messages.BytesRead, totalDownloaded); request.CompleteProgress(progressTracker.ProgressID, true); return totalDownloaded; } // if request is canceled, don't retry if (request.IsCanceled) { return 0; } } catch (Exception ex) { request.CompleteProgress(progressTracker.ProgressID, true); request.Verbose(ex.Message); request.Debug(ex.StackTrace); } finally { // dispose input and output stream if (input != null) { input.Dispose(); } // dispose it if (output != null) { output.Dispose(); } // delete the file if created and nothing has downloaded if (totalDownloaded == 0 && File.Exists(fileName)) { fileName.TryHardToDelete(); } if (cts != null) { cts.Dispose(); } } // we have to retry again request.Verbose(Resources.Messages.RetryingDownload, query, remainingTry); } return totalDownloaded; }
internal static string DownloadFile(string queryUrl, string destination, PackageSourceListRequest request, ProgressTracker progressTracker) { try { request.Debug(Resources.Messages.DebugInfoCallMethod, Constants.ProviderName, string.Format(System.Globalization.CultureInfo.InvariantCulture, "DownloadFile - url='{0}', destination='{1}'", queryUrl, destination)); if (string.IsNullOrWhiteSpace(destination)) { throw new ArgumentNullException("destination"); } // make sure that the parent folder is created first. var folder = Path.GetDirectoryName(destination); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } if (File.Exists(destination)) { destination.TryHardToDelete(); } if (progressTracker == null) { progressTracker = new ProgressTracker(request.StartProgress(0, Resources.Messages.DownloadingPackage, queryUrl)); } Uri uri; if (!Uri.TryCreate(queryUrl, UriKind.Absolute, out uri)) { request.Error(Internal.ErrorCategory.InvalidOperation, Resources.Messages.UnsupportedUriFormat, Constants.ProviderName, queryUrl); return(null); } if (uri.IsFile) { // downloading from a file share using (var input = File.OpenRead(queryUrl)) { using (var output = new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.Read)) { request.Progress(progressTracker.ProgressID, progressTracker.StartPercent, Resources.Messages.Downloading); input.CopyTo(output); } } request.CompleteProgress(progressTracker.ProgressID, true); } else { //Downloading from url var result = DownloadDataToFileAsync(destination, queryUrl, request, PathUtility.GetNetworkCredential(request.CredentialUsername, request.CredentialPassword), progressTracker).Result; } if (File.Exists(destination)) { request.Verbose(Resources.Messages.CompletedDownload, queryUrl); return(destination); } else { request.Error(Internal.ErrorCategory.InvalidOperation, Resources.Messages.FailedToDownload, Constants.ProviderName, queryUrl, destination); return(null); } } catch (Exception ex) { ex.Dump(request); request.Warning(ex.Message); return(null); } }
internal static string DownloadFile(string queryUrl, string destination, PackageSourceListRequest request, ProgressTracker progressTracker) { try { request.Debug(Resources.Messages.DebugInfoCallMethod, Constants.ProviderName, string.Format(System.Globalization.CultureInfo.InvariantCulture, "DownloadFile - url='{0}', destination='{1}'", queryUrl, destination)); if (string.IsNullOrWhiteSpace(destination)) { throw new ArgumentNullException("destination"); } // make sure that the parent folder is created first. var folder = Path.GetDirectoryName(destination); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } if (File.Exists(destination)) { destination.TryHardToDelete(); } if (progressTracker == null) { progressTracker = new ProgressTracker(request.StartProgress(0, Resources.Messages.DownloadingPackage, queryUrl)); } Uri uri; if (!Uri.TryCreate(queryUrl, UriKind.Absolute, out uri)) { request.Error(Internal.ErrorCategory.InvalidOperation, Resources.Messages.UnsupportedUriFormat, Constants.ProviderName, queryUrl); return null; } if (uri.IsFile) { // downloading from a file share using (var input = File.OpenRead(queryUrl)) { using (var output = new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.Read)) { request.Progress(progressTracker.ProgressID, progressTracker.StartPercent, Resources.Messages.Downloading); input.CopyTo(output); } } request.CompleteProgress(progressTracker.ProgressID, true); } else { //Downloading from url var result = DownloadDataToFileAsync(destination, queryUrl, request, PathUtility.GetNetworkCredential(request.CredentialUsername, request.CredentialPassword), progressTracker).Result; } if (File.Exists(destination)) { request.Verbose(Resources.Messages.CompletedDownload, queryUrl); return destination; } else { request.Error(Internal.ErrorCategory.InvalidOperation, Resources.Messages.FailedToDownload, Constants.ProviderName, queryUrl, destination); return null; } } catch (Exception ex) { ex.Dump(request); request.Warning(ex.Message); return null; } }
internal static bool InstallZipPackage(PackageJson package, string fastPath, PackageSourceListRequest request) { if (request.RemoveFromPath.Value) { request.Warning(Resources.Messages.AddOrRemovePath, Constants.ProviderName, "RemoveFromPath", "Uninstall-Package"); } // download the exe package var providerType = package.Type.ToLowerInvariant(); var file = Path.ChangeExtension(Path.GetTempFileName(), providerType); if (string.IsNullOrWhiteSpace(package.Destination)) { request.Error(ErrorCategory.InvalidOperation, Constants.ProviderName, Resources.Messages.DestinationRequired); return(false); } WebDownloader.DownloadFile(package.Source, file, request, null); if (!File.Exists(file)) { return(false); } // validate the file if (!WebDownloader.VerifyHash(file, package, request)) { file.TryHardToDelete(); return(false); } if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source)) { request.Warning(Constants.Messages.UserDeclinedUntrustedPackageInstall, package.Name); file.TryHardToDelete(); return(false); } Timer timer = null; object timerLock = new object(); bool cleanUp = false; ProgressTracker tracker = new ProgressTracker(request.StartProgress(0, "Installing Zip Package............")); double percent = tracker.StartPercent; Action cleanUpAction = () => { lock (timerLock) { // check whether clean up is already done before or not if (!cleanUp) { try { if (timer != null) { // stop timer timer.Change(Timeout.Infinite, Timeout.Infinite); timer.Dispose(); timer = null; } } catch { } cleanUp = true; } } }; // extracted folder string extractedFolder = string.Concat(file.GenerateTemporaryFilename()); var versionFolder = ""; try { timer = new Timer(_ => { percent += 0.025; var progressPercent = tracker.ConvertPercentToProgress(percent); if (progressPercent < 90) { request.Progress(tracker.ProgressID, (int)progressPercent, string.Format(CultureInfo.CurrentCulture, "Copying files ...")); } if (request.IsCanceled) { cleanUpAction(); } }, null, 0, 1000); //unzip the file ZipFile.ExtractToDirectory(file, extractedFolder); if (Directory.Exists(extractedFolder)) { versionFolder = Path.Combine(package.Destination, package.Name, package.Version); // create the directory version folder if not exist if (!Directory.Exists(versionFolder)) { Directory.CreateDirectory(versionFolder); } // The package will be installed to destination\packageName\version\ // However, a few packages have a package name as its top level folder after zip. // So the installed folder will look like this: // \destination\foobarPackage\1.0.1\foobarPackage // In this case we directly copy the files to \destination\foobarPackage\1.0.1. var extractedTopLevelFolder = Directory.EnumerateDirectories(extractedFolder, "*", SearchOption.TopDirectoryOnly); while (!Directory.GetFiles(extractedFolder).Any() && extractedTopLevelFolder.Count() == 1) { extractedFolder = extractedTopLevelFolder.FirstOrDefault(); //in case the zip contains version folder extractedTopLevelFolder = Directory.EnumerateDirectories(extractedFolder, "*", SearchOption.TopDirectoryOnly); } FileUtility.CopyDirectory(extractedFolder, versionFolder, true); request.YieldFromSwidtag(package, fastPath); request.Verbose(Resources.Messages.SuccessfullyInstalledToDestination, package.Name, package.Destination); AddEnvironmentVariable(request, versionFolder); return(true); } else { request.Warning("Failed to download a Zip package {0} from {1}", package.Name, package.Source); } } catch (Exception e) { request.Debug(e.StackTrace); if (e is System.UnauthorizedAccessException) { request.WriteError(ErrorCategory.InvalidOperation, package.Name, Resources.Messages.InstallFailed, package.Name, "UnauthorizedAccessException. The requested operation likely requires elevation, i.e., launch PowerShell as administer"); } else { request.WriteError(ErrorCategory.InvalidOperation, package.Name, Resources.Messages.InstallFailed, package.Name, e.Message); } if (!(e is UnauthorizedAccessException || e is IOException)) { // something wrong, delete the version folder versionFolder.TryHardToDelete(); } } finally { cleanUpAction(); file.TryHardToDelete(); extractedFolder.TryHardToDelete(); request.CompleteProgress(tracker.ProgressID, true); } return(false); }
internal static bool InstallZipPackage(PackageJson package, string fastPath, PackageSourceListRequest request) { // download the exe package var file = Path.ChangeExtension(Path.GetTempFileName(), "exe"); WebDownloader.DownloadFile(package.Source, file, request, null); if (!File.Exists(file)) { return(false); } // validate the file if (!WebDownloader.VerifyHash(file, package, request)) { return(false); } if (!package.IsTrustedSource) { if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source)) { request.Warning(Constants.Messages.UserDeclinedUntrustedPackageInstall, package.Name); return(false); } } Timer timer = null; object timerLock = new object(); bool cleanUp = false; ProgressTracker tracker = new ProgressTracker(request.StartProgress(0, "Installing Zip Package............")); double percent = tracker.StartPercent; Action cleanUpAction = () => { lock (timerLock) { // check whether clean up is already done before or not if (!cleanUp) { try { if (timer != null) { // stop timer timer.Change(Timeout.Infinite, Timeout.Infinite); timer.Dispose(); timer = null; } } catch { } cleanUp = true; } } }; // extracted folder string extractedFolder = string.Concat(file.GenerateTemporaryFilename()); try { timer = new Timer(_ => { percent += 0.025; var progressPercent = tracker.ConvertPercentToProgress(percent); if (progressPercent < 90) { request.Progress(tracker.ProgressID, (int)progressPercent, string.Format(CultureInfo.CurrentCulture, "Copying files ...")); } if (request.IsCanceled) { cleanUpAction(); } }, null, 0, 1000); //unzip the file ZipFile.ExtractToDirectory(file, extractedFolder); if (Directory.Exists(extractedFolder)) { var versionFolder = Path.Combine(package.Destination, package.Name, package.Version); // create the directory version folder if not exist if (!Directory.Exists(versionFolder)) { Directory.CreateDirectory(versionFolder); } try { FileUtility.CopyDirectory(extractedFolder, versionFolder, true); request.YieldFromSwidtag(package, fastPath); } catch (Exception e) { request.CompleteProgress(tracker.ProgressID, false); request.Debug(e.StackTrace); if (!(e is UnauthorizedAccessException || e is IOException)) { // something wrong, delete the version folder versionFolder.TryHardToDelete(); return(false); } } return(true); } else { request.Warning("Failed to download a Zip package {0} from {1}", package.Name, package.Source); } } finally { cleanUpAction(); file.TryHardToDelete(); extractedFolder.TryHardToDelete(); request.CompleteProgress(tracker.ProgressID, true); } return(false); }
internal static bool InstallExePackage(PackageJson package, string fastPath, PackageSourceListRequest request) { ProgressTracker tracker = new ProgressTracker(request.StartProgress(0, Resources.Messages.Installing)); var exePackage = Path.ChangeExtension(Path.GetTempFileName(), "exe"); WebDownloader.DownloadFile(package.Source, exePackage, request, tracker); if (File.Exists(exePackage)) { request.Verbose("Package: '{0}'", exePackage); // validate the file if (!WebDownloader.VerifyHash(exePackage,package, request)) { return false; } if (!package.IsTrustedSource) { if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source)) { request.Warning(Constants.Messages.UserDeclinedUntrustedPackageInstall, package.Name); return false; } } // Prepare the process to run var processArguments = string.IsNullOrWhiteSpace(package.InstallArguments) ? "/VERYSILENT /CLOSEAPPLICATIONS /NORESTART /NOCANCEL /SP /qn" : package.InstallArguments; var start = new ProcessStartInfo { FileName = exePackage, Arguments = processArguments, UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, //LoadUserProfile = true, }; double percent = tracker.StartPercent; Timer timer = null; object timerLock = new object(); bool cleanUp = false; Action cleanUpAction = () => { lock (timerLock) { // check whether clean up is already done before or not if (!cleanUp) { try { if (timer != null) { // stop timer timer.Change(Timeout.Infinite, Timeout.Infinite); // dispose it timer.Dispose(); } } catch { } cleanUp = true; } } }; // Run the external process & wait for it to finish using (var proc = Process.Start(start)) { var timer1 = timer; timer = new Timer(_ => { percent += 0.025; // percent between startProgress and endProgress var progressPercent = tracker.ConvertPercentToProgress(percent); if (progressPercent < 90) { request.Progress(tracker.ProgressID, (int)progressPercent, Resources.Messages.InstallingPackage, package.Source); } if (request.IsCanceled) { cleanUpAction(); } }, null, 100, 3000); proc.WaitForExit(); // Retrieve the app's exit code var exitCode = proc.ExitCode; if (exitCode != 0) { request.WriteError(ErrorCategory.InvalidOperation, fastPath, Resources.Messages.InstallFailed, package.Name, proc.StandardError.ReadToEnd()); request.CompleteProgress(tracker.ProgressID, false); return false; } else { request.CompleteProgress(tracker.ProgressID, true); request.YieldFromSwidtag(package, fastPath); request.Verbose(Resources.Messages.SuccessfullyInstalled, package.Name); } cleanUpAction(); } return true; } else { request.Error(ErrorCategory.InvalidOperation, Resources.Messages.FailedToDownload, Constants.ProviderName, package.Source, exePackage); } return false; }
internal static bool InstallZipPackage(PackageJson package, string fastPath, PackageSourceListRequest request) { // download the exe package var file = Path.ChangeExtension(Path.GetTempFileName(), "exe"); WebDownloader.DownloadFile(package.Source, file, request, null); if (!File.Exists(file)) { return false; } // validate the file if (!WebDownloader.VerifyHash(file, package,request)) { return false; } if (!package.IsTrustedSource) { if (!request.ShouldContinueWithUntrustedPackageSource(package.Name, package.Source)) { request.Warning(Constants.Messages.UserDeclinedUntrustedPackageInstall, package.Name); return false; } } Timer timer = null; object timerLock = new object(); bool cleanUp = false; ProgressTracker tracker = new ProgressTracker(request.StartProgress(0, "Installing Zip Package............")); double percent = tracker.StartPercent; Action cleanUpAction = () => { lock (timerLock) { // check whether clean up is already done before or not if (!cleanUp) { try { if (timer != null) { // stop timer timer.Change(Timeout.Infinite, Timeout.Infinite); timer.Dispose(); timer = null; } } catch { } cleanUp = true; } } }; // extracted folder string extractedFolder = string.Concat(file.GenerateTemporaryFilename()); try { timer = new Timer(_ => { percent += 0.025; var progressPercent = tracker.ConvertPercentToProgress(percent); if (progressPercent < 90) { request.Progress(tracker.ProgressID, (int)progressPercent, string.Format(CultureInfo.CurrentCulture, "Copying files ...")); } if (request.IsCanceled) { cleanUpAction(); } }, null, 0, 1000); //unzip the file ZipFile.ExtractToDirectory(file, extractedFolder); if (Directory.Exists(extractedFolder)) { var versionFolder = Path.Combine(package.Destination, package.Name, package.Version); // create the directory version folder if not exist if (!Directory.Exists(versionFolder)) { Directory.CreateDirectory(versionFolder); } try { FileUtility.CopyDirectory(extractedFolder, versionFolder, true); request.YieldFromSwidtag(package, fastPath); } catch (Exception e) { request.CompleteProgress(tracker.ProgressID, false); request.Debug(e.StackTrace); if (!(e is UnauthorizedAccessException || e is IOException)) { // something wrong, delete the version folder versionFolder.TryHardToDelete(); return false; } } return true; } else { request.Warning("Failed to download a Zip package {0} from {1}", package.Name, package.Source); } } finally { cleanUpAction(); file.TryHardToDelete(); extractedFolder.TryHardToDelete(); request.CompleteProgress(tracker.ProgressID, true); } return false; }