- 
                Notifications
    
You must be signed in to change notification settings  - Fork 395
 
Description
Describe the bug
I have this code in my WinUI3 C# app
public partial class App : Application
{
    protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
    {	
        // Other codes....
        AppActivationArguments activatedEventArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
        // Other codes....
    }
}I've installed my app for a Standard user account. My app offers protocol, file and launch activation kinds.
When my app detects certain files, it attempts to relaunch itself via administrator privilege using ActivateApplication, but then I get error in the code i showed you above.
A specified logon session does not exist. It may already have been terminated.
It's a COMException.
Here are my apps' files that provide more info:
- https://github.com/HotCakeX/Harden-Windows-Security/blob/47141a44663a30cb84bbd3526409da4a45aa6dc4/AppControl%20Manager/App.xaml_ACM.cs
 - https://github.com/HotCakeX/Harden-Windows-Security/blob/47141a44663a30cb84bbd3526409da4a45aa6dc4/Harden%20System%20Security/App.xaml_HSS.cs
 
Steps to reproduce the bug
// MIT License
//
// Copyright (c) 2023-Present - Violet Hansen - (aka HotCakeX on GitHub) - Email Address: [email protected]
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// See here for more information: https://github.com/HotCakeX/Harden-Windows-Security/blob/main/LICENSE
//
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using AppControlManager.Others;
using AppControlManager.Taskbar;
using AppControlManager.ViewModels;
using AppControlManager.WindowComponents;
using Microsoft.UI.Xaml;
using Microsoft.Windows.AppLifecycle;
using Windows.ApplicationModel.Activation;
using Windows.Storage;
namespace AppControlManager;
#pragma warning disable CA1515
// Any App Setting that is related to OnLaunched event is only used in this file.
public partial class App : Application
{
	private static string? _activationAction;
	private static string? _activationFilePath;
	private static bool _activationIsFileActivation;
	/// <summary>
	/// Invoked when the application is launched.
	/// </summary>
	/// <param name="args">Details about the launch request and process.</param>
	protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
	{
		// Register the Jump List tasks
		/*
		_ = Task.Run(async () =>
		{
			try
			{
				await Taskbar.JumpListMgr.RegisterJumpListTasksAsync();
			}
			catch (Exception ex)
			{
				Logger.Write(ex);
			}
		});
		*/
		// About single instancing: https://learn.microsoft.com/windows/apps/windows-app-sdk/migrate-to-windows-app-sdk/guides/applifecycle#single-instanced-apps
		// Determines whether the session must prompt for UAC to elevate or not
		bool requireAdminPrivilege = false;
		try
		{
			// https://learn.microsoft.com/windows/apps/windows-app-sdk/migrate-to-windows-app-sdk/guides/applifecycle#file-type-association
			AppActivationArguments activatedEventArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
			if (activatedEventArgs.Kind is ExtendedActivationKind.File)
			{
				Logger.Write(GlobalVars.GetStr("FileActivationDetectedMessage"));
				IFileActivatedEventArgs? fileActivatedArgs = activatedEventArgs.Data as IFileActivatedEventArgs;
				if (fileActivatedArgs is not null)
				{
					IReadOnlyList<IStorageItem>? incomingStorageItems = fileActivatedArgs.Files;
					if (incomingStorageItems is not null && incomingStorageItems.Count > 0)
					{
						foreach (IStorageItem item in incomingStorageItems)
						{
							if (item.Path is not null && File.Exists(item.Path))
							{
								// If the selected file is not accessible with the privileges the app is currently running with, prompt for elevation
								requireAdminPrivilege = !FileAccessCheck.IsFileAccessibleForWrite(item.Path);
								// Store ephemeral activation context
								_activationFilePath = item.Path;
								_activationIsFileActivation = true;
								// We can only process one XML/CIP file for now
								break;
							}
						}
					}
					else
					{
						Logger.Write(GlobalVars.GetStr("FileActivationNoObjectsMessage"));
					}
				}
				else
				{
					Logger.Write(GlobalVars.GetStr("FileActivationNoArgumentsMessage"));
				}
			}
			else if (activatedEventArgs.Kind is ExtendedActivationKind.Protocol)
			{
				ProtocolActivatedEventArgs? eventArgs = activatedEventArgs.Data as ProtocolActivatedEventArgs;
				string? protocolName = eventArgs?.Uri?.OriginalString;
				if (protocolName is not null)
				{
					Logger.Write($"Protocol Activation Detected: {protocolName}");
					Match match = Regex1().Match(protocolName);
					string? action = null;
					string? filePath = null;
					// Allow action-only or action+file.
					if (match.Success)
					{
						if (match.Groups[1].Success)
						{
							action = match.Groups[1].Value.Trim();
							if (!string.IsNullOrWhiteSpace(action))
							{
								Logger.Write($"Action: {action}");
								_activationAction = action;
								// Elevation policy for action-only operations
								if (!IsElevated &&
									(string.Equals(action, nameof(ViewModelBase.LaunchProtocolActions.DeployRMMAuditPolicy), StringComparison.OrdinalIgnoreCase) ||
									 string.Equals(action, nameof(ViewModelBase.LaunchProtocolActions.DeployRMMBlockPolicy), StringComparison.OrdinalIgnoreCase)))
								{
									requireAdminPrivilege = true;
								}
							}
						}
						if (match.Groups[2].Success)
						{
							filePath = match.Groups[2].Value;
							if (!string.IsNullOrWhiteSpace(filePath))
							{
								Logger.Write($"File Path: {filePath}");
								_activationFilePath = filePath;
							}
						}
					}
				}
			}
			else
			{
				Logger.Write($"ExtendedActivationKind: {activatedEventArgs.Kind}");
				/*
				Windows.ApplicationModel.Activation.LaunchActivatedEventArgs launchArgs = (Windows.ApplicationModel.Activation.LaunchActivatedEventArgs)activatedEventArgs.Data;
				string passed = launchArgs.Arguments;
				Logger.Write($"Arguments: {passed}");
				*/
				string[] possibleArgs = Environment.GetCommandLineArgs();
				// Look for our two keys
				string? actionArg = possibleArgs.FirstOrDefault(a => a.StartsWith("--action=", StringComparison.OrdinalIgnoreCase));
				string? fileArg = possibleArgs.FirstOrDefault(a => a.StartsWith("--file=", StringComparison.OrdinalIgnoreCase));
				// Action is mandatory
				if (actionArg is not null)
				{
					// Extract the action
					string action = actionArg["--action=".Length..].Trim();
					if (!string.IsNullOrWhiteSpace(action))
					{
						Logger.Write($"Parsed Action: {action}");
						_activationAction = action;
					}
					// File is optional
					if (fileArg is not null)
					{
						string filePath = fileArg["--file=".Length..].Trim('"');
						if (!string.IsNullOrWhiteSpace(filePath))
						{
							Logger.Write($"Parsed File: {filePath}");
							_activationFilePath = filePath;
							// If the selected file is not accessible with the privileges the app is currently running with, prompt for elevation
							requireAdminPrivilege = !FileAccessCheck.IsFileAccessibleForWrite(filePath);
						}
					}
					// Elevation policy for action-only operations
					if (!IsElevated &&
						(string.Equals(action, nameof(ViewModelBase.LaunchProtocolActions.DeployRMMAuditPolicy), StringComparison.OrdinalIgnoreCase) ||
						 string.Equals(action, nameof(ViewModelBase.LaunchProtocolActions.DeployRMMBlockPolicy), StringComparison.OrdinalIgnoreCase)))
					{
						requireAdminPrivilege = true;
					}
				}
			}
		}
		catch (Exception ex)
		{
			Logger.Write(ex);
		}
		// If the current session is not elevated and user configured the app to ask for elevation on startup
		// Also prompt for elevation whether or not prompt for elevation setting is on when user selects a file to open from file explorer that requires elevated permissions
		if (!IsElevated && Settings.PromptForElevationOnStartup || !IsElevated && requireAdminPrivilege)
		{
			// Build passthrough arguments.
			if (Relaunch.RelaunchAppElevated(AUMID, BuildRelaunchArguments()))
			{
				// Exit the process; the app was successfully relaunched elevated.
				Environment.Exit(0);
			}
			else if (requireAdminPrivilege)
			{
				Logger.Write(GlobalVars.GetStr("ElevationRequiredButDeniedMessage"));
				// Exit the process anyway since admin privileges were required but user didn't successfully elevate.
				Environment.Exit(0);
			}
			else
			{
				Logger.Write(GlobalVars.GetStr("ElevationDeniedMessage"));
			}
		}
		m_window = new MainWindow();
		MainWindowVM.SetCaptionButtonsFlowDirection(string.Equals(Settings.ApplicationGlobalFlowDirection, "LeftToRight", StringComparison.OrdinalIgnoreCase) ? FlowDirection.LeftToRight : FlowDirection.RightToLeft);
		NavigationService.RestoreWindowSize(m_window.AppWindow); // Restore window size on startup
		ViewModelProvider.NavigationService.mainWindowVM.OnIconsStylesChanged(Settings.IconsStyle); // Set the initial Icons styles based on the user's settings
		m_window.Closed += Window_Closed;  // Assign event handler for the window closed event
		m_window.Activate();
		// If the app was forcefully exited previously while there was a badge being displayed on the taskbar icon we have to remove it on app startup otherwise it will be there!
		Badge.ClearBadge();
		#region Initial navigation and file activation processing
		// Handle direct file activation
		if (_activationIsFileActivation && !string.IsNullOrWhiteSpace(_activationFilePath))
		{
			Logger.Write(string.Format(GlobalVars.GetStr("FileActivationLaunchMessage"), _activationFilePath));
			try
			{
				await ViewModelProvider.PolicyEditorVM.OpenInPolicyEditor(_activationFilePath);
			}
			catch (Exception ex)
			{
				Logger.Write(string.Format(GlobalVars.GetStr("PolicyEditorLaunchErrorMessage"), ex.Message));
				// Continue doing the normal navigation if there was a problem
				InitialNav();
			}
			finally
			{
				// Clear ephemeral file activation context
				_activationFilePath = null;
				_activationIsFileActivation = false;
			}
		}
		// If there is/was activation through protocol/CLI/context menu (action-based)
		else if (!string.IsNullOrWhiteSpace(_activationAction))
		{
			try
			{
				if (Enum.TryParse(_activationAction, true, out ViewModelBase.LaunchProtocolActions parsedAction))
				{
					switch (parsedAction)
					{
						case ViewModelBase.LaunchProtocolActions.PolicyEditor:
							{
								await ViewModelProvider.PolicyEditorVM.OpenInPolicyEditor(_activationFilePath);
								break;
							}
						case ViewModelBase.LaunchProtocolActions.FileSignature:
							{
								ViewFileCertificatesVM vm = ViewModelProvider.ViewFileCertificatesVM;
								await vm.OpenInViewFileCertificatesVM(_activationFilePath);
								break;
							}
						case ViewModelBase.LaunchProtocolActions.FileHashes:
							{
								GetCIHashesVM vm = ViewModelProvider.GetCIHashesVM;
								await vm.OpenInGetCIHashes(_activationFilePath);
								break;
							}
						case ViewModelBase.LaunchProtocolActions.DeployRMMAuditPolicy:
						case ViewModelBase.LaunchProtocolActions.DeployRMMBlockPolicy:
							{
								await ViewModelProvider.CreatePolicyVM.OpenInCreatePolicy(parsedAction);
								break;
							}
						default:
							{
								InitialNav();
								break;
							}
					}
				}
				else
				{
					InitialNav();
				}
			}
			catch (Exception ex)
			{
				Logger.Write(ex);
				// Continue doing the normal navigation if there was a problem
				InitialNav();
			}
			finally
			{
				// Clear ephemeral action context after it's been used
				_activationAction = null;
				_activationFilePath = null;
			}
		}
		else
		{
			InitialNav();
		}
		#endregion
		// If the user has enabled animated rainbow border for the app window, start it
		if (Settings.IsAnimatedRainbowEnabled)
		{
			CustomUIElements.AppWindowBorderCustomization.StartAnimatedFrame();
		}
		// If the user has set a custom color for the app window border, apply it
		else if (!string.IsNullOrEmpty(Settings.CustomAppWindowsBorder))
		{
			if (RGBHEX.ToRGB(Settings.CustomAppWindowsBorder, out byte r, out byte g, out byte b))
				CustomUIElements.AppWindowBorderCustomization.SetBorderColor(r, g, b);
		}
		// Startup update check
		AppUpdate.CheckAtStartup();
	}
	/// <summary>
	/// Group 1 = action (enum token)
	/// Group 2 (optional) = file path.
	/// </summary>
	/// <returns></returns>
	[GeneratedRegex(@"^appcontrol-manager:--action=([A-Za-z0-9]+)(?:--file=(.+))?$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)]
	private static partial Regex Regex1();
	/// <summary>
	/// Builds the argument string to pass to the elevated instance so that it can re-create the original launch intent without persisting anything.
	/// File activation is converted into a PolicyEditor action since the app only supports handling .CIP/XML files from File explorer at the moment.
	/// If in the future more file types are supported we can detect type based on file extenson and implement different behaviors.
	/// </summary>
	private static string? BuildRelaunchArguments()
	{
		List<string> parts = [];
		if (!string.IsNullOrWhiteSpace(_activationAction))
		{
			parts.Add($"--action={_activationAction}");
		}
		else if (_activationIsFileActivation && !string.IsNullOrWhiteSpace(_activationFilePath))
		{
			parts.Add("--action=PolicyEditor");
		}
		if (!string.IsNullOrWhiteSpace(_activationFilePath))
		{
			// Properly quote the file path for command line parsing (double embedded quotes if any).
			string safePath = _activationFilePath.Replace("\"", "\"\"");
			parts.Add($"--file=\"{safePath}\"");
		}
		if (parts.Count == 0)
		{
			return null;
		}
		StringBuilder builder = new();
		for (int i = 0; i < parts.Count; i++)
		{
			if (i > 0)
			{
				_ = builder.Append(' ');
			}
			_ = builder.Append(parts[i]);
		}
		return builder.ToString();
	}
}Expected behavior
Should allow me to call the
AppActivationArguments activatedEventArgs = AppInstance.GetCurrent().GetActivatedEventArgs();in the App class's protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) method so i can retrieve the arguments and set up my app accordingly, when my app is installed for Standard user account and then via file/launch/protocol activation it tries to relaunch itself to obtain administrator privilege.
Screenshots
No response
NuGet package version
Windows App SDK 1.8.2: 1.8.251003001
Packaging type
Packaged (MSIX)
Windows version
Windows 11 version 24H2 (26100, June 2025 Update)
IDE
Other, Visual Studio 2022-preview
Additional context
No response