//// ===========================================================================================================
        //// Methods
        //// ===========================================================================================================

        /// <summary>
        /// Reads a value from the Windows registryKey.
        /// </summary>
        /// <typeparam name="T">The type of value that is read (<see cref="RegistryReadValueCommand{T}"/>).</typeparam>
        /// <param name="command">The command to execute.</param>
        /// <param name="logger">The logger to use.</param>
        /// <returns>A response indicating success and the read value, or failure with error details.</returns>
        public IServiceCommandResponse ExecuteRead <T>(RegistryReadValueCommand <T> command, ILogger logger)
        {
            Param.VerifyNotNull(command, nameof(command));
            Param.VerifyNotNull(logger, nameof(logger));

            ServiceCommandResponse response;

            try
            {
                var registryHive = (RegistryHive)Enum.Parse(typeof(RegistryHive), command.BaseKey.ToString());

                using (IWin32RegistryKey baseKey = _registry.OpenBaseKey(registryHive, RegistryView.Registry64))
                    using (IWin32RegistryKey subKey = baseKey.OpenSubKey(command.Key, writable: false))
                    {
                        object value = subKey?.GetValue(command.ValueName, command.DefaultValue) ?? command.DefaultValue;
                        response = ServiceCommandResponse.Create(command.CommandName, value);
                    }
            }
            catch (Exception e)
            {
                response = ServiceCommandResponse.CreateError(
                    command.CommandName,
                    ServiceErrorInfo.RegistryReadError(
                        RegistryPath.HiveToWin32Name(RegistryPath.BaseKeyToHive(command.BaseKey)),
                        command.Key,
                        command.ValueName,
                        e));
                logger.LogError(response.ErrorMessage);
            }

            return(response);
        }
