确定应用程序从哪个位置启动

时间:2017-09-07 07:28:19

标签: c# .net wpf process shortcut

是否有可能确定如何启动c#应用程序?

在我的情况下,我想检查此应用程序(wpf)是否由位于特定文件夹中的快捷方式启动。

因此,有两种方法可以打开我的应用程序

  • 使用直接快捷方式
  • 启动另一个类似于更新管理器的应用程序,以使我的应用程序保持最新状态。检查后,它使用Process.Start()
  • 启动我的应用程序

我想确保只能使用更新管理器启动应用程序。

3 个答案:

答案 0 :(得分:1)

如果只有两种启动应用的方法,第二种方法应该将参数(GUID?)传递给Process.Start() - 由更新程序应用生成。

也许设计一种允许应用程序仅使用令牌启动的算法。

答案 1 :(得分:1)

据我所知,这是不可能的,你想要它的方式,但你可以使用一个技巧。首先更改WPF应用程序的入口方法以获取命令行参数,并(例如)使用-u参数来区别于应用程序的启动位置。然后在-u之后,您可以传递HWND或与您的更新程序匹配的进程ID。当然,您必须检查该应用程序是否正在运行以及它是否是您的更新程序。

示例:

// updated process start
ProcessStartInfo psi = new ProcessStartInfo("your/WPF/application.exe");
psi.Arguments = "-u " + Process.GetCurrentProcess().Id;
// fill up rest of the properties you need 
Process.Start(psi);

// wpf application's entry point
void Main(string[] args)
{
    string updaterProcessIdstr = string.Empty;
    for (int i = 0; i < args.Length; i++)
    {
        if(args[i] == "-u")
        {
            updaterProcessIdstr = args[i + 1];
            i++;
        }
    }
    int pid = int.Parse(updaterProcessIdstr);
    Process updaterProcess = Process.GetProcessById(pid);
    // do some validation here
    // send something to stdin and read from stdout 
    // to determine if it was started from that updater.
}

答案 2 :(得分:1)

您可以使用的技巧是检查父ID的PID,然后获取父进程的一些信息。

如果父进程的名称类似于&#34; explorer.exe&#34;然后应用程序从快捷方式启动或直接在资源管理器上双击它。

否则,它是从另一个应用程序启动的:它可能是您的更新程序应用程序,它也可能是与更新程序应用程序同名的另一个应用程序...

这意味着您必须重新思考您希望获得此类解决方案的深度,以及您希望安全控制的深度。您可以将更新程序中的参数传递给主应用程序,或者使用令牌交换实现一些进程间通信......不可能建立100%安全的系统。

如上所述,这似乎是一个XY问题......或者可能不是。也许这只是一个安全问题。建议修改你的目标是什么。

如果您需要用于在.NET中检索进程信息的示例代码(通过使用System.Management),那么只需尝试下面列出的代码即可。您所要做的就是将其放在名为&#39; Updater&#39;的控制台应用程序项目中,并在代码中正确设置主应用程序的路径。

如果您通过在不同情况下启动和关闭 YourApplication.exe 来玩这个示例,那么您应该能够看到如下输出:

Parent process 'Updater.exe' [PID=5472]
Parent process 'explorer.exe' [PID=12052]

以下代码在VS2017 .Net 4.6.1上进行了测试

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;

class Program
{
    static void Main(string[] args)
    {
        Process.Start(new ProcessStartInfo()
        {
            FileName = "YourApplication.exe" // path to your application
        });

        while (Console.ReadKey(true).Key != ConsoleKey.Escape)
        {
            Process process = Process.GetProcessesByName("YourApplication").FirstOrDefault();  // your application's process name
            if (process == null)
            {
                Console.WriteLine($"Process is not running...");
                continue;
            }
            ProcessManager pm = ProcessManager.FromLocalMachine();
            var processProperties = pm.GetProcessProperties(process.Id);
            int parentProcessId = Convert.ToInt32(processProperties[EProcessProperty.ParentProcessId]);

            try
            {
                var parentProcessProperties = pm.GetProcessProperties(parentProcessId);
                string parentProcessName = parentProcessProperties[EProcessProperty.Name].ToString();
                Console.WriteLine($"Parent process '{parentProcessName ?? "Unknown"}' [PID={parentProcessId}]");
                Console.WriteLine("---------------------------------");
            }
            catch { Console.WriteLine("Parent process information not found."); }
        }
    }
}

