WPF - how to determine how the app was launched

Tim Cadieux 21 Reputation points
2021-01-13T15:39:40.447+00:00

I've never used a WPF project before. We're trying to determine, if in the

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
    }

Can we determine if the application was started by the user clicking on the Icon or if the application was started by a Task? I'm not sure where to start looking?

Any insight would be helpful, thank you.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,687 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Ken Tucker 5,846 Reputation points
    2021-01-15T11:16:58.717+00:00

    I would have the task pass in a command line parameter to tell you the app was started by the task

    https://www.wpf-tutorial.com/wpf-application/command-line-parameters/

    0 comments No comments

  2. Castorix31 82,121 Reputation points
    2021-01-15T11:54:02.83+00:00

    A way is to get the parent PID, with NtQueryInformationProcess then QueryFullProcessImageName to get the parent name

    I tested on Windows 10, I get :

    From Explorer : c:\windows\explorer.exe
    From Task Scheduler : c:\windows\system32\svchost.exe

    (must be executed with maximum authorizations with Task Scheduler, otherwise OpenProcess returns ACCESS_DENIED )

    int nStatus = STATUS_SUCCESS;
    PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION();
    nStatus = NtQueryInformationProcess(GetCurrentProcess(), PROCESSINFOCLASS.ProcessBasicInformation, pbi, (int)Marshal.SizeOf(pbi), null);
    if (nStatus == 0)
    {
        IntPtr hProcessForName = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, true, (uint)pbi.InheritedFromUniqueProcessId);
        if (hProcessForName != IntPtr.Zero)
        {
            uint nSize = 260;
            StringBuilder sProcessImageName = new StringBuilder((int)nSize);
            QueryFullProcessImageName(hProcessForName, 0, sProcessImageName, ref nSize);
            string sName = sProcessImageName.ToString();
            CloseHandle(hProcessForName);
            MessageBox.Show(sName, "Information");
        }
        else
        {
            int nError = Marshal.GetLastWin32Error();
            // ...
        }
    }
    

    Declarations (using System.Runtime.InteropServices;):

    public const int STATUS_SUCCESS = 0x0;
    
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern IntPtr GetCurrentProcess();
    
    public const int SYNCHRONIZE = 0x100000;
    public const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
    
    public const int PROCESS_VM_READ = (0x10);
    public const int PROCESS_VM_WRITE = (0x20);
    public const int PROCESS_DUP_HANDLE = (0x40);
    public const int PROCESS_CREATE_PROCESS = (0x80);
    public const int PROCESS_SET_QUOTA = (0x100);
    public const int PROCESS_SET_INFORMATION = (0x200);
    public const int PROCESS_QUERY_INFORMATION = (0x400);
    public const int PROCESS_SUSPEND_RESUME = (0x800);
    public const int PROCESS_QUERY_LIMITED_INFORMATION = (0x1000);
    public const int PROCESS_SET_LIMITED_INFORMATION = (0x2000);
    public const long PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFFF);
    
    [DllImport("Kernel32.dll", SetLastError = true)]
    public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
    
    [DllImport("Kernel32.dll", SetLastError = true)]
    public static extern bool CloseHandle(IntPtr hObject);
    
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool QueryFullProcessImageName(IntPtr hProcess, int dwFlags, StringBuilder lpExeName, ref uint lpdwSize);
    
    [DllImport("NtDll.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern int NtQueryInformationProcess(IntPtr ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PROCESS_BASIC_INFORMATION info, int ProcessInformationLength, int[] ReturnLength);
    
    public enum PROCESSINFOCLASS
    {
        ProcessBasicInformation,
        ProcessQuotaLimits,
        ProcessIoCounters,
        ProcessVmCounters,
        ProcessTimes,
        ProcessBasePriority,
        ProcessRaisePriority,
        ProcessDebugPort,
        ProcessExceptionPort,
        ProcessAccessToken,
        ProcessLdtInformation,
        ProcessLdtSize,
        ProcessDefaultHardErrorMode,
        ProcessIoPortHandlers,          // Note: this is kernel mode only
        ProcessPooledUsageAndLimits,
        ProcessWorkingSetWatch,
        ProcessUserModeIOPL,
        ProcessEnableAlignmentFaultFixup,
        ProcessPriorityClass,
        ProcessWx86Information,
        ProcessHandleCount,
        ProcessAffinityMask,
        ProcessPriorityBoost,
        ProcessDeviceMap,
        ProcessSessionInformation,
        ProcessForegroundInformation,
        ProcessWow64Information,
        ProcessImageFileName,
        ProcessLUIDDeviceMapsEnabled,
        ProcessBreakOnTermination,
        ProcessDebugObjectHandle,
        ProcessDebugFlags,
        ProcessHandleTracing,
        ProcessUnusedSpare1,
        ProcessExecuteFlags,
        ProcessResourceManagement,
        ProcessCookie,
        ProcessImageInformation,
        MaxProcessInfoClass             // MaxProcessInfoClass should always be the last enum
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public class PROCESS_BASIC_INFORMATION
    {
        public int ExitStatus = 0;
        public IntPtr PebBaseAddress = (IntPtr)0;
        public IntPtr AffinityMask = (IntPtr)0;
        public int BasePriority = 0;
        public IntPtr UniqueProcessId = (IntPtr)0;
        public IntPtr InheritedFromUniqueProcessId = (IntPtr)0;
    }
    
    0 comments No comments