12

I am trying to start an exe that is located in C:/Program Files (x86)/App from UWP app. How can I do this.

I can start exe file by using Windows Desktop extension for UWP, add Hide Copy Code

<Extensions>
        <desktop:Extension Category="windows.fullTrustProcess"          Executable="Assets\app.exe" />
</Extensions>

to Package.appmanifest and call this

await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();

in main class. But I need to add app.exe to Assets directory of project
My question is if exe file is located in other directory, how can I start it without adding exactly the exe file.
Thanks

neo
  • 618
  • 1
  • 10
  • 29

2 Answers2

18

Today I wrote a program to successfully launch any .exe programs from UWP. Want to share the process for the benefit of others. This is in addition to the answer by stefan Wick MSFT. First the package.appmanifest needs to be updated. This is what I have in package.appmanifest:

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"

  IgnorableNamespaces="uap mp">

  <Identity
    Name="217d09c4-aa67-4403-939f-518a55d46f16"
    Publisher="CN=admin"
    Version="1.0.0.0" />

  <mp:PhoneIdentity PhoneProductId="217d09c4-aa67-4403-939f-518a55d46f16" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

  <Properties>
    <DisplayName>App1</DisplayName>
    <PublisherDisplayName>admin</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
  </Properties>

  <Dependencies>
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.14393.0" MaxVersionTested="10.0.16299.0" />
  </Dependencies>

  <Resources>
    <Resource Language="x-generate"/>
  </Resources>

  <Applications>
    <Application Id="App"
      Executable="$targetnametoken$.exe"
      EntryPoint="App1.App">
      <uap:VisualElements
        DisplayName="App1"
        Square150x150Logo="Assets\Square150x150Logo.png"
        Square44x44Logo="Assets\Square44x44Logo.png"
        Description="App1"
        BackgroundColor="transparent">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>

        <Extensions>

          <desktop:Extension Category="windows.fullTrustProcess" Executable="Assets\Launcher.exe" >
          <desktop:FullTrustProcess>
            <desktop:ParameterGroup GroupId="ChromeGroup" Parameters="chrome.exe"/>
            <desktop:ParameterGroup GroupId="WordGroup" Parameters="WINWORD.exe"/>
          </desktop:FullTrustProcess>
          </desktop:Extension>
        </Extensions>

    </Application>
  </Applications>

  <Capabilities>

    <Capability Name="internetClient"/>
    <rescap:Capability Name="runFullTrust" />

  </Capabilities>

</Package>

The code within the <Extensions> tag is the one responsible for launching the executable files. The code with <Capabilities> tag add capability or permission to launch the executable.The restrictive capabilities like runFullTrust is having green green line below it. It is not a error and program will run without any error. The Launcher.exe in the above code is a console app. I write the code in the text editor and created Launcher.exe from it. The code of the Launcher.exe is this:

using System;  
using System.IO;   
using System.Diagnostics;                                                                         
using System.Reflection;
    class Program
    {
    static void Main(string []args)
    {
    try
    {

    if(args.Length!=0)
    {
    string executable=args[2];
   /*uncomment the below three lines if the exe file is in the Assets  
    folder of the project and not installed with the system*/         
    /*string path=Assembly.GetExecutingAssembly().CodeBase;
    string directory=Path.GetDirectoryName(path);
    process.Start(directory+"\\"+executable);*/
    Process.Start(executable);
    }
    }
    catch(Exception e)
    {
    Console.WriteLine(e.Message);
    Console.ReadLine();
    }

    }
    }

Saved this Launcher.exe console app in Assets folder of the UWP project. UWP is not allowed to launch .exe apps. But UWP app calls this code to launch any .exe program. The GroupId ChromeGroup is used to launch chrome browser by passing chrome.exe parameter to the Launcher.exe. The GroupId WordGroup is used to launch MS Word by passing WINWORD.exe parameter to Launcher.exe. The code to pass the parameter to Launcher.exe is :

`private async void Button_Click(object sender, RoutedEventArgs e)
{
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("ChromeGroup");
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("WordGroup");
}`

On the click of a button above Api pass on the name of the exe file to Launcher.exe program. It do this by accepting GroupId as parameter. The Api is available under Windows.ApplicationModel NameSpace.

EDIT:

The executable you want to launch may not be installed on system. It may not be packaged with your application in Assets folder. Than you can give full path of the executable in the Parameters attribute.

Paramjit
  • 760
  • 8
  • 25
2