public class ProcessConnection
{
    internal ManagementScope ManagementScope { get; }

    internal ProcessConnection(string machineName, string user = null, string password = null, string domain = null)
    {
        ManagementScope = new ManagementScope
        {
            Path = new ManagementPath(@"\\" + machineName + @"\root\CIMV2"),
            Options = new ConnectionOptions
            {
                Impersonation = ImpersonationLevel.Impersonate,
                Authentication = AuthenticationLevel.Default,
                EnablePrivileges = true,
                Username = user == null ? null : (string.IsNullOrWhiteSpace(domain) ? user : $"{domain}\\{user}"),
                Password = user == null ? null : password,
            },
        };
        ManagementScope.Connect();
    }
}

public class ProcessManager
{
    public static ProcessManager FromLocalMachine() => new ProcessManager()
    {
        Machine = Environment.MachineName,
    };

    public static ProcessManager FromRemoteMachine(string machine, string user = null, string password = null, string domain = null) => new ProcessManager()
    {
        Machine = machine,
        User = user,
        Password = password,
        Domain = domain,
    };

    private ProcessManager() { }

    public string Machine { get; private set; }
    public string User { get; private set; }
    public string Password { get; private set; }
    public string Domain { get; private set; }

    private ProcessConnection Connection { get; set; }
    private ManagementScope ManagementScope => Connection == null ? (Connection = new ProcessConnection(Machine, User, Password, Domain)).ManagementScope : Connection.ManagementScope;

    public EProcessStartStatus StartProcess(string processPath)
    {
        ManagementClass mc = new ManagementClass($"\\\\{Machine}\\root\\CIMV2", "Win32_Process", null);
        ManagementBaseObject process = mc.GetMethodParameters("Create");
        process["CommandLine"] = processPath;
        ManagementBaseObject createCode = mc.InvokeMethod("Create", process, null);
        string createCodeStr = createCode["ReturnValue"].ToString();
        return (EProcessStartStatus)Convert.ToInt32(createCodeStr);
    }

    public bool KillProcess(string processName)
    {
        try
        {
            SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE Name = '{processName}'");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
            foreach (ManagementObject mo in searcher.Get()) mo.InvokeMethod("Terminate", null);
            return true;
        }
        catch { return false; }
    }

    public bool KillProcess(int processId)
    {
        try
        {
            SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE ProcessId = '{processId}'");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
            foreach (ManagementObject mo in searcher.Get()) mo.InvokeMethod("Terminate", null);
            return true;
        }
        catch { return false; }
    }

    public void SetProcessPriority(string processName, EProcessPriority priority)
    {
        SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE Name = '{processName}'");
        ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher(ManagementScope, query);
        foreach (ManagementObject managementObject in managementObjectSearcher.Get())
        {
            ManagementBaseObject methodParams = managementObject.GetMethodParameters("SetPriority");
            methodParams["Priority"] = priority;
            managementObject.InvokeMethod("SetPriority", methodParams, null);
        }
    }

    public string GetProcessOwner(string processName)
    {
        SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE Name = '{processName}'");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
        foreach (ManagementObject mo in searcher.Get())
        {
            ManagementBaseObject methodParams = mo.GetMethodParameters("GetOwner");
            ManagementBaseObject owner = mo.InvokeMethod("GetOwner", null, null);
            return owner["User"].ToString();
        }
        return null;
    }

