Maps command-lines to the best matching Command.
コード例 #1
0
        /// <summary>
        /// Collects data about well-known URL protocol handlers.
        /// </summary>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <param name="capabilities">The capability list to add the collected data to.</param>
        /// <exception cref="IOException">There was an error accessing the registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the registry was not permitted.</exception>
        public void CollectProtocolAssocs([NotNull] CommandMapper commandMapper, [NotNull] CapabilityList capabilities)
        {
            #region Sanity checks
            if (capabilities == null)
            {
                throw new ArgumentNullException(nameof(capabilities));
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException(nameof(commandMapper));
            }
            #endregion

            foreach (string protocol in ProtocolAssocs.Select(protocolAssoc => protocolAssoc.Key))
            {
                using (var protocolKey = Registry.ClassesRoot.OpenSubKey(protocol))
                {
                    if (protocolKey == null)
                    {
                        throw new IOException(protocol + " not found");
                    }
                    capabilities.Entries.Add(new UrlProtocol
                    {
                        ID           = protocol,
                        Descriptions = { RegistryUtils.GetString(@"HKEY_CLASSES_ROOT\" + protocol, valueName: null, defaultValue: protocol) },
                        Verbs        = { GetVerb(protocolKey, commandMapper, "open") }
                    });
                }
            }
        }
コード例 #2
0
        private static CapabilityList GetCapabilityList(CommandMapper commandMapper, SnapshotDiff diff)
        {
            var capabilities = new CapabilityList {
                OS = OS.Windows
            };
            string appName = null, appDescription = null;

            diff.CollectFileTypes(commandMapper, capabilities);
            diff.CollectContextMenus(commandMapper, capabilities);
            diff.CollectAutoPlays(commandMapper, capabilities);
            diff.CollectDefaultPrograms(commandMapper, capabilities, ref appName);

            var appRegistration = diff.GetAppRegistration(commandMapper, capabilities, ref appName, ref appDescription);

            if (appRegistration != null)
            {
                capabilities.Entries.Add(appRegistration);
            }
            else
            { // Only collect URL protocols if there wasn't already an application registration that covered them
                diff.CollectProtocolAssocs(commandMapper, capabilities);
            }

            return(capabilities);
        }
コード例 #3
0
        public void TestGetCommand()
        {
            var commandNoArgs = new Command {
                Name = "no-args", Path = "entry.exe"
            };
            var commandArgs1 = new Command {
                Name = "args1", Path = "entry.exe", Arguments = { "--arg1", "long argument" }
            };
            var commandArgs2 = new Command {
                Name = "args2", Path = "entry.exe", Arguments = { "--arg2", "long argument" }
            };
            var provider = new CommandMapper("installation directory", new[] { commandNoArgs, commandArgs1, commandArgs2 });

            string additionalArgs;

            Assert.AreSame(commandNoArgs, provider.GetCommand("installation directory" + Path.DirectorySeparatorChar + "entry.exe", out additionalArgs));
            Assert.AreEqual("", additionalArgs);

            Assert.AreSame(commandNoArgs, provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg1", out additionalArgs));
            Assert.AreEqual("--arg1", additionalArgs);

            Assert.AreSame(commandArgs1, provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg1 \"long argument\" bla", out additionalArgs));
            Assert.AreEqual("bla", additionalArgs);

            Assert.AreSame(commandArgs2, provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg2 \"long argument\" bla", out additionalArgs));
            Assert.AreEqual("bla", additionalArgs);

            Assert.IsNull(provider.GetCommand("Something" + Path.DirectorySeparatorChar + "else.exe", out additionalArgs));
        }
コード例 #4
0
        public void TestGetCommand()
        {
            var commandNoArgs = new Command {Name = "no-args", Path = "entry.exe"};
            var commandArgs1 = new Command {Name = "args1", Path = "entry.exe", Arguments = {"--arg1", "long argument"}};
            var commandArgs2 = new Command {Name = "args2", Path = "entry.exe", Arguments = {"--arg2", "long argument"}};
            var provider = new CommandMapper("installation directory", new[] {commandNoArgs, commandArgs1, commandArgs2});

            string additionalArgs;

            provider.GetCommand("installation directory" + Path.DirectorySeparatorChar + "entry.exe", out additionalArgs)
                .Should().BeSameAs(commandNoArgs);
            additionalArgs.Should().Be("");

            provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg1", out additionalArgs)
                .Should().BeSameAs(commandNoArgs);
            additionalArgs.Should().Be("--arg1");

            provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg1 \"long argument\" bla", out additionalArgs)
                .Should().BeSameAs(commandArgs1);
            additionalArgs.Should().Be("bla");

            provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg2 \"long argument\" bla", out additionalArgs)
                .Should().BeSameAs(commandArgs2);
            additionalArgs.Should().Be("bla");

            provider.GetCommand("Something" + Path.DirectorySeparatorChar + "else.exe", out additionalArgs)
                .Should().BeNull();
        }
