2016-03-08 142 views
-2

我想为我制作的一套wpf应用程序制作程序启动器。启动器将用于将用户登录到应用程序中,并在启动应用程序之前执行各种测试。是否可以限制哪些程序可以启动wpf应用程序?

我想做的是让应用程序只能由启动程序启动,而不能直接运行。有没有办法让我检查应用程序的进程是否已经由启动程序而不是用户启动,可能在我的AppStart()中?

+1

你可以使用命名管道进行进程间通信来传递一些“密钥”或执行一些其他验证。 – crashmstr

+0

会有一种方法来检查程序是否只通过命名管道启动?而且也不会有人能够用绕过这个命名管道的同一个命名管道创建另一个应用程序吗? –

+2

@AleksandrAlbert - 你需要自己研究一下。我们不会为你做所有的工作。据推测,管道的名称只有父应用程序和子应用程序(即正在启动的应用程序)才知道。孩子们当然会发起,不管怎么样,但如果他们不是通过父母开始的,他们可以终止。 –

回答

0

这里有一种方法可以为你工作。您可以注册您的发射器组件:

enter image description here

然后你可以把它这样,如果他们不从你启动应用程序运行你的子应用程序将终止。

这是您的子应用程序使用the Windows API NtQueryInformationProcess function的一些代码。它通过首先通过GetParentProcessID获取其进程ID来获得父进程,然后从该进程加载程序集并检索其包含公钥的完整(即“强”)名称。

[System.Runtime.InteropServices.DllImport("ntdll.dll")] 
private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref NtQueryInformationProcessProcessInformation processInformation, int processInformationLength, ref int returnLength); 

/// <summary> 
/// Return the process ID of the process that is the parent of this process, if any, or else return null. 
/// </summary> 
/// <returns>Return the process ID of the process that is the parent of this process, if any, or else return null.</returns> 
/// <remarks></remarks> 
private static int? GetParentProcessID() 
{ 
    var info = new NtQueryInformationProcessProcessInformation(); 
    var returnLength = 0; 
    const int ProcessInfoClassProcessBasicInformation = 0; 
    var status = NtQueryInformationProcess(Process.GetCurrentProcess().Handle, ProcessInfoClassProcessBasicInformation, ref info, System.Runtime.InteropServices.Marshal.SizeOf(info), ref returnLength); 
    var NTStatusSuccess = 0; 
    if (status != NTStatusSuccess) throw new System.ComponentModel.Win32Exception(status); 

    try 
    { 
     return Process.GetProcessById(info.InheritedFromUniqueProcessId.ToInt32()).Id; 
    } 
    catch (ArgumentException) 
    { 
     return new int?(); //not found.    
    } 
} 

/// <summary> 
/// A structure which is required by the <see cref="NtQueryInformationProcess"/> method. 
/// </summary> 
/// <remarks></remarks> 
private struct NtQueryInformationProcessProcessInformation 
{ 
    internal IntPtr Reserved1; 
    internal IntPtr PebBaseAddress; 
    internal IntPtr Reserved2_0; 
    internal IntPtr Reserved2_1; 
    internal IntPtr UniqueProcessId; 
    internal IntPtr InheritedFromUniqueProcessId; 
} 

然后,你可以使用这样的:

var parentProcessID = GetParentProcessID(); 
var parentProcess = parentProcessID.HasValue ? Process.GetProcessById(parentProcessID.Value) : null; 

if(parentProcess != null) 
{ 
    try 
    { 
     var strongName = Assembly.ReflectionOnlyLoadFrom(parentProcess.MainModule.FileName); 

     // check your strong name to make sure it belongs to the launcher... 
    } 
    catch (System.BadImageFormatException e) 
    { 
     // not a .net assembly, so it couldn't be your launcher app. 
    } 
} 

这仅仅是一个开始,但你的想法...

+0

嗨,感谢您花时间回答,这似乎是沿着我所寻找的路线,但问题已被搁置,即使您提供了有用的答案。我期待听到你的进一步想法。 –

+0

@AleksandrAlbert - 是的,这个问题非常广泛,这就是为什么它被搁置。回答它会花费太多。在它被搁置之前,我设法得到了我的答案。 –

+0

@AleksandrAlbert - 我为您的评论添加了一些更新。 –

相关问题