UWP FullTrustProcess - 实际控制进程 [英] UWP FullTrustProcess - actually controlling the process

查看:69
本文介绍了UWP FullTrustProcess - 实际控制进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 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 只是使用 DllImportuser32.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();}

所以这一切正常,所以现在的问题是我如何做以下事情:

  1. 检查进程是否正在运行
  2. 在特定时间从 UWP 应用程序中关闭进程
  3. 将窗口移动到屏幕上的某个位置(或使用其他类似 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:

  1. Check if the process is running
  2. Close the process at a certain time from within the UWP application
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