UWP FullTrustProcess - 实际控制进程 [英] UWP FullTrustProcess - actually controlling the process
问题描述
在 WPF 中,我用这段代码来控制外部 .exe 文件的进程:
ProcessStartInfo info = new ProcessStartInfo(){动词 = "runas",FileName = executePath,//WPF 应用程序中的Client.exe 路径UseShellExecute = false,重定向标准错误 = 真,重定向标准输出 = 真,};进程 scanProcess = 新进程{开始信息 = 信息,EnableRaisingEvents = 真};int procId = Process.GetCurrentProcess().Id;Process[] existingProcess = Process.GetProcessesByName("Client.exe");foreach(现有进程中的进程进程){if (process.Id == procId){继续;}return;//不要运行,可能已经尝试启动double}scanProcess.Start();scanProcess.Exited += (s, e) =>回去();windowHandle = IntPtr.Zero;IntPtr buttonHandle = IntPtr.Zero;while (buttonHandle == IntPtr.Zero)//等到进程完全启动,我们等待一个按钮可用,因为那时我们知道它准备好了{windowHandle = HardwareApi.GetForegroundWindow();buttonHandle = HardwareApi.FindWindowEx(windowHandle, IntPtr.Zero, "TPanel", "Start");}矩形 rect = new Rectangle(0, 0, 0, 0);HardwareApi.GetWindowRect(windowHandle, ref rect);//移动窗口到正确的位置var tempX = 500;var tempY = 600;HardwareApi.SetWindowPos(windowHandle, new IntPtr(-1), 0, 0, 0, 0, 3u);HardwareApi.MoveWindow(windowHandle, (int)tempX, (int)tempY, rect.Width, rect.Height - 55, true);
如您所见,过程控制相当激烈.HardwareApi
只是使用 DllImport
的 user32.dll
方法的集合.
现在我不介意是否所有这些功能都可用,但至少我需要能够启动进程并停止它/从新的 UWP 应用程序中终止它.
所以我经历了创建UWP应用程序和Package应用程序的过程,我跟着
Package 项目的Package.appxmanifest 包含这部分:
<应用程序><应用程序 ID="应用程序"....<扩展><桌面:扩展类别="windows.fullTrustProcess" Executable="Rss\Hardware\Software\RedFolder\Client.exe"/></扩展></应用程序></应用程序><能力><能力名称="internetClient"/><rescap:Capability Name="runFullTrust"/><rescap:Capability Name="allowElevation"/></能力>
在 UWP 应用程序中,我在某处启动了 FullTrustProcess
不要忘记去添加引用
->通用Windows->扩展->Windows桌面扩展的UWP(最新版本)
并添加引用
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0)){等待 FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();}
所以这一切正常,所以现在的问题是我如何做以下事情:
- 检查进程是否正在运行
- 在特定时间从 UWP 应用程序中关闭进程
- 将窗口移动到屏幕上的某个位置(或使用其他类似
user32.dll
的函数.
根据我的理解,UWP 中的应用服务似乎不是解决方案,我无法以接收/连接的方式修改外部 .exe.如果应用服务只能从 UWP 端使用来控制进程,那就太好了.
要解决您的方案,您需要将完全信任的启动器/控制器 EXE 添加到您的包中.通过 FullTrustProcess 启动器从 UWP 启动它并通过 AppServiceConnection 与其通信.从控制器 EXE 中,您可以使用所有 System.Diagnostis.Process* API 来启动、检查和终止您的实际应用程序进程(在您的示例中为 Client.exe) - 并且还可以使用所有 user32 函数进行窗口操作等.>
在此处处理多个进程的更多信息和示例应用程序:https://stefanwick.com/2018/04/06/uwp-with-desktop-extension-part-2/
有关如何在此处进行通信的信息和示例:https://stefanwick.com/2018/04/16/uwp-with-desktop-extension-part-3/
In WPF, I have used this code to control the process of an external .exe file:
ProcessStartInfo info = new ProcessStartInfo()
{
Verb = "runas",
FileName = executePath,//Client.exe path within the WPF application
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
};
Process scanProcess = new Process
{
StartInfo = info,
EnableRaisingEvents = true
};
int procId = Process.GetCurrentProcess().Id;
Process[] existingProcess = Process.GetProcessesByName("Client.exe");
foreach (Process process in existingProcess)
{
if (process.Id == procId)
{
continue;
}
return;//don't run, might have tried to start double
}
scanProcess.Start();
scanProcess.Exited += (s, e) => GoBack();
windowHandle = IntPtr.Zero;
IntPtr buttonHandle = IntPtr.Zero;
while (buttonHandle == IntPtr.Zero)//wait till process is fully started, we wait for a button the be available because then we know it is ready
{
windowHandle = HardwareApi.GetForegroundWindow();
buttonHandle = HardwareApi.FindWindowEx(windowHandle, IntPtr.Zero, "TPanel", "Start");
}
Rectangle rect = new Rectangle(0, 0, 0, 0);
HardwareApi.GetWindowRect(windowHandle, ref rect);
//move window to correct position
var tempX = 500;
var tempY = 600;
HardwareApi.SetWindowPos(windowHandle, new IntPtr(-1), 0, 0, 0, 0, 3u);
HardwareApi.MoveWindow(windowHandle, (int)tempX, (int)tempY, rect.Width, rect.Height - 55, true);
As you see, quite a bit of intense process controlling. HardwareApi
is just a collection of user32.dll
methods using DllImport
.
Now I don't mind if not all of these functionalities are possible, but at least I need to be able to start the process and stop it/kill it from out the new UWP application.
So I went through the process of creating an UWP application and a Package application, I followed this blog, provided by this answer on stackoverflow. What is importantly different is that I do not have a separate Visual Studio Project of the external Client.exe, so I did what the mentioned answer said: Copy the Client.exe file (and the dependent files) into the Package project.
Solution view:
Package.appxmanifest of the Package project includes this part:
<Applications>
<Application Id="App"
....
<Extensions>
<desktop:Extension Category="windows.fullTrustProcess" Executable="Rss\Hardware\Software\RedFolder\Client.exe"/>
</Extensions>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
<rescap:Capability Name="allowElevation" />
</Capabilities>
And within the UWP application, I somewhere start the FullTrustProcess
Don't forget to go to Add Reference
-> Universal Windows -> Extensions -> Windows Desktop Extensions for the UWP (latest version)
and add the reference
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
{
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
}
So this all works fine, so now the question is how I can do the following things:
- Check if the process is running
- Close the process at a certain time from within the UWP application
- Move the window to a certain on-screen position (or use other
user32.dll
-like functions.
As per my understanding, App Service within UWP doesn't seem to be a solution, I can't modify the external .exe in such a way that it would receive/connect. If an App Service can be used from only the UWP-side to control a process then that would be great.
To solve your scenario you need to add a full-trust launcher/controller EXE to your package. Launch this from the UWP via FullTrustProcess launcher and communicate with it via AppServiceConnection. From the controller EXE you can then use all the System.Diagnostis.Process* APIs to start, check and kill your actual app process (Client.exe in your example) - and also use all the user32 function for window manipulation etc.
More info and a sample app on handling multiple processes here: https://stefanwick.com/2018/04/06/uwp-with-desktop-extension-part-2/
Info and sample on how to do the communication here: https://stefanwick.com/2018/04/16/uwp-with-desktop-extension-part-3/
这篇关于UWP FullTrustProcess - 实际控制进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!