Handling Appservice connections in a multiple instance of fulltrust process

DotNET Fan 271 Reputation points
2024-10-15T10:24:46.31+00:00

Hello UWP experts,

Please look at the below thread . This question is related to the thread.

https://learn.microsoft.com/en-us/answers/questions/2087088/uwp-app-communication-with-another-process-(*-exe)?comment=question#newest-question-comment

UWP app will start multiple instances of fulltrust process each will start the Appservice server. How to differentiate Appservice service for Appservice connections started from UWP?

Thanks

Universal Windows Platform (UWP)
{count} votes

Accepted answer
  1. Junjie Zhu - MSFT 19,216 Reputation points Microsoft Vendor
    2024-10-23T07:54:31.09+00:00

    Hello @DotNET Fan ,

    This is my test code for your reference. I use WPF project as fulltrust process. Appservice can be used normally.

    In WPF(.net 7.0),

     private AppServiceConnection connection = null;
     public MainWindow()
     {
         InitializeComponent();
         InitializeAppServiceConnection();
     }
     private async void InitializeAppServiceConnection()
     {
         connection = new AppServiceConnection();
         connection.AppServiceName = "SampleInteropService";
         connection.PackageFamilyName = Package.Current.Id.FamilyName;
         connection.RequestReceived += Connection_RequestReceived;
         connection.ServiceClosed += Connection_ServiceClosed;
         AppServiceConnectionStatus status = await connection.OpenAsync();
         if (status != AppServiceConnectionStatus.Success)
         {
             // something went wrong ...
             MessageBox.Show(status.ToString());
             this.IsEnabled = false;
         }
     }
    
    
    

    Add Extensions in WAPP Package.appxmanifest.

       <Extensions>
         <desktop:Extension Category="windows.fullTrustProcess" 
                               Executable="WPFfulltrust\WPFfulltrust.exe"/>
         <uap:Extension Category="windows.appService">
            <uap:AppService Name="SampleInteropService" />
         </uap:Extension>
       </Extensions>  
    
    
    

    In UWP App.xaml.cs, activate the UWP in the background and establish the AppServiceConnection.

     public static BackgroundTaskDeferral AppServiceDeferral = null;
     public static AppServiceConnection Connection = null;
     public static event EventHandler AppServiceDisconnected;
     public static event EventHandler<AppServiceTriggerDetails> AppServiceConnected;
     public static bool IsForeground = false;
     /// <summary>
     /// Initializes the singleton application object.  This is the first line of authored code
     /// executed, and as such is the logical equivalent of main() or WinMain().
     /// </summary>
     public App()
     {
         this.InitializeComponent();
         this.Suspending += OnSuspending;
         this.EnteredBackground += App_EnteredBackground;
         this.LeavingBackground += App_LeavingBackground;
     }
     private void App_LeavingBackground(object sender, LeavingBackgroundEventArgs e)
     {
         IsForeground = true;
     }
     private void App_EnteredBackground(object sender, EnteredBackgroundEventArgs e)
     {
         IsForeground = false;
     }
     protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)
     {
         base.OnBackgroundActivated(args);
         if (args.TaskInstance.TriggerDetails is AppServiceTriggerDetails details)
         {
             // only accept connections from callers in the same package
             if (details.CallerPackageFamilyName == Package.Current.Id.FamilyName)
             {
                 // connection established from the fulltrust process
                 AppServiceDeferral = args.TaskInstance.GetDeferral();
                 args.TaskInstance.Canceled += OnTaskCanceled;
                 Connection = details.AppServiceConnection;
                 AppServiceConnected?.Invoke(this, args.TaskInstance.TriggerDetails as AppServiceTriggerDetails);
             }
         }
     }
     private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
     {
         AppServiceDeferral?.Complete();
         AppServiceDeferral = null;
         Connection = null;
         AppServiceDisconnected?.Invoke(this, null);
     }
    

    In UWP MainPage, send message.

    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
        if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
        {
            App.AppServiceConnected += MainPage_AppServiceConnected;
            App.AppServiceDisconnected += MainPage_AppServiceDisconnected;
            await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
        }
    }
    /// <summary>
    /// When the desktop process is connected, get ready to send/receive requests
    /// </summary>
    private async void MainPage_AppServiceConnected(object sender, AppServiceTriggerDetails e)
    {
        App.Connection.RequestReceived += AppServiceConnection_RequestReceived;
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            // enable UI to access  the connection
            btnRegKey.IsEnabled = true;
        });
    }
    
     private async void btnClick_ReadKey(object sender, RoutedEventArgs e)
     {
         ValueSet request = new ValueSet();
         request.Add("KEY", tbKey.Text);
         AppServiceResponse response = await App.Connection.SendMessageAsync(request);
         // display the response key/value pairs
         tbResult.Text = "";
         foreach (string key in response.Message.Keys)
         {
             tbResult.Text += key + " = " + response.Message[key] + "\r\n";
         }
     }
    
    
    

    This code refers to StefanWick's blog and code.

    Feel free to comment on how there are other questions.

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


