Skip to content

Commit

Permalink
Runner: fix startup task state setting for MSIX (#1181)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyoyuppe committed Jan 31, 2020
1 parent ca20343 commit aa714f7
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 22 deletions.
2 changes: 2 additions & 0 deletions src/common/common.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<AdditionalIncludeDirectories>inc;telemetry;..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -82,6 +83,7 @@
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalIncludeDirectories>inc;telemetry;..\..\deps\cpprestsdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand Down
69 changes: 65 additions & 4 deletions src/common/winstore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,70 @@

#include <appmodel.h>

bool running_as_packaged()
#include <winrt/Windows.ApplicationModel.h>

using winrt::Windows::ApplicationModel::StartupTask;

namespace
{
const wchar_t* STARTUP_TASKID = L"PowerToysStartupTaskID";
}

namespace winstore
{
UINT32 length = 0;
const auto rc = GetPackageFamilyName(GetCurrentProcess(), &length, nullptr);
return rc != APPMODEL_ERROR_NO_PACKAGE;
bool running_as_packaged()
{
UINT32 length = 0;
const auto rc = GetPackageFamilyName(GetCurrentProcess(), &length, nullptr);
return rc != APPMODEL_ERROR_NO_PACKAGE;
}

std::future<StartupTaskState> get_startup_task_status_async()
{
const auto startupTask = co_await StartupTask::GetAsync(STARTUP_TASKID);
co_return startupTask.State();
}

std::future<void> switch_startup_task_state_async(const bool enabled)
{
const auto startupTask = co_await StartupTask::GetAsync(STARTUP_TASKID);
enum class action
{
none,
enable,
disable,
} action_to_try = action::none;
switch (startupTask.State())
{
case StartupTaskState::Disabled:
if (enabled)
{
action_to_try = action::enable;
}
break;
case StartupTaskState::Enabled:
if (!enabled)
{
action_to_try = action::disable;
}
break;
}
try
{
switch (action_to_try)
{
case action::enable:
co_await startupTask.RequestEnableAsync();
break;
case action::disable:
startupTask.Disable();
break;
}
}
catch (...)
{
// We can't handle the error, in case we don't have a permission to change startup task state
}
}

}
14 changes: 13 additions & 1 deletion src/common/winstore.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
#pragma once

bool running_as_packaged();
#include <future>

#include <winrt/Windows.ApplicationModel.h>


namespace winstore
{
using winrt::Windows::ApplicationModel::StartupTaskState;

bool running_as_packaged();
std::future<void> switch_startup_task_state_async(const bool enabled);
std::future<StartupTaskState> get_startup_task_status_async();
}
60 changes: 50 additions & 10 deletions src/runner/general_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
static std::wstring settings_theme = L"system";
static bool run_as_elevated = false;

// TODO: add resource.rc for settings project and localize
namespace localized_strings
{
const std::wstring_view STARTUP_DISABLED_BY_POLICY = L"This setting has been disabled by your administrator.";
const std::wstring_view STARTUP_DISABLED_BY_USER = LR"(This setting has been disabled manually via <a href="https://ms_settings_startupapps" target="_blank">Startup Settings</a>.)";
}

json::JsonObject load_general_settings()
{
auto loaded = PTSettingsHelper::load_general_settings();
Expand All @@ -27,10 +34,36 @@ json::JsonObject get_general_settings()
{
json::JsonObject result;

const bool packaged = running_as_packaged();
const bool packaged = winstore::running_as_packaged();
result.SetNamedValue(L"packaged", json::value(packaged));

const bool startup = is_auto_start_task_active_for_this_user();
bool startup{};
if (winstore::running_as_packaged())
{
using namespace localized_strings;
const auto task_state = winstore::get_startup_task_status_async().get();
switch (task_state)
{
case winstore::StartupTaskState::Disabled:
startup = false;
break;
case winstore::StartupTaskState::Enabled:
startup = true;
break;
case winstore::StartupTaskState::DisabledByPolicy:
result.SetNamedValue(L"startup_disabled_reason", json::value(STARTUP_DISABLED_BY_POLICY));
startup = false;
break;
case winstore::StartupTaskState::DisabledByUser:
result.SetNamedValue(L"startup_disabled_reason", json::value(STARTUP_DISABLED_BY_USER));
startup = false;
break;
}
}
else
{
startup = is_auto_start_task_active_for_this_user();
}
result.SetNamedValue(L"startup", json::value(startup));

json::JsonObject enabled;
Expand All @@ -54,16 +87,23 @@ void apply_general_settings(const json::JsonObject& general_configs)
if (json::has(general_configs, L"startup", json::JsonValueType::Boolean))
{
const bool startup = general_configs.GetNamedBoolean(L"startup");
const bool current_startup = is_auto_start_task_active_for_this_user();
if (!running_as_packaged() && current_startup != startup)
if (winstore::running_as_packaged())
{
if (startup)
{
enable_auto_start_task_for_this_user();
}
else
winstore::switch_startup_task_state_async(startup).wait();
}
else
{
const bool current_startup = is_auto_start_task_active_for_this_user();
if (current_startup != startup)
{
disable_auto_start_task_for_this_user();
if (startup)
{
enable_auto_start_task_for_this_user();
}
else
{
disable_auto_start_task_for_this_user();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class BoolToggleSettingsControl extends BaseSettingsControl {
public render(): JSX.Element {
return (
<Toggle
disabled={this.props.disabled}
onChange={
(_event,_check) => {
this.setState( (prev_state:any) => ({
Expand Down
12 changes: 8 additions & 4 deletions src/settings-web/src/components/GeneralSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,18 @@ export class GeneralSettings extends React.Component <any, any> {
}
<Separator />
<Text variant='xLarge'>General</Text>
{!this.state.settings.general.packaged &&
(
<Stack>
{this.state.settings.general.startup_disabled_reason != null &&
<span style={{color:"#c50500"}} dangerouslySetInnerHTML={{__html: this.state.settings.general.startup_disabled_reason }} />
}
<Label>Run at Startup</Label>
<BoolToggleSettingsControl
setting={{display_name: 'Run at Startup', value: this.state.settings.general.startup}}
disabled={this.state.settings.general.startup_disabled_reason}
setting={{value: this.state.settings.general.startup}}
on_change={this.parent_on_change}
ref={(input) => {this.startup_reference=input;}}
/>
)}
</Stack>
<BoolToggleSettingsControl
setting={{display_name: 'Always run as administrator', value: this.state.settings.general.run_elevated}}
on_change={this.parent_on_change}
Expand Down
9 changes: 7 additions & 2 deletions src/settings/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,13 @@ void initialize_webview(int nShowCmd)

g_webview.NewWindowRequested([=](IWebViewControl sender_requester, WebViewControlNewWindowRequestedEventArgs args) {
// Open the requested link in the default browser registered in the Shell
int res = static_cast<int>(reinterpret_cast<uintptr_t>(ShellExecute(nullptr, L"open", args.Uri().AbsoluteUri().c_str(), nullptr, nullptr, SW_SHOWNORMAL)));
WINRT_VERIFY(res > 32);
using winrt::Windows::Foundation::Uri;
Uri uri = args.Uri();
// WebView doesn't let us to open ms-settings:protocol links directly, so we translate it
// from a https placeholder
if (uri.AbsoluteUri() == L"https://ms_settings_startupapps/")
uri = Uri{L"ms-settings:startupapps"};
winrt::Windows::System::Launcher::LaunchUriAsync(uri);
});

g_webview.ContentLoading([=](IWebViewControl sender, WebViewControlContentLoadingEventArgs const& args) {
Expand Down
2 changes: 1 addition & 1 deletion src/settings/settings-html/dist/bundle.js

Large diffs are not rendered by default.

0 comments on commit aa714f7

Please sign in to comment.