我想爲我製作的一套wpf應用程序製作程序啓動器。啓動器將用於將用戶登錄到應用程序中,並在啓動應用程序之前執行各種測試。是否可以限制哪些程序可以啓動wpf應用程序?
我想做的是讓應用程序只能由啓動程序啓動,而不能直接運行。有沒有辦法讓我檢查應用程序的進程是否已經由啓動程序而不是用戶啓動,可能在我的AppStart()中?
我想爲我製作的一套wpf應用程序製作程序啓動器。啓動器將用於將用戶登錄到應用程序中,並在啓動應用程序之前執行各種測試。是否可以限制哪些程序可以啓動wpf應用程序?
我想做的是讓應用程序只能由啓動程序啓動,而不能直接運行。有沒有辦法讓我檢查應用程序的進程是否已經由啓動程序而不是用戶啓動,可能在我的AppStart()中?
這裏有一種方法可以爲你工作。您可以註冊您的發射器組件:
然後你可以把它這樣,如果他們不從你啓動應用程序運行你的子應用程序將終止。
這是您的子應用程序使用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.
}
}
這僅僅是一個開始,但你的想法...
嗨,感謝您花時間回答,這似乎是沿着我所尋找的路線,但問題已被擱置,即使您提供了有用的答案。我期待聽到你的進一步想法。 –
@AleksandrAlbert - 是的,這個問題非常廣泛,這就是爲什麼它被擱置。回答它會花費太多。在它被擱置之前,我設法得到了我的答案。 –
@AleksandrAlbert - 我爲您的評論添加了一些更新。 –
你可以使用命名管道進行進程間通信來傳遞一些「密鑰」或執行一些其他驗證。 – crashmstr
會有一種方法來檢查程序是否只通過命名管道啓動?而且也不會有人能夠用繞過這個命名管道的同一個命名管道創建另一個應用程序嗎? –
@AleksandrAlbert - 你需要自己研究一下。我們不會爲你做所有的工作。據推測,管道的名稱只有父應用程序和子應用程序(即正在啓動的應用程序)才知道。孩子們當然會發起,不管怎麼樣,但如果他們不是通過父母開始的,他們可以終止。 –