コード例 #1
0
        /// <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);
        }
コード例 #2
0
        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();
                }
            }
        }
コード例 #3
0
ファイル: WebDownloader.cs プロジェクト: 40a/PowerShell
        /// <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;
        }
コード例 #4
0
        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);
            }
        }
コード例 #5
0
ファイル: WebDownloader.cs プロジェクト: 40a/PowerShell
        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;
            }
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
ファイル: ExePackageInstaller.cs プロジェクト: 40a/PowerShell
        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;
        }
コード例 #9
0
ファイル: ZipPackageInstaller.cs プロジェクト: 40a/PowerShell
        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;
        }