Beispiel #2
0
        //// ===========================================================================================================
        //// Methods
        //// ===========================================================================================================

        public async Task <IServiceCommandResponse> SendCommandAsync(IServiceCommand command)
        {
            var valueSet = new ValueSet();

            command.SerializeToValueSet(valueSet);
            AppServiceResponse bridgeResponse = await _connection.SendMessageAsync(valueSet);

            AppServiceResponseStatus status = bridgeResponse.Status;

            IServiceCommandResponse response;

            if (status == AppServiceResponseStatus.Success)
            {
                if (!ServiceCommandResponse.TryDeserializeFromValueSet(
                        bridgeResponse.Message,
                        out response,
                        out IServiceCommandResponse errorResponse))
                {
                    response = errorResponse;
                }
            }
            else
            {
                response = ServiceCommandResponse.CreateError(command.CommandName,
                                                              ServiceErrorInfo.InternalError($"AppServiceConnection failed with status '{status}'"));
            }

            return(response);
        }
        public void TryDeserializeFromJsonString_should_deserialize_a_successful_response()
        {
            string json = $@"
{{
    {ParamName.CommandName}: ""{ServiceCommandName.RegistryReadIntValue}"",
    {ParamName.CommandResult}: 123,
    {ParamName.ErrorCode}: ""{ServiceCommandErrorCode.Success}"",
}}";

            ServiceCommandResponse.TryDeserializeFromJsonString(
                json,
                out IServiceCommandResponse response,
                out IServiceCommandResponse errorResponse)
            .Should()
            .BeTrue("because there are no errors in deserialization: {0}", errorResponse?.ToDebugString());

            response.Should().NotBeNull();
            errorResponse.Should().BeNull();

            response.CommandName.Should().Be(ServiceCommandName.RegistryReadIntValue);
            response.Result.Should().Be(123);
            response.ErrorCode.Should().Be(ServiceCommandErrorCode.Success);
            response.ErrorMessage.Should().BeNull();

            response.IsError.Should().BeFalse();
            response.IsSuccess.Should().BeTrue();
        }
        public void TryDeserializeFromJsonString_should_deserialize_an_error()
        {
            string json = $@"
{{
    {ParamName.CommandName}: ""{ServiceCommandName.RegistryReadIntValue}"",
    {ParamName.CommandResult}: null,
    {ParamName.ErrorCode}: ""{ServiceCommandErrorCode.InternalError}"",
    {ParamName.ErrorMessage}: ""Error"",
}}";

            ServiceCommandResponse.TryDeserializeFromJsonString(
                json,
                out IServiceCommandResponse response,
                out IServiceCommandResponse errorResponse)
            .Should()
            .BeTrue();

            response.Should().NotBeNull();
            errorResponse.Should().BeNull();

            response.CommandName.Should().Be(ServiceCommandName.RegistryReadIntValue);
            response.Result.Should().BeNull();
            response.ErrorCode.Should().Be(ServiceCommandErrorCode.InternalError);
            response.ErrorMessage.Should().Be("Error");

            response.IsError.Should().BeTrue();
            response.IsSuccess.Should().BeFalse();
        }
        public void TryDeserializeFromValueSet_should_deserialize_an_error()
        {
            var valueSet = new Dictionary <string, object>
            {
                [ParamName.CommandName.ToString()]   = ServiceCommandName.RegistryReadIntValue,
                [ParamName.CommandResult.ToString()] = null,
                [ParamName.ErrorCode.ToString()]     = ServiceCommandErrorCode.InternalError,
                [ParamName.ErrorMessage.ToString()]  = "Error",
            };

            ServiceCommandResponse.TryDeserializeFromValueSet(
                valueSet,
                out IServiceCommandResponse response,
                out IServiceCommandResponse errorResponse)
            .Should()
            .BeTrue();

            response.Should().NotBeNull();
            errorResponse.Should().BeNull();

            response.CommandName.Should().Be(ServiceCommandName.RegistryReadIntValue);
            response.Result.Should().BeNull();
            response.ErrorCode.Should().Be(ServiceCommandErrorCode.InternalError);
            response.ErrorMessage.Should().Be("Error");

            response.IsError.Should().BeTrue();
            response.IsSuccess.Should().BeFalse();
        }
        /// <summary>
        /// Writes a value to the Windows registryKey.
        /// </summary>
        /// <typeparam name="T">The type of value that is written (<see cref="RegistryReadValueCommand{T}"/>).</typeparam>
        /// <param name="command">The command to execute.</param>
        /// <param name="logger">The logger to use.</param>
        /// <returns>A response indicating success and the written value, or failure with error details.</returns>
        public IServiceCommandResponse ExecuteWrite <T>(RegistryWriteValueCommand <T> command, ILogger logger)
        {
            Param.VerifyNotNull(command, nameof(command));
            Param.VerifyNotNull(logger, nameof(logger));

            IServiceCommandResponse response;

            try
            {
                var registryHive = (RegistryHive)Enum.Parse(typeof(RegistryHive), command.BaseKey.ToString());

                using (IWin32RegistryKey baseKey = _registry.OpenBaseKey(registryHive, RegistryView.Registry64))
                    using (IWin32RegistryKey subKey = baseKey.CreateSubKey(command.Key, writable: true))
                    {
                        subKey.SetValue(command.ValueName, command.Value, TypeToRegistryValueKind(typeof(T)));
                        response = ServiceCommandResponse.Create(command.CommandName, command.Value);
                    }
            }
            catch (Exception e)
            {
                response = ServiceCommandResponse.CreateError(
                    command.CommandName,
                    ServiceErrorInfo.RegistryWriteError(
                        RegistryPath.HiveToWin32Name(RegistryPath.BaseKeyToHive(command.BaseKey)),
                        command.Key,
                        command.ValueName,
                        e));
                logger.LogError(response.ErrorMessage);
            }

            return(response);
        }
        public void Execute_should_run_an_EchoCommand()
        {
            var executor = new CommandExecutor(new NullLogger(), new FakeRegistry());

            executor.Execute(new EchoCommand("Test"))
            .Should()
            .BeEquivalentTo(ServiceCommandResponse.Create(ServiceCommandName.Echo, "Test"));
        }
        public void Execute_should_run_a_ShutdownServerCommand()
        {
            var executor = new CommandExecutor(new NullLogger(), new FakeRegistry());

            executor.Execute(new ShutdownServerCommand())
            .Should()
            .BeEquivalentTo(ServiceCommandResponse.Create(ServiceCommandName.ShutdownServer, true));
        }
        public void Create_should_store_the_properties()
        {
            var response = ServiceCommandResponse.Create(ServiceCommandName.RegistryReadIntValue, 10);

            response.CommandName.Should().Be(ServiceCommandName.RegistryReadIntValue);
            response.Result.Should().Be(10);
            response.ErrorCode.Should().Be(ServiceCommandErrorCode.Success);
            response.ErrorMessage.Should().BeNull();
        }
        public void Execute_should_run_a_RegistryWriteIntValueCommand()
        {
            var registry = new FakeRegistry();
            var executor = new CommandExecutor(new NullLogger(), registry);

            executor.Execute(new RegistryWriteIntValueCommand(RegistryBaseKey.CurrentUser, "SubKey", "IntValue", 123))
            .Should()
            .BeEquivalentTo(ServiceCommandResponse.Create(ServiceCommandName.RegistryWriteIntValue, 123));
        }
        public void Execute_should_run_a_RegistryWriteStringValueCommand()
        {
            var registry = new FakeRegistry(@"HKCU\SubKey\StringValue=""Here""");
            var executor = new CommandExecutor(new NullLogger(), registry);

            executor.Execute(
                new RegistryReadStringValueCommand(RegistryBaseKey.CurrentUser, "SubKey", "StringValue", null))
            .Should()
            .BeEquivalentTo(ServiceCommandResponse.Create(ServiceCommandName.RegistryReadStringValue, "Here"));
        }
        public void CreateError_from_exception_should_store_the_properties()
        {
            var response = ServiceCommandResponse.CreateError(
                ServiceCommandName.RegistryReadIntValue,
                new InvalidOperationException());

            response.CommandName.Should().Be(ServiceCommandName.RegistryReadIntValue);
            response.Result.Should().BeNull();
            response.ErrorCode.Should().Be(ServiceCommandErrorCode.InternalError);
            response.ErrorMessage.Should().NotBeNull();
        }
        public void SerializeToValueSet_should_add_all_of_the_parameters_except_ErrorMessage_when_successful()
        {
            var response = ServiceCommandResponse.Create(ServiceCommandName.RegistryReadIntValue, 123);
            var valueSet = new Dictionary <string, object>();

            response.SerializeToValueSet(valueSet);

            valueSet.Select(pair => ((ParamName)Enum.Parse(typeof(ParamName), pair.Key), pair.Value))
            .Should()
            .BeEquivalentTo(
                new (ParamName, object)[]
        public void CreateError_should_store_the_properties()
        {
            var response = ServiceCommandResponse.CreateError(
                ServiceCommandName.RegistryReadIntValue,
                ServiceErrorInfo.InternalError("message"));

            response.CommandName.Should().Be(ServiceCommandName.RegistryReadIntValue);
            response.Result.Should().BeNull();
            response.ErrorCode.Should().Be(ServiceCommandErrorCode.InternalError);
            response.ErrorMessage.Should().NotBeNull();
        }
        //// ===========================================================================================================
        //// Methods
        //// ===========================================================================================================

        public async Task <IServiceCommandResponse> SendCommandAsync(IServiceCommand command, ILogger logger)
        {
            // The path to the elevated app is a zero-byte executable EXE that facilitates the packaged app launch for
            // classic invokers – such as CMD or Process.Start.
            string localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
            string elevatedAppPath  = Path.Combine(
                localAppDataPath,
                "microsoft",
                "windowsapps",
                "ElevatedDesktopServicesApp.exe");

            string args = BuildArgs(command);

            var processStartInfo = new ProcessStartInfo
            {
                Arguments       = args,
                FileName        = elevatedAppPath,
                Verb            = "runas",
                UseShellExecute = true
            };

            int exitCode = 0;

            try
            {
                var elevatedProcess = Process.Start(processStartInfo);
                elevatedProcess?.WaitForExit(5000);
                exitCode = elevatedProcess?.ExitCode ?? 3;
            }
            catch (Exception e)
            {
                if (e.HResult == E_FAIL)
                {
                    // the user cancelled the elevated process
                    // by clicking "No" on the Windows elevation dialog
                    exitCode = 1;
                }

                logger.LogError($"Error starting elevated process: {e}");
            }

            ServiceCommandResponse response = exitCode == 0
                ? ServiceCommandResponse.Create(command.CommandName, 0)
                : ServiceCommandResponse.CreateError(
                command.CommandName,
                new InvalidOperationException($"Error starting elevated process: {exitCode}"));

            return(await Task.FromResult(response));
        }
        public IServiceCommandResponse Execute(IServiceCommand command)
        {
            IServiceCommandResponse response;

            _logger.LogDebug("Executing command: ", command.ToDebugString());
            switch (command)
            {
            case ShutdownServerCommand _:
                response = ServiceCommandResponse.Create(ServiceCommandName.ShutdownServer, true);
                break;

            case EchoCommand echoCommand:
                response = ServiceCommandResponse.Create(ServiceCommandName.Echo, echoCommand.EchoMessage);
                break;

            case RegistryReadIntValueCommand registryCommand:
                response = _registryExecutor.ExecuteRead(registryCommand, _logger);
                break;

            case RegistryReadStringValueCommand registryCommand:
                response = _registryExecutor.ExecuteRead(registryCommand, _logger);
                break;

            case RegistryWriteIntValueCommand registryCommand:
                response = _registryExecutor.ExecuteWrite(registryCommand, _logger);
                break;

            default:
                _logger.LogWarning("Unsupported command: ", command.CommandName);
                response = ServiceCommandResponse.CreateError(
                    command.CommandName,
                    ServiceErrorInfo.InternalError(
                        $"Command '{command.CommandName}' is not supported for execution in the elevated bridge application."));
                break;
            }

            return(response);
        }
        public void TryDeserializeFromValueSet_should_fail_if_missing_a_command_name()
        {
            var valueSet = new Dictionary <string, object>
            {
                [ParamName.CommandResult.ToString()] = 123,
                [ParamName.ErrorCode.ToString()]     = ServiceCommandErrorCode.Success,
            };

            ServiceCommandResponse.TryDeserializeFromValueSet(
                valueSet,
                out IServiceCommandResponse response,
                out IServiceCommandResponse errorResponse)
            .Should()
            .BeFalse();

            response.Should().BeNull();
            errorResponse.Should().NotBeNull();

            errorResponse.CommandName.Should().Be(ServiceCommandName.Unknown);
            errorResponse.Result.Should().BeNull();
            errorResponse.ErrorCode.Should().Be(ServiceCommandErrorCode.MissingRequiredMessageValue);
            errorResponse.ErrorMessage.Should().Contain(ParamName.CommandName.ToString());
        }
        public void TryDeserializeFromJsonString_should_fail_if_missing_a_command_name()
        {
            string json = $@"
{{
    {ParamName.CommandResult}: 123,
    {ParamName.ErrorCode}: ""{ServiceCommandErrorCode.Success}"",
}}";

            ServiceCommandResponse.TryDeserializeFromJsonString(
                json,
                out IServiceCommandResponse response,
                out IServiceCommandResponse errorResponse)
            .Should()
            .BeFalse();

            response.Should().BeNull();
            errorResponse.Should().NotBeNull();

            errorResponse.CommandName.Should().Be(ServiceCommandName.Unknown);
            errorResponse.Result.Should().BeNull();
            errorResponse.ErrorCode.Should().Be(ServiceCommandErrorCode.MissingRequiredMessageValue);
            errorResponse.ErrorMessage.Should().Contain(ParamName.CommandName.ToString());
        }
 public int IndexOf(ServiceCommandResponse value)
 {
     return a.IndexOf(value);
 }
 public bool Contains(ServiceCommandResponse value)
 {
     return a.Contains(value);
 }
 public int Add(ServiceCommandResponse value)
 {
     return a.Add(value);
 }
 public void Remove(ServiceCommandResponse value)
 {
     a.Remove(value);
 }
 public void Insert(int index, ServiceCommandResponse value)
 {
     a.Insert(index, value);
 }
                    private bool GetAllCommands(XmlNode tNode, BlackLight.Services.Modules.Help.Lists.CommandList TopList)
                    {
                        string tCmdName;
                        string tCmdValue = "";
                        string[] tCmdValues;
                        BlackLight.Services.Modules.Help.Lists.CommandList tCommands = new BlackLight.Services.Modules.Help.Lists.CommandList();
                        ServiceCommandResponse tCmd;
                        foreach (XmlNode tCommandNode in tNode)
                        {
                            if (tCommandNode.Attributes["name"] != null && tCommandNode.Attributes["name"].Value != "")
                            {
                                tCmdName = tCommandNode.Attributes["name"].Value;
                            }
                            else
                            {
                                MyBase.Core.SendLogMessage("Help", "GetAllCommands()", BlackLight.Services.Error.Errors.ERROR, "XML Data Corruption", "", "", "");
                                //MessageBox.Show("XML Data corruption");
                                return false;
                            }

                            if (tCommandNode["commands"] != null)
                            {
                                try
                                {
                                    GetAllCommands(tCommandNode["commands"], tCommands);
                                }
                                catch (Exception ex)
                                {
                                    MyBase.Core.SendLogMessage("Help", "GetAllCommands()", BlackLight.Services.Error.Errors.ERROR, "Exception", "", ex.Message, ex.StackTrace);
                                    //MessageBox.Show(ex.Message + " " + ex.StackTrace);
                                }
                            }
                            else
                            {
                                if (tCommandNode.InnerText != null&& tCommandNode.InnerText != "")
                                {
                                    tCmdValue = tCommandNode.InnerText.Trim();
                                }
                                else
                                {
                                    MyBase.Core.SendLogMessage("Help", "ModLoad", BlackLight.Services.Error.Errors.ERROR, "XML Data Corruption", "", "", "");
                                    //MessageBox.Show("XML Data corruption");
                                    return false;
                                }
                            }
                            tCmdValue = tCmdValue.Replace("  ", " ");
                            tCmdValue = tCmdValue.Replace("  ", " ");
                            tCmdValue = tCmdValue.Replace("`B", "");
                            tCmdValue = tCmdValue.Replace("`U", "");
                            tCmdValue = tCmdValue.Replace("\r\n", "\r");
                            tCmdValue = tCmdValue.Replace("\n", "\r");
                            tCmdValues = tCmdValue.Split('\r');
                            if (tCommands.Count == 0)
                            {
                                tCmd = new ServiceCommandResponse(tCmdName, tCmdValues, null);
                            }
                            else
                            {
                                tCmd = new ServiceCommandResponse(tCmdName, tCommands["help"].Value, tCommands);
                            }

                            TopList.Add(tCmd);
                        }
                        return true;
                    }