Search code examples
c#uwpprocesswindows-10desktop-bridge

UWP FullTrustProcess - actually controlling the process


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:

enter image description here

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.


Solution

  • 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/