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