    public string GetProcessOwnerSID(string processName)
    {
        SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE Name = '{processName}'");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
        foreach (ManagementObject mo in searcher.Get())
        {
            ManagementBaseObject methodParams = mo.GetMethodParameters("GetOwnerSid");
            ManagementBaseObject OwnerSid = mo.InvokeMethod("GetOwnerSid", null, null);
            return OwnerSid["Sid"].ToString();
        }
        return null;
    }

    public IList<int> GetRunningProcesses()
    {
        IList<int> processes = new List<int>();
        SelectQuery query = new SelectQuery("SELECT * FROM Win32_Process");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
        foreach (ManagementObject mo in searcher.Get()) processes.Add(int.Parse(mo["ProcessId"].ToString()));
        return processes;
    }

    public IDictionary<EProcessProperty, object> GetProcessProperties(int processId)
    {
        SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE ProcessId = '{processId}'");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);

        Dictionary<EProcessProperty, object> properties = new Dictionary<EProcessProperty, object>();
        foreach (ManagementObject mo in searcher.Get())
        {
            foreach (PropertyData pd in mo.Properties)
            {
                if (Enum.TryParse(pd.Name, out EProcessProperty e)) properties[e] = pd.Value;
                else Console.WriteLine(pd.Name + " is not mapped in the properties enumeration.");
            }
        }
        return properties;
    }

    public IDictionary<EProcessProperty, object> GetProcessProperties(string processName)
    {
        SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE Name = '{processName}'");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);

        Dictionary<EProcessProperty, object> properties = new Dictionary<EProcessProperty, object>();
        foreach (ManagementObject mo in searcher.Get())
        {
            foreach (PropertyData pd in mo.Properties)
            {
                if (Enum.TryParse(pd.Name, out EProcessProperty e)) properties[e] = pd.Value;
                else Console.WriteLine(pd.Name + " is not mapped in the properties enumeration.");
            }
        }
        return properties;
    }

    public IList<int> GetProcessessFromExecutablePath(string executablePath)
    {
        SelectQuery query = new SelectQuery($"SELECT * FROM Win32_Process WHERE ExecutablePath = '{executablePath.Replace("\\", "\\\\")}'");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(ManagementScope, query);
        return searcher.Get().Cast<ManagementObject>().Select(mo => Convert.ToInt32(mo["ProcessId"])).ToList();
    }

}

public enum EProcessPriority : uint
{
    IDLE = 0x40,
    BELOW_NORMAL = 0x4000,
    NORMAL = 0x20,
    ABOVE_NORMAL = 0x8000,
    HIGH_PRIORITY = 0x80,
    REALTIME = 0x100
}

public enum EProcessStartStatus
{
    Success = 0,
    AccessDenied = 2,
    NoPermissions = 3,
    Unknown = 8,
    FileNotFound = 9,
    Invalid = 21,
}

public enum EProcessProperty
{
    Caption,
    CommandLine,
    CreationClassName,
    CreationDate,
    CSCreationClassName,
    CSName,
    Description,
    ExecutablePath,
    ExecutionState,
    Handle,
    HandleCount,
    InstallDate,
    KernelModeTime,
    MaximumWorkingSetSize,
    MinimumWorkingSetSize,
    Name,
    OSCreationClassName,
    OSName,
    OtherOperationCount,
    OtherTransferCount,
    PageFaults,
    PageFileUsage,
    ParentProcessId,
    PeakPageFileUsage,
    PeakVirtualSize,
    PeakWorkingSetSize,
    Priority,
    PrivatePageCount,
    ProcessId,
    QuotaNonPagedPoolUsage,
    QuotaPagedPoolUsage,
    QuotaPeakNonPagedPoolUsage,
    QuotaPeakPagedPoolUsage,
    ReadOperationCount,
    ReadTransferCount,
    SessionId,
    Status,
    TerminationDate,
    ThreadCount,
    UserModeTime,
    VirtualSize,
    WindowsVersion,
    WorkingSetSize,
    WriteOperationCount,
    WriteTransferCount,
}