aboutsummaryrefslogtreecommitdiff
path: root/src/wix/WixToolset.Core.WindowsInstaller/CommandLine/ValidateSubcommand.cs
blob: 36ec0d2112fbc2b7a75db39aab23e6df8c30e71f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.

namespace WixToolset.Core.WindowsInstaller.CommandLine
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Threading;
    using System.Threading.Tasks;
    using WixToolset.Core.WindowsInstaller.Validate;
    using WixToolset.Data;
    using WixToolset.Data.WindowsInstaller;
    using WixToolset.Extensibility.Data;
    using WixToolset.Extensibility.Services;

    internal class ValidateSubcommand : WindowsInstallerSubcommandBase
    {
        public ValidateSubcommand(IServiceProvider serviceProvider)
        {
            this.Messaging = serviceProvider.GetService<IMessaging>();
            this.FileSystem = serviceProvider.GetService<IFileSystem>();
        }

        private IMessaging Messaging { get; }

        private IFileSystem FileSystem { get; }

        private string DatabasePath { get; set; }

        private string WixpdbPath { get; set; }

        private string IntermediateFolder { get; set; }

        private List<string> CubeFiles { get; } = new List<string>();

        private List<string> Ices { get; } = new List<string>();

        private List<string> SuppressIces { get; } = new List<string>();

        public override CommandLineHelp GetCommandLineHelp()
        {
            return new CommandLineHelp("Validates MSI database using standard or custom ICEs.", "msi validate [options] {inputfile.msi|inputfile.msm}", new[]
            {
                new CommandLineHelpSwitch("-cub", "Optional path to a custom validation .CUBe file."),
                new CommandLineHelpSwitch("-ice", "Validates only with the specified ICE. May be provided multiple times."),
                new CommandLineHelpSwitch("-intermediateFolder", "Optional working folder. If not specified %TMP% will be used."),
                new CommandLineHelpSwitch("-pdb", "Optional path to .wixpdb for source line information. If not provided, will check next to the input file."),
                new CommandLineHelpSwitch("-sice", "Suppresses an ICE validator."),
            });
        }

        public override Task<int> ExecuteAsync(CancellationToken cancellationToken)
        {
            WindowsInstallerData data = null;

            if (String.IsNullOrEmpty(this.DatabasePath))
            {
                this.Messaging.Write(ErrorMessages.FilePathRequired("input MSI or MSM database"));
            }
            else if (this.CubeFiles.Count == 0)
            {
                var ext = Path.GetExtension(this.DatabasePath);
                switch (ext.ToLowerInvariant())
                {
                    case ".msi":
                        this.CubeFiles.Add("darice.cub");
                        break;

                    case ".msm":
                        this.CubeFiles.Add("mergemod.cub");
                        break;

                    default:
                        this.Messaging.Write(WindowsInstallerBackendErrors.UnknownValidationTargetFileExtension(ext));
                        break;
                }
            }

            if (!this.Messaging.EncounteredError)
            {
                if (String.IsNullOrEmpty(this.WixpdbPath))
                {
                    this.WixpdbPath = Path.ChangeExtension(this.DatabasePath, ".wixpdb");
                }

                if (String.IsNullOrEmpty(this.IntermediateFolder))
                {
                    this.IntermediateFolder = Path.GetTempPath();
                }

                if (File.Exists(this.WixpdbPath))
                {
                    try
                    {
                        data = WindowsInstallerData.Load(this.WixpdbPath);
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        this.Messaging.Write(WindowsInstallerBackendErrors.InvalidWindowsInstallerWixpdbForValidation(this.WixpdbPath));
                    }
                }

                var command = new ValidateDatabaseCommand(this.Messaging, this.FileSystem, this.IntermediateFolder, this.DatabasePath, data, this.CubeFiles, this.Ices, this.SuppressIces);
                command.Execute();
            }

            return Task.FromResult(this.Messaging.LastErrorNumber);
        }

        public override bool TryParseArgument(ICommandLineParser parser, string argument)
        {
            if (parser.IsSwitch(argument))
            {
                var parameter = argument.Substring(1);
                switch (parameter.ToLowerInvariant())
                {
                    case "cub":
                        parser.GetNextArgumentOrError(argument, this.CubeFiles);
                        return true;

                    case "ice":
                        parser.GetNextArgumentOrError(argument, this.Ices);
                        return true;

                    case "intermediatefolder":
                        this.IntermediateFolder = parser.GetNextArgumentAsDirectoryOrError(argument);
                        return true;

                    case "pdb":
                        this.WixpdbPath = parser.GetNextArgumentAsFilePathOrError(argument, "wixpdb path");
                        return true;

                    case "sice":
                        parser.GetNextArgumentOrError(argument, this.SuppressIces);
                        return true;
                }
            }
            else if (String.IsNullOrEmpty(this.DatabasePath))
            {
                this.DatabasePath = argument;
                return true;
            }

            return false;
        }
    }
}