コード例 #5
0
        public void TestGetCommand()
        {
            var commandNoArgs = new Command {
                Name = "no-args", Path = "entry.exe"
            };
            var commandArgs1 = new Command {
                Name = "args1", Path = "entry.exe", Arguments = { "--arg1", "long argument" }
            };
            var commandArgs2 = new Command {
                Name = "args2", Path = "entry.exe", Arguments = { "--arg2", "long argument" }
            };
            var provider = new CommandMapper("installation directory", new[] { commandNoArgs, commandArgs1, commandArgs2 });

            string additionalArgs;

            provider.GetCommand("installation directory" + Path.DirectorySeparatorChar + "entry.exe", out additionalArgs)
            .Should().BeSameAs(commandNoArgs);
            additionalArgs.Should().Be("");

            provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg1", out additionalArgs)
            .Should().BeSameAs(commandNoArgs);
            additionalArgs.Should().Be("--arg1");

            provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg1 \"long argument\" bla", out additionalArgs)
            .Should().BeSameAs(commandArgs1);
            additionalArgs.Should().Be("bla");

            provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg2 \"long argument\" bla", out additionalArgs)
            .Should().BeSameAs(commandArgs2);
            additionalArgs.Should().Be("bla");

            provider.GetCommand("Something" + Path.DirectorySeparatorChar + "else.exe", out additionalArgs)
            .Should().BeNull();
        }