You cannot start an arbitrary EXE from your UWP app process. What you can do is launch your own full trust EXE in your own package (as you already discovered). From that EXE you can then launch the arbitrary EXE (assuming the user has the privileges to access it). So it's a two step process for this scenario in the arbitrary case.

A better option is to launch the other app via a protocol (but this may not always be an option, if you don't own it, or it doesn't support protocol activation).

Stefan Wick MSFT
  • 13,600
  • 1
  • 32
  • 51
  • Hi @Stefan, thanks for your reply. `From that EXE you can then launch the arbitrary EXE (assuming the user has the privileges to access it)`. Could you explain more detail about this. I am a newbie in UWP development. `A better option is to launch the other app via a protocol`. What is protocol here? It would be better for me if you could give me a reference or example of this option. Thanks – neo Mar 12 '18 at 05:40
  • 1
    The full trust EXE in your package can just be a dumb launcher, to launch the actual EXE you want to launch, based on data passed from your UWP. For that you can use ShellExecute, Process.Start, CreateProcess or whatever you would prefer to use in a standard Windows desktop app. By protocol launch I mean things like ms-word:// or mailto:// - however this won't work for apps that don't implement such a protocol. – Stefan Wick MSFT Mar 12 '18 at 22:47
  • Thanks @Stefan, the exe file is is build from C project and therefore it doesn't support protocol activation. Currently I can execute the exe by using `` in Package.appxmanifest, and exe file is included in appX package. However, is it possible to add multiple `` for register multiple exe files. I tried to do that but I got error :`The Extension element with Category attribute value "windows.fullTrustProcess" must only be declared once`. Could you help me out, thanks. – neo Mar 14 '18 at 04:53
  • @neo, you only declare one 'fullTrustProcess' extension in the manifest, which is your launcher. Based on data passed from the UWP this launcher can then launch any number of other processes, either from EXEs in your package, or EXE from other places on the system. – Stefan Wick MSFT Mar 14 '18 at 04:59
  • If I configure `` as above, I can only directly start `my.exe` by calling `FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync()` method. But in case have `a.exe`, `b.exe`... and I need to call each of them for appropriate function then how to register these exe files in manifest as full trust process and what data need to pass from UWP to launcher. I checked `FullTrustProcessLauncher`. It supports 'LaunchFullTrustProcessForAppAsync(string fullTrustPackageRelativeAppId)' and `LaunchFullTrustProcessForCurrentAppAsync(string parameterGroupId)` – neo Mar 14 '18 at 06:47
  • I found that one `https://learn.microsoft.com/en-us/uwp/api/windows.applicationmodel.fulltrustprocesslauncher#Windows_ApplicationModel_FullTrustProcessLauncher_LaunchFullTrustProcessForCurrentAppAsync`. This tag `` indicates that the exe file is located in /Sync directory will be execute when I call `LaunchFullTrustProcessForCurrentAppAsync("SyncGroup")`. Am I right ? – neo Mar 14 '18 at 10:40
  • 1
    No, in the example "/Sync" is the parameter that is passed to the fulltrustprocess when you launch it LaunchFullTrustProcess("SyncGroup"). As I said before, you only need to declare one fulltrustprocess in the manifest, let's call it LAUNCHER.EXE. Then you define ParameterGroups for each of the additional EXE that you intend to launch. The LAUNCHER.EXE now can launch each of those EXEs based on the parameter that is based from the UWP. – Stefan Wick MSFT Mar 14 '18 at 13:29
  • I tried your way. I create a C# console app called LAUNCHER.EXE and get parameter in main class `if(args.Length != 0) { string param = args[0]}`. The parameter suppose to be "/Sync" but I always receive "/InvokerPRAID:" in LAUNCHER app. What did I do wrong or UWP app doesn't support passing parameters to other process. I'm thinking about using app data or file to pass parameters but I still look for better solution. – neo Mar 15 '18 at 05:21
  • The parameter is in args[3]. – Stefan Wick MSFT Mar 15 '18 at 16:09
  • the parameter is in args[2]. It seems that the order of parameters in args[] array are: `/InvokerPRAID:, AppId, GroupId`. I am not so sure but I guess that `args[0] = InvokerPRAID:` is a flag that indicates a call from UWP app. Anyway, my problem is solved, thanks a lot, you are so patient with me :). – neo Mar 16 '18 at 02:23
  • Glad to hear you got it working. Please mark as answered so we can check this off. Thanks! – Stefan Wick MSFT Mar 16 '18 at 02:26
  • I have done this using a proxy app running in the background waiting from command coming from UWP app. – jaysonragasa Apr 28 '20 at 01:46