2 additional answers

Sort by: Most helpful
  1. Junjie Zhu - MSFT 19,216 Reputation points Microsoft Vendor
    2024-10-16T03:21:04.72+00:00

    Hello @DotNET Fan ,

    Welcome to Microsoft Q&A!

    You can use AppServiceConnection.SendMessageAsync to send a special ID, such as file name + time.

    var message = new ValueSet(); 
    message.Add("Fileinfo", "Name+Time"); 
    AppServiceResponse response = await this.inventoryService.SendMessageAsync(message);
    

    Then read the passed parameters from args in OnRequestReceived.

    var messageDeferral = args.GetDeferral(); 
    ValueSet message = args.Request.Message;
    

    Thank you.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. DotNET Fan 271 Reputation points
    2024-10-20T13:37:08.4333333+00:00

    @Junjie Zhu - MSFT

    Can't get the Appserviceconnnection to work in .Net 8 fulltrustprocess and UWP app  .

    When the fulltrustprocess server starts with the call to Windows.ApplicationModel.FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync and tries to open the server the openasync always returns AppServiceUnavailable;

     

    Here is the code in the main (fulltrustprocess)

    program.cs

     

    static async Task Main(string[] args)
    {
    AppServiceConversionServer appServiceServerManager = new AppServiceConversionServer();
     await appServiceServerManager.InitializeAppServiceAsync();
    }
    

     

     AppServiceConversionServer.cs (fulltrustprocess)

    namespace Desktop.FullTrustApp.AppService;
    public class AppServiceConversionServer
    {
     
    public async Task InitializeAppServiceAsync()
    {
    AppserviceConnection = new AppServiceConnection
     {
         AppServiceName = "Desktop.FullTrustApp.AppService",
         PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName
     };
     AppServiceConnectionStatus status = await AppserviceConnection.OpenAsync();
      if (status == AppServiceConnectionStatus.Success)
     {
         AppserviceConnection.RequestReceived += OnRequestReceived;
         await Task.Delay(-1);
    }
    }
    }
    
    

    In the UWP App package.appxmanifest

     

    <uap:Extension Category="windows.appService" EntryPoint=" Desktop.FullTrustApp.AppService.AppServiceConversionServer">
       <uap3:AppService Name="Desktop.FullTrustApp.AppService" uap4:SupportsMultipleInstances="true"/>
     </uap:Extension>
    

    In the UWP client App, it starts the fulltrustprocess on some button click and tries to start the server connection for the client to communicate. 

    await Windows.ApplicationModel.FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
     
     AppserviceConnection = new AppServiceConnection
     {
         AppServiceName = "Desktop.FullTrustApp.AppService",
         PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName
     };
     AppserviceConnection.RequestReceived += OnRequestReceived;
     
     
     for (int attempt = 1; attempt <= MaxConnectionRetries; attempt++)
     {
     
         status = await AppserviceConnection.OpenAsync();
         if (status == AppServiceConnectionStatus.Success)
         {
             break;
         }
         await Task.Delay(1000);
     }
    

    In the fulltrustprocess server and UWP app client scenario , what is the correct way to make the connection work and send bi directional messages ? The learn documentation is confusing.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.