コード例 #6
0
        private static Verb GetVerb([NotNull] RegistryKey typeKey, [NotNull] CommandMapper commandMapper, [NotNull] string verbName)
        {
            #region Sanity checks
            if (typeKey == null)
            {
                throw new ArgumentNullException("typeKey");
            }
            if (string.IsNullOrEmpty(verbName))
            {
                throw new ArgumentNullException("verbName");
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException("commandMapper");
            }
            #endregion

            using (var verbKey = typeKey.OpenSubKey(@"shell\" + verbName))
            {
                if (verbKey == null)
                {
                    return(null);
                }

                string description = verbKey.GetValue("", "").ToString();
                string commandLine;
                using (var commandKey = verbKey.OpenSubKey("command"))
                {
                    if (commandKey == null)
                    {
                        return(null);
                    }
                    commandLine = commandKey.GetValue("", "").ToString();
                }

                string additionalArgs;
                var    command = commandMapper.GetCommand(commandLine, out additionalArgs);
                if (command == null)
                {
                    return(null);
                }
                string commandName = command.Name;

                if (commandName == Command.NameRun)
                {
                    commandName = null;
                }
                var verb = new Verb
                {
                    Name      = verbName,
                    Command   = commandName,
                    Arguments = additionalArgs
                };
                if (!string.IsNullOrEmpty(description))
                {
                    verb.Descriptions.Add(description);
                }
                return(verb);
            }
        }
コード例 #7
0
        /// <summary>
        /// Collects data about URL protocol handlers indicated by registered application capabilities.
        /// </summary>
        /// <param name="capsKey">A registry key containing capability information for a registered application.</param>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <param name="capabilities">The capability list to add the collected data to.</param>
        /// <exception cref="IOException">There was an error accessing the registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the registry was not permitted.</exception>
        private static void CollectProtocolAssocsEx(RegistryKey capsKey, CommandMapper commandMapper, CapabilityList capabilities)
        {
            #region Sanity checks
            if (capsKey == null)
            {
                throw new ArgumentNullException(nameof(capsKey));
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException(nameof(commandMapper));
            }
            if (capabilities == null)
            {
                throw new ArgumentNullException(nameof(capabilities));
            }
            #endregion

            using var urlAssocKey = capsKey.OpenSubKey(DesktopIntegration.Windows.AppRegistration.RegSubKeyUrlAssocs);
            if (urlAssocKey == null)
            {
                return;
            }

            foreach (string protocol in urlAssocKey.GetValueNames())
            {
                string progID = urlAssocKey.GetValue(protocol)?.ToString();
                if (string.IsNullOrEmpty(progID))
                {
                    continue;
                }
                using var progIDKey = Registry.ClassesRoot.OpenSubKey(progID);
                if (progIDKey == null)
                {
                    continue;
                }

                var prefix = new KnownProtocolPrefix {
                    Value = protocol
                };
                var existing = capabilities.GetCapability <UrlProtocol>(progID);
                if (existing == null)
                {
                    var capability = new UrlProtocol
                    {
                        ID            = progID,
                        Descriptions  = { progIDKey.GetValue("", defaultValue: "").ToString() },
                        KnownPrefixes = { prefix }
                    };
                    capability.Verbs.AddRange(GetVerbs(progIDKey, commandMapper));
                    capabilities.Entries.Add(capability);
                }
                else
                {
                    existing.KnownPrefixes.Add(prefix);
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Retrieves data about a verb (an executable command) from the registry.
        /// </summary>
        /// <param name="typeKey">The registry key containing information about the file type / protocol the verb belongs to.</param>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <param name="verbName">The internal name of the verb.</param>
        /// <returns>The detected <see cref="Verb"/> or an empty <see cref="Verb"/> if no match was found.</returns>
        private static Verb?GetVerb(RegistryKey typeKey, CommandMapper commandMapper, string verbName)
        {
            #region Sanity checks
            if (typeKey == null)
            {
                throw new ArgumentNullException(nameof(typeKey));
            }
            if (string.IsNullOrEmpty(verbName))
            {
                throw new ArgumentNullException(nameof(verbName));
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException(nameof(commandMapper));
            }
            #endregion

            using var verbKey = typeKey.OpenSubKey(@"shell\" + verbName);
            if (verbKey == null)
            {
                return(null);
            }

            string description = verbKey.GetValue("")?.ToString();
            string commandLine;
            using (var commandKey = verbKey.OpenSubKey("command"))
            {
                if (commandKey == null)
                {
                    return(null);
                }
                commandLine = commandKey.GetValue("")?.ToString();
            }

            if (string.IsNullOrEmpty(commandLine))
            {
                return(null);
            }
            var command = commandMapper.GetCommand(commandLine, out string additionalArgs);
            if (command == null)
            {
                return(null);
            }

            var verb = new Verb
            {
                Name             = verbName,
                Command          = (command.Name == Command.NameRun) ? null : command.Name,
                ArgumentsLiteral = additionalArgs
            };
            if (!string.IsNullOrEmpty(description))
            {
                verb.Descriptions.Add(description);
            }
            return(verb);
        }
コード例 #9
0
        /// <summary>
        /// Retrieves data about registered applications.
        /// </summary>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <param name="capabilities">The capability list to add the collected data to.</param>
        /// <param name="appName">Is set to the name of the application as displayed to the user; unchanged if the name was not found.</param>
        /// <param name="appDescription">Is set to a user-friendly description of the application; unchanged if the name was not found.</param>
        /// <exception cref="IOException">There was an error accessing the registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the registry was not permitted.</exception>
        public AppRegistration GetAppRegistration([NotNull] CommandMapper commandMapper, [NotNull] CapabilityList capabilities, ref string appName, ref string appDescription)
        {
            #region Sanity checks
            if (capabilities == null)
            {
                throw new ArgumentNullException("capabilities");
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException("commandMapper");
            }
            #endregion

            // Ambiguity warnings
            if (RegisteredApplications.Length == 0)
            {
                return(null);
            }
            if (RegisteredApplications.Length > 1)
            {
                Log.Warn(Resources.MultipleRegisteredAppsDetected);
            }

            // Get registry path pointer
            string appRegName          = RegisteredApplications[0];
            var    capabilitiesRegPath = RegistryUtils.GetString(@"HKEY_LOCAL_MACHINE\" + DesktopIntegration.Windows.AppRegistration.RegKeyMachineRegisteredApplications, appRegName);
            if (string.IsNullOrEmpty(capabilitiesRegPath))
            {
                return(null);
            }

            bool x64;
            using (var capsKey = RegistryUtils.OpenHklmKey(capabilitiesRegPath, out x64))
            {
                if (string.IsNullOrEmpty(appName))
                {
                    appName = capsKey.GetValue(DesktopIntegration.Windows.AppRegistration.RegValueAppName, "").ToString();
                }
                if (string.IsNullOrEmpty(appDescription))
                {
                    appDescription = capsKey.GetValue(DesktopIntegration.Windows.AppRegistration.RegValueAppDescription, "").ToString();
                }

                CollectProtocolAssocsEx(capsKey, commandMapper, capabilities);
                CollectFileAssocsEx(capsKey, capabilities);
                // Note: Contenders for StartMenu entries are detected elsewhere

                return(new AppRegistration
                {
                    ID = appRegName,
                    CapabilityRegPath = capabilitiesRegPath,
                    X64 = x64
                });
            }
        }
コード例 #10
0
        /// <summary>
        /// Finishes the capture process after <see cref="Diff"/> has been called an <see cref="FeedBuilder.MainCandidate"/> has been set.
        /// </summary>
        /// <exception cref="InvalidOperationException"><see cref="Diff"/> was not called or <see cref="FeedBuilder.MainCandidate"/> is not set.</exception>
        /// <exception cref="IOException">There was an error accessing the registry or file system.</exception>
        /// <exception cref="UnauthorizedAccessException">Access to the registry or file system was not permitted.</exception>
        public void Finish()
        {
            if (_diff == null || InstallationDir == null)
            {
                throw new InvalidOperationException("Diff() must be called first.");
            }

            _feedBuilder.GenerateCommands();

            var commandMapper = new CommandMapper(InstallationDir, _feedBuilder.Commands);

            _feedBuilder.CapabilityList = GetCapabilityList(commandMapper, _diff);
        }
コード例 #11
0
        /// <summary>
        /// Collects data about default programs.
        /// </summary>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <param name="capabilities">The capability list to add the collected data to.</param>
        /// <param name="appName">Is set to the name of the application as displayed to the user; unchanged if the name was not found.</param>
        /// <exception cref="IOException">There was an error accessing the registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the registry was not permitted.</exception>
        public void CollectDefaultPrograms([NotNull] CommandMapper commandMapper, [NotNull] CapabilityList capabilities, ref string appName)
        {
            #region Sanity checks
            if (capabilities == null)
            {
                throw new ArgumentNullException(nameof(capabilities));
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException(nameof(commandMapper));
            }
            #endregion

            // Ambiguity warnings
            if (ServiceAssocs.Length > 1)
            {
                Log.Warn(Resources.MultipleDefaultProgramsDetected);
            }

            foreach (var serviceAssoc in ServiceAssocs)
            {
                string service = serviceAssoc.Key;
                string client  = serviceAssoc.Value;

                using (var clientKey = Registry.LocalMachine.OpenSubKey(DesktopIntegration.Windows.DefaultProgram.RegKeyMachineClients + @"\" + service + @"\" + client))
                {
                    if (clientKey == null)
                    {
                        continue;
                    }

                    if (string.IsNullOrEmpty(appName))
                    {
                        appName = clientKey.GetValue("", "").ToString();
                    }
                    if (string.IsNullOrEmpty(appName))
                    {
                        appName = clientKey.GetValue(DesktopIntegration.Windows.DefaultProgram.RegValueLocalizedName, "").ToString();
                    }

                    var defaultProgram = new DefaultProgram
                    {
                        ID      = client,
                        Service = service
                    };
                    defaultProgram.Verbs.AddRange(GetVerbs(clientKey, commandMapper));
                    defaultProgram.InstallCommands = GetInstallCommands(clientKey, commandMapper.InstallationDir);
                    capabilities.Entries.Add(defaultProgram);
                }
            }
        }
コード例 #12
0
        /// <summary>
        /// Collects data about URL protocol handlers indicated by registered application capabilities.
        /// </summary>
        /// <param name="capsKey">A registry key containing capability information for a registered application.</param>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <param name="capabilities">The capability list to add the collected data to.</param>
        /// <exception cref="IOException">There was an error accessing the registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the registry was not permitted.</exception>
        private static void CollectProtocolAssocsEx([NotNull] RegistryKey capsKey, [NotNull] CommandMapper commandMapper, [NotNull] CapabilityList capabilities)
        {
            #region Sanity checks
            if (capsKey == null)
            {
                throw new ArgumentNullException("capsKey");
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException("commandMapper");
            }
            if (capabilities == null)
            {
                throw new ArgumentNullException("capabilities");
            }
            #endregion

            using (var urlAssocKey = capsKey.OpenSubKey(DesktopIntegration.Windows.AppRegistration.RegSubKeyUrlAssocs))
            {
                if (urlAssocKey == null)
                {
                    return;
                }

                // TODO: Fold multiple prefixes pointing to one protocol together
                foreach (string protocol in urlAssocKey.GetValueNames())
                {
                    string progID = urlAssocKey.GetValue(protocol, "").ToString();
                    using (var progIDKey = Registry.ClassesRoot.OpenSubKey(progID))
                    {
                        if (progIDKey == null)
                        {
                            continue;
                        }

                        var capability = new UrlProtocol
                        {
                            ID            = progID,
                            Descriptions  = { progIDKey.GetValue("", "").ToString() },
                            KnownPrefixes = { new KnownProtocolPrefix {
                                                  Value = protocol
                                              } }
                        };

                        capability.Verbs.AddRange(GetVerbs(progIDKey, commandMapper));
                        capabilities.Entries.Add(capability);
                    }
                }
            }
        }
コード例 #13
0
        /// <summary>
        /// Retrieves data about multiple verbs (executable commands) from the registry.
        /// </summary>
        /// <param name="typeKey">The registry key containing information about the file type / protocol the verbs belong to.</param>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <returns>A list of detected <see cref="Verb"/>.</returns>
        private static IEnumerable <Verb> GetVerbs(RegistryKey typeKey, CommandMapper commandMapper)
        {
            #region Sanity checks
            if (typeKey == null)
            {
                throw new ArgumentNullException(nameof(typeKey));
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException(nameof(commandMapper));
            }
            #endregion

            return(RegUtils.GetSubKeyNames(typeKey, "shell").Select(verbName => GetVerb(typeKey, commandMapper, verbName)).WhereNotNull());
        }
コード例 #14
0
        /// <summary>
        /// Collects data about file types and also URL protocol handlers.
        /// </summary>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <param name="capabilities">The capability list to add the collected data to.</param>
        /// <exception cref="IOException">There was an error accessing the registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the registry was not permitted.</exception>
        public void CollectFileTypes(CommandMapper commandMapper, CapabilityList capabilities)
        {
            #region Sanity checks
            if (capabilities == null)
            {
                throw new ArgumentNullException(nameof(capabilities));
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException(nameof(commandMapper));
            }
            #endregion

            capabilities.Entries.AddRange((
                                              from progID in ProgIDs
                                              where !string.IsNullOrEmpty(progID)
                                              select GetFileType(progID, commandMapper)).WhereNotNull());
        }
コード例 #15
0
        /// <summary>
        /// Collects data about AutoPlay handlers.
        /// </summary>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <param name="capabilities">The capability list to add the collected data to.</param>
        /// <exception cref="IOException">There was an error accessing the registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the registry was not permitted.</exception>
        public void CollectAutoPlays([NotNull] CommandMapper commandMapper, [NotNull] CapabilityList capabilities)
        {
            #region Sanity checks
            if (capabilities == null)
            {
                throw new ArgumentNullException(nameof(capabilities));
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException(nameof(commandMapper));
            }
            #endregion

            capabilities.Entries.AddRange(AutoPlayHandlersUser
                                          .Select(handler => GetAutoPlay(handler, Registry.CurrentUser, AutoPlayAssocsUser, commandMapper))
                                          .WhereNotNull());

            capabilities.Entries.AddRange(AutoPlayHandlersMachine
                                          .Select(handler => GetAutoPlay(handler, Registry.LocalMachine, AutoPlayAssocsMachine, commandMapper))
                                          .WhereNotNull());
        }
コード例 #16
0
        public void TestGetCommand()
        {
            var commandNoArgs = new Command {Name = "no-args", Path = "entry.exe"};
            var commandArgs1 = new Command {Name = "args1", Path = "entry.exe", Arguments = {"--arg1", "long argument"}};
            var commandArgs2 = new Command {Name = "args2", Path = "entry.exe", Arguments = {"--arg2", "long argument"}};
            var provider = new CommandMapper("installation directory", new[] {commandNoArgs, commandArgs1, commandArgs2});

            string additionalArgs;

            Assert.AreSame(commandNoArgs, provider.GetCommand("installation directory" + Path.DirectorySeparatorChar + "entry.exe", out additionalArgs));
            Assert.AreEqual("", additionalArgs);

            Assert.AreSame(commandNoArgs, provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg1", out additionalArgs));
            Assert.AreEqual("--arg1", additionalArgs);

            Assert.AreSame(commandArgs1, provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg1 \"long argument\" bla", out additionalArgs));
            Assert.AreEqual("bla", additionalArgs);

            Assert.AreSame(commandArgs2, provider.GetCommand("\"installation directory" + Path.DirectorySeparatorChar + "entry.exe\" --arg2 \"long argument\" bla", out additionalArgs));
            Assert.AreEqual("bla", additionalArgs);

            Assert.IsNull(provider.GetCommand("Something" + Path.DirectorySeparatorChar + "else.exe", out additionalArgs));
        }
コード例 #17
0
        /// <summary>
        /// Retrieves data about a specific file type or URL protocol from a snapshot diff.
        /// </summary>
        /// <param name="progID">The programmatic identifier of the file type.</param>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <returns>Data about the file type or <see paramref="null"/> if no file type for this <paramref name="progID"/> was detected.</returns>
        /// <exception cref="IOException">There was an error accessing the registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the registry was not permitted.</exception>
        private VerbCapability?GetFileType(string progID, CommandMapper commandMapper)
        {
            #region Sanity checks
            if (string.IsNullOrEmpty(progID))
            {
                throw new ArgumentNullException(nameof(progID));
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException(nameof(commandMapper));
            }
            #endregion

            using var progIDKey = Registry.ClassesRoot.OpenSubKey(progID);
            if (progIDKey == null)
            {
                return(null);
            }

            VerbCapability capability;
            if (progIDKey.GetValue(DesktopIntegration.Windows.UrlProtocol.ProtocolIndicator) == null)
            { // Normal file type
                var fileType = new FileType {
                    ID = progID
                };

                foreach (var fileAssoc in FileAssocs.Where(fileAssoc => fileAssoc.Value == progID && !string.IsNullOrEmpty(fileAssoc.Key)))
                {
                    using var assocKey = Registry.ClassesRoot.OpenSubKey(fileAssoc.Key);
                    if (assocKey == null)
                    {
                        continue;
                    }

                    fileType.Extensions.Add(new FileTypeExtension
                    {
                        Value         = fileAssoc.Key,
                        MimeType      = assocKey.GetValue(DesktopIntegration.Windows.FileType.RegValueContentType)?.ToString(),
                        PerceivedType = assocKey.GetValue(DesktopIntegration.Windows.FileType.RegValuePerceivedType)?.ToString()
                    });
                }

                capability = fileType;
            }
            else
            { // URL protocol handler
                capability = new UrlProtocol {
                    ID = progID
                };
            }

            var description = progIDKey.GetValue(DesktopIntegration.Windows.FileType.RegValueFriendlyName) ?? progIDKey.GetValue("");
            if (description != null)
            {
                capability.Descriptions.Add(description.ToString());
            }

            capability.Verbs.AddRange(GetVerbs(progIDKey, commandMapper));

            // Only return capabilities that have verbs associated with them
            return(capability.Verbs.Count == 0 ? null : capability);
        }
コード例 #18
0
        /// <summary>
        /// Finishes the capture process after <see cref="Diff"/> has been called an <see cref="FeedBuilder.MainCandidate"/> has been set.
        /// </summary>
        /// <exception cref="InvalidOperationException"><see cref="Diff"/> was not called or <see cref="FeedBuilder.MainCandidate"/> is not set.</exception>
        /// <exception cref="IOException">There was an error accessing the registry or file system.</exception>
        /// <exception cref="UnauthorizedAccessException">Access to the registry or file system was not permitted.</exception>
        public void Finish()
        {
            if (_diff == null || InstallationDir == null) throw new InvalidOperationException("Diff() must be called first.");

            _feedBuilder.GenerateCommands();

            var commandMapper = new CommandMapper(InstallationDir, _feedBuilder.Commands);
            _feedBuilder.CapabilityList = GetCapabilityList(commandMapper, _diff);
        }
コード例 #19
0
        private static CapabilityList GetCapabilityList(CommandMapper commandMapper, SnapshotDiff diff)
        {
            var capabilities = new CapabilityList {OS = OS.Windows};
            string appName = null, appDescription = null;

            diff.CollectFileTypes(commandMapper, capabilities);
            diff.CollectContextMenus(commandMapper, capabilities);
            diff.CollectAutoPlays(commandMapper, capabilities);
            diff.CollectDefaultPrograms(commandMapper, capabilities, ref appName);

            var appRegistration = diff.GetAppRegistration(commandMapper, capabilities, ref appName, ref appDescription);
            if (appRegistration != null) capabilities.Entries.Add(appRegistration);
            else
            { // Only collect URL protocols if there wasn't already an application registration that covered them
                diff.CollectProtocolAssocs(commandMapper, capabilities);
            }

            return capabilities;
        }
コード例 #20
0
        /// <summary>
        /// Collects data about context menu entries.
        /// </summary>
        /// <param name="commandMapper">Provides best-match command-line to <see cref="Command"/> mapping.</param>
        /// <param name="capabilities">The capability list to add the collected data to.</param>
        /// <exception cref="IOException">There was an error accessing the registry.</exception>
        /// <exception cref="UnauthorizedAccessException">Read access to the registry was not permitted.</exception>
        public void CollectContextMenus(CommandMapper commandMapper, CapabilityList capabilities)
        {
            #region Sanity checks
            if (capabilities == null)
            {
                throw new ArgumentNullException(nameof(capabilities));
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException(nameof(commandMapper));
            }
            #endregion

            using (var progIDKey = Registry.ClassesRoot.OpenSubKey(DesktopIntegration.Windows.ContextMenu.RegKeyClassesFiles))
            {
                if (progIDKey == null)
                {
                    throw new IOException("Registry key not found");
                }
                foreach (string entry in ContextMenuFiles)
                {
                    capabilities.Entries.Add(new ContextMenu
                    {
                        ID     = "files-" + entry,
                        Target = ContextMenuTarget.Files,
                        Verbs  = { GetVerb(progIDKey, commandMapper, entry) }
                    });
                }
            }

            using (var progIDKey = Registry.ClassesRoot.OpenSubKey(DesktopIntegration.Windows.ContextMenu.RegKeyClassesExecutableFiles[0]))
            {
                if (progIDKey == null)
                {
                    throw new IOException("Registry key not found");
                }
                foreach (string entry in ContextMenuExecutableFiles)
                {
                    capabilities.Entries.Add(new ContextMenu
                    {
                        ID     = "executable-files-" + entry,
                        Target = ContextMenuTarget.ExecutableFiles,
                        Verbs  = { GetVerb(progIDKey, commandMapper, entry) }
                    });
                }
            }

            using (var progIDKey = Registry.ClassesRoot.OpenSubKey(DesktopIntegration.Windows.ContextMenu.RegKeyClassesDirectories))
            {
                if (progIDKey == null)
                {
                    throw new IOException("Registry key not found");
                }
                foreach (string entry in ContextMenuDirectories)
                {
                    capabilities.Entries.Add(new ContextMenu
                    {
                        ID     = "directories-" + entry,
                        Target = ContextMenuTarget.Directories,
                        Verbs  = { GetVerb(progIDKey, commandMapper, entry) }
                    });
                }
            }

            using (var progIDKey = Registry.ClassesRoot.OpenSubKey(DesktopIntegration.Windows.ContextMenu.RegKeyClassesAll))
            {
                if (progIDKey == null)
                {
                    throw new IOException("Registry key not found");
                }
                foreach (string entry in ContextMenuAll)
                {
                    capabilities.Entries.Add(new ContextMenu
                    {
                        ID     = "all-" + entry,
                        Target = ContextMenuTarget.Directories,
                        Verbs  = { GetVerb(progIDKey, commandMapper, entry) }
                    });
                }
            }
        }
コード例 #21
0
        private static Capability GetAutoPlay([NotNull] string handler, [NotNull] RegistryKey hive, [NotNull, ItemNotNull] IEnumerable <ComparableTuple <string> > autoPlayAssocs, [NotNull] CommandMapper commandMapper)
        {
            #region Sanity checks
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }
            if (hive == null)
            {
                throw new ArgumentNullException(nameof(hive));
            }
            if (autoPlayAssocs == null)
            {
                throw new ArgumentNullException(nameof(autoPlayAssocs));
            }
            if (commandMapper == null)
            {
                throw new ArgumentNullException(nameof(commandMapper));
            }
            #endregion

            using (var handlerKey = hive.OpenSubKey(DesktopIntegration.Windows.AutoPlay.RegKeyHandlers + @"\" + handler))
            {
                if (handlerKey == null)
                {
                    return(null);
                }

                string progID   = handlerKey.GetValue(DesktopIntegration.Windows.AutoPlay.RegValueProgID, "").ToString();
                string verbName = handlerKey.GetValue(DesktopIntegration.Windows.AutoPlay.RegValueVerb, "").ToString();

                using (var progIDKey = Registry.ClassesRoot.OpenSubKey(progID))
                {
                    if (progIDKey == null)
                    {
                        throw new IOException(progID + " key not found");
                    }
                    var autoPlay = new AutoPlay
                    {
                        ID           = handler,
                        Provider     = handlerKey.GetValue(DesktopIntegration.Windows.AutoPlay.RegValueProvider, "").ToString(),
                        Descriptions = { handlerKey.GetValue(DesktopIntegration.Windows.AutoPlay.RegValueDescription, "").ToString() },
                        Verb         = GetVerb(progIDKey, commandMapper, verbName)
                    };

                    autoPlay.Events.AddRange(
                        from autoPlayAssoc in autoPlayAssocs
                        where autoPlayAssoc.Value == handler
                        select new AutoPlayEvent {
                        Name = autoPlayAssoc.Key
                    });

                    return(autoPlay);
                }
            }
        }