{"id":139,"date":"2021-08-05T12:00:00","date_gmt":"2021-08-05T19:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/react-native\/?p=139"},"modified":"2022-11-17T03:32:35","modified_gmt":"2022-11-17T11:32:35","slug":"win32component","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/react-native\/win32component\/","title":{"rendered":"Use Win32 features from a React Native for Windows application"},"content":{"rendered":"<p>If you have adopted React Native to build your Windows applications, you&#8217;ll know that the final output is a <a href=\"https:\/\/docs.microsoft.com\/windows\/uwp\/get-started\/universal-application-platform-guide\">Universal Windows Platform application<\/a>. This development platform gives you access to all the latest enhancements in the Windows ecosystem (modern UI platform, notifications, integration with features like inking and Windows Hello, etc.), plus greater security and reliability thanks to the sandbox the application runs in.\nHowever, there might be scenarios where UWP isn&#8217;t enough and you need to perform one or more tasks which are supported only by the Win32 ecosystem: working with any file on the disk without user intervention, reading a key from the registry, integrating a SDK which doesn&#8217;t support the Windows Runtime.<\/p>\n<p>In this post we&#8217;re going to explore a solution that will enable you to get the best of both worlds: a React Native for Windows application which integrates a classic Win32 process. We&#8217;re going to build a sample React Native application which will be able to read a registry key and display it. The goal is to display to the user values stored in the <code>\\HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion<\/code> hive, which contains many information about the currently installed version of Windows.<\/p>\n<p>The solution will use the following components.<\/p>\n<h4>A classic Windows process<\/h4>\n<p>We&#8217;re going to build a .NET 5.0 console application which, by targeting Windows 10 and using the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/core\/porting\/windows-compat-pack\">Windows Compatibility Pack<\/a>, will be able to interact with the system registry. The React Native application will send to this process the name of the key we want to retrieve; the process will read its value and send it back to the React Native application.<\/p>\n<h4>A React Native for Windows application<\/h4>\n<p>This will be a traditional React Native for Windows application. However, as we&#8217;re going to see later, we&#8217;ll have to make a couple of changes to the host app generated by the template to handle the communication with the classic Windows process.<\/p>\n<h4>App Services<\/h4>\n<p><a href=\"https:\/\/docs.microsoft.com\/windows\/uwp\/launch-resume\/app-services\">App Services<\/a> is a UWP feature that enables a Windows application to host one or more background tasks that can be consumed by other applications. You can think of this feature like REST services, but exposed locally. Once a UWP application which exposes an App Service is deployed on a machine, other applications can connect to it using its name and the Package Family Name of the hosting application. Once the communication channel is established, the calling application can send data to the App Service, which will process it and send back the results.<\/p>\n<p>In our context, App Service will enable us to create a communication channel between the React Native application and the classic Win32 process. The main difference compared to the traditional usage is that the App Service will be hosted and consumed by the same package, since the two processes (UWP and classic Win32) will be packaged together.<\/p>\n<p>App Services support two approaches: <a href=\"https:\/\/docs.microsoft.com\/windows\/uwp\/launch-resume\/convert-app-service-in-process\">in-proc<\/a> (when the implementation of the service is defined in the main application itself) and <a href=\"https:\/\/docs.microsoft.com\/windows\/uwp\/launch-resume\/how-to-create-and-consume-an-app-service\">out-of-proc<\/a> (when the implementation of the service is defined in an external Windows Runtime Component, which gets executed in a different process). For our scenario, we must use the in-proc approach, since we need to hold a direct connection with the main application.<\/p>\n<h4>A native module<\/h4>\n<p><a href=\"https:\/\/microsoft.github.io\/react-native-windows\/docs\/native-modules\">A native module<\/a> is the way to expose native features to the JavaScript layer of React Native application. In the Windows context, a native module is a Windows Runtime Component that, through attributes which decorates your code, can expose methods, properties and events to JavaScript.\nThe native module is needed as a glue between the React Native world and the UWP world. All the APIs to interact with an App Service are exposed by the Windows Runtime and, as such, we need a middle man that can make them accessible to JavaScript.<\/p>\n<h4>Windows Application Packaging Project<\/h4>\n<p>A <a href=\"https:\/\/docs.microsoft.com\/\/windows\/msix\/desktop\/desktop-to-uwp-packaging-dot-net\">Windows Application Packaging Project<\/a> (WAP project, from now on) is a template available in Visual Studio, which is typically used to package as MSIX classic Windows application. In our context, we&#8217;re going to use it to bundle together the classic Win32 process and the React Native for Windows application in the same MSIX package.<\/p>\n<p>The diagram below shows how all these components are tight together:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/react-native\/wp-content\/uploads\/sites\/76\/2022\/11\/architecture.png\" alt=\"The architecture of the solution we&#039;re going to build in the article\" \/><\/p>\n<ol>\n<li>The user launches the React Native application which, at the same time, starts also the classic Win32 process.<\/li>\n<li>The Win32 process, at startup, establishes a communication with the React Native application using an App Service and it stores a reference to the channel.<\/li>\n<li>The user presses a button in the React Native application.<\/li>\n<li>The button will invoke a method method exposed by the native module. The method will push a message to the communication channel, so that it can be received by the classic Win32 process. The message will contain the information about the key that the Windows process must retrieve from the registry.<\/li>\n<li>The classic Win32 process retrieves the desired key from the registry, it stores it inside another message and it sends it back to the communication channel.<\/li>\n<li>The native module, which is using the App Service to keep the communication channel open, receives the message with the retrieved key and it sends it back to the JavaScript layer.<\/li>\n<li>The React Native application can now show to the user the value of the registry key.<\/li>\n<\/ol>\n<p>Let&#8217;s start building all the components!<\/p>\n<blockquote>\n<p>All the samples you&#8217;ll find below (including the native module and the React Native host app) will be based on C#, since it&#8217;s the language I&#8217;m most familiar with. However, the same goal can be achieved also using the C++ templates.<\/p>\n<\/blockquote>\n<h3>The classic Win32 process<\/h3>\n<p>For the purpose of this sample, we&#8217;re going to use a .NET 5.0 console application. Open with Visual Studio the solution included in the <code>windows<\/code> folder of your React Native application, right click on it and choose <strong>Add -&gt; New project<\/strong>. Choose <strong>Console application<\/strong> as template.<\/p>\n<p>Before starting to write some code, we need to make a few changes:<\/p>\n<ol>\n<li>Double click on the project and change the <code>TargetFramework<\/code> from <code>net5.0<\/code> to <code>net5.0-windows10.0.19041.0<\/code>. The new target will enable you to leverage Windows 10 APIs from your .NET application. It&#8217;s required in our scenario since we need to use the App Service APIs.<\/li>\n<li>Right click on the project, choose <strong>Manage NuGet Packages<\/strong> and install the <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Windows.Compatibility\">Microsoft.Windows.Compatibility<\/a> package. It will give us access to the APIs to interact with the Windows registry.<\/li>\n<li>Right click on the project, choose <strong>Properties<\/strong> and change the <strong>Output type<\/strong> from <strong>Console Application<\/strong> to <strong>Windows Application<\/strong>. Thanks to this change, our application will run headless, without any visible UI. This helps to achieve a good user experience, since our classic Win32 process will run only in background. All the UI and interaction will be handled by the React Naive application.<\/li>\n<\/ol>\n<p>The application will run continuously in background, until the main React Native application will be closed. To achieve this goal, we start the main process in a separate thread, which gets terminated when the connection with the App Service is closed (which means that the application is closed). This approach ensures that the classic Win32 application doesn&#8217;t become a &#8220;zombie&#8221; process, which stays alive even if the main app has been shut down.<\/p>\n<pre><code class=\"language-csharp\">static AutoResetEvent appServiceExit;\r\nstatic AppServiceConnection connection = null;\r\n\r\nstatic void Main(string[] args)\r\n{\r\n    appServiceExit = new AutoResetEvent(false);\r\n    Thread appServiceThread = new Thread(new ThreadStart(ThreadProc));\r\n    appServiceThread.Start();\r\n    appServiceExit.WaitOne();\r\n}<\/code><\/pre>\n<p>The code above starts the execution of a method (called <code>ThreadProc<\/code>) in a separate thread. We use an <code>AutoResetEvent<\/code> to block the execution of the <code>Main()<\/code> method. This way, we make sure that the process will keep running until the communication channel created with the App Service is alive.<\/p>\n<p>The <code>ThreadProc<\/code> method is the real &#8220;core&#8221; of the process, which takes care of initializing the connection with the App Service:<\/p>\n<pre><code class=\"language-csharp\">static async void ThreadProc()\r\n{\r\n    connection = new AppServiceConnection();\r\n    connection.AppServiceName = \"RegistryService\";\r\n    connection.PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;\r\n    connection.RequestReceived += Connection_RequestReceived;\r\n    connection.ServiceClosed += Connection_ServiceClosed;\r\n\r\n    \/\/we open the connection\r\n    AppServiceConnectionStatus status = await connection.OpenAsync();\r\n\r\n    if (status != AppServiceConnectionStatus.Success)\r\n    {\r\n        \/\/if the connection fails, we terminate the Win32 process\r\n        appServiceExit.Set();\r\n    }\r\n}<\/code><\/pre>\n<p>We create a new <code>AppServiceConnection<\/code> and we configure it in the following way:<\/p>\n<ul>\n<li>We specify the name of the App Service we want to connect to, using the <code>AppServiceName<\/code> property. This name must match the one we&#8217;re going to include inside the manifest of the Windows Application Packaging Project in a later stage.<\/li>\n<li>We specify the Package Family Name of the application which hosts the App Service. In our scenario, since the React Native application and the classic Win32 process are hosted in the same package, we can retrieve it using the <code>Windows.ApplicationModel.Package<\/code> APIs.<\/li>\n<li>We subscribe to two events: <code>RequestReceived<\/code>, which is triggered when the React Native application sends a message; <code>ServiceClosed<\/code>, which is triggered when the App Service channel is shut down.<\/li>\n<\/ul>\n<p>Then we use the <code>OpenAsync()<\/code> method to open the connection. If it isn&#8217;t successful, there&#8217;s no need for this process to stay alive, so we call <code>Set()<\/code> on the <code>AutoResetEvent<\/code> object, so that the <code>Main()<\/code> method can terminate.<\/p>\n<p>Let&#8217;s see now the implementation of the two event handlers. The first one, <code>ServiceClosed<\/code>, is the easiest one:<\/p>\n<pre><code class=\"language-csharp\">private static void Connection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)\r\n{\r\n    \/\/when the connection with the App Service is closed, we terminate the Win32 process\r\n    appServiceExit.Set();\r\n}<\/code><\/pre>\n<p>If the communication with the App Service drops, we simply call <code>Set()<\/code> on the <code>AutoResetEvent<\/code> object so that the process can terminate.<\/p>\n<p>The second one, <code>RequestReceived<\/code>, instead, is the one where the communication with the React Native application happens:<\/p>\n<pre><code class=\"language-csharp\">private static async void Connection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)\r\n{\r\n    string key = args.Request.Message[\"RegistryKeyName\"].ToString();\r\n\r\n    var hive = Registry.LocalMachine.OpenSubKey(@\"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\", false);\r\n    string value = hive.GetValue(key).ToString();\r\n\r\n    ValueSet valueSet = new ValueSet\r\n    {\r\n        { \"RegistryKeyValue\", value }\r\n    };\r\n\r\n    await args.Request.SendResponseAsync(valueSet);\r\n}<\/code><\/pre>\n<p>From the <code>Request.Message<\/code> dictionary of the event arguments, we can retrieve any information passed by the main React Native application. In our scenario, the name of the requested registry key will be stored in an item with <code>RegistryKeyName<\/code> as key.\nWe use this information to connect to the registry (using the <code>Registry<\/code> APIs) and to retrieve this key from <code>SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion<\/code>, which is the hive that contains all the information about the currently installed version of Windows.<\/p>\n<p>Once we have retrieved the key, we stored it a new message (the <code>ValueSet<\/code> object) with key <code>RegistryKeyValue<\/code>. In the end, we send it back using the <code>SendResponseAsync()<\/code> method, so that the caller (in our case, the native module) can use it.<\/p>\n<h3>The React Native for Windows application<\/h3>\n<p>When the classic Windows application invokes the <code>OpenAsync()<\/code> method to connect to the App Service, the host UWP app will wake up to respond (remember that we&#8217;re using an in-proc App Service). This scenario is handled by a special event called <code>OnBackgroundActivated<\/code>, which you can subscribe in the <code>App<\/code> class of the host app. This is the implementation:<\/p>\n<pre><code class=\"language-csharp\">protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args)\r\n{\r\n    base.OnBackgroundActivated(args);\r\n\r\n    if (args.TaskInstance.TriggerDetails is AppServiceTriggerDetails details)\r\n    {\r\n        appServiceDeferral = args.TaskInstance.GetDeferral();\r\n\r\n        var ns = ReactPropertyBagHelper.GetNamespace(\"RegistryChannel\");\r\n        var name = ReactPropertyBagHelper.GetName(ns, \"AppServiceConnection\");\r\n\r\n        InstanceSettings.Properties.Set(name, details.AppServiceConnection);\r\n    }\r\n}<\/code><\/pre>\n<p>First, we check if the type of activation is <code>AppServiceTriggerDetails<\/code>, since the application might have other background activation entry points. If that&#8217;s the case we retrieve a deferral and we store it as a class variable:<\/p>\n<pre><code class=\"language-csharp\">sealed partial class App : ReactApplication\r\n{\r\n    private BackgroundTaskDeferral appServiceDeferral;\r\n\r\n    public App()\r\n    {\r\n        \/\/ ...\r\n    }\r\n\r\n    \/\/ ...\r\n}<\/code><\/pre>\n<p>The deferral is <a href=\"https:\/\/blogs.windows.com\/windowsdeveloper\/2016\/04\/28\/the-lifecycle-of-a-uwp-app\/\">a concept used by the Universal Windows Platform<\/a> to properly handle asynchronous methods in background tasks. Since, when an asynchronous method is started, its execution is delegated to another thread, the background task might think that the operation is completed so Windows will terminate it. To avoid this scenario, we use a deferral to manually tell to the background task when the operation is really completed, by calling the <code>Complete()<\/code> method at the end. However, in our scenario, we just need to call <code>GetDeferral()<\/code> to get one, but we don&#8217;t actually need to complete it, since we want our channel to stay alive until the application is running. If we don&#8217;t do this, the channel would open, but it would be closed after a few seconds.<\/p>\n<p>The last past of the code introduces a new concept, which are <strong>React Property Bags<\/strong>. This is a feature included in React Native which enables to share key \/ value pairs across an entire React Native application, including its modules. Why do we need it? Since we&#8217;re building a React Native app, the UWP application won&#8217;t contain the actual code which interacts with the App Service, but it will just host the JavaScript layer. As such, the communication will be handled by the native module. Thanks to React Property Bags, we can store a reference to the App Service in the host but let the native module use it.<\/p>\n<p>The code creates a new property bag, which is composed by a namespace (<code>RegistryChannel<\/code>) and a name (<code>AppServiceConnection<\/code>). Then, using the <code>InstanceSettings<\/code> static class, we create the property bag in the current instance, by calling the <code>Set()<\/code> method and passing, as object to store, the App Service channel we have just created.<\/p>\n<h3>The native module<\/h3>\n<p>Now we are ready to interact with the classic Win32 process we have previously built. In a regular UWP scenario, we would have interacted with the App Service directly in the main application. However, in React Native for Windows, the UWP app is just a host for the JavaScript layer, so we need to build a native module to expose the APIs we need to JavaScript.<\/p>\n<p>The next step is to add a native module to your solution. This is well documented in the <a href=\"https:\/\/microsoft.github.io\/react-native-windows\/docs\/native-modules-setup\">official documentation<\/a>. The module I&#8217;m going to build is a C# Windows Runtime Component, but of course you can do the same in C++.<\/p>\n<p>By default, the module will contain two classes: one called <code>ReactPackageProvider<\/code>, which handles the registration in the main app, and one called <code>ReactNativeModule<\/code>, which contains the module definition. The default implementation of the class provided by the template will look like this:<\/p>\n<pre><code class=\"language-csharp\">namespace ReactNativeAppServiceModule\r\n{\r\n[ReactModule(\"ReactNativeAppServiceModule\")]\r\ninternal sealed class ReactNativeModule\r\n{\r\n\r\n    private ReactContext _reactContext;\r\n\r\n    [ReactInitializer]\r\n    public void Initialize(ReactContext reactContext)\r\n    {\r\n        _reactContext = reactContext;\r\n    }\r\n\r\n    [ReactMethod]\r\n    public void sampleMethod(string stringArgument, int numberArgument, Action&lt;string&gt; callback)\r\n    {\r\n        \/\/ TODO: Implement some actually useful functionality\r\n        callback(\"Received numberArgument: \" + numberArgument + \" stringArgument: \" + stringArgument);\r\n    }\r\n}\r\n}<\/code><\/pre>\n<p>The class already includes many elements we&#8217;re going to need, like the <code>[ReactModule]<\/code> attribute to expose the module to JavaScript; the <code>[ReactMethod]<\/code> attribute to expose a method to JavaScript; the <code>[ReactInitializer]<\/code> attribute, which decorates the method that give us access to the <code>ReactContext<\/code> property. This is the object that will contain the property bag we have set in the main application.<\/p>\n<p>Keep everything as it is, but delete the <code>sampleMethod()<\/code> function. We&#8217;re going to replace it with the real methods that we need to expose to JavaScript.<\/p>\n<p>Let&#8217;s start with the first one:<\/p>\n<pre><code class=\"language-csharp\">[ReactMethod(\"launchFullTrustProcess\")]\r\npublic async Task LaunchFullTrustProcessAsync()\r\n{\r\n    await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();\r\n}<\/code><\/pre>\n<p>This method uses the <code>FullTrustProcessLauncher<\/code> API to launch a classic Win32 process from a UWP application. We just need to call it as it is. We&#8217;re going to specify the information about the process to launch later in the manifest. Later, we&#8217;re going to call this method from the JavaScript layer when the application starts.\nBy default, the <code>FullTrustProcessLauncher<\/code> class won&#8217;t be found. The reason is that this API isn&#8217;t included in UWP by default, but it&#8217;s part of the specific extensions for desktop. As such, you have to right click on the native module&#8217;s project, choose <strong>Add reference<\/strong> and, in the <strong>Universal Windows -&gt; Extensions<\/strong> section, click on the latest version of the <code>Windows Desktop Extension for UWP<\/code>.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/react-native\/wp-content\/uploads\/sites\/76\/2022\/11\/desktop-extensions.png\" alt=\"How to enable the Windows Desktop Extensions for UWP\" \/><\/p>\n<p>Let&#8217;s see now the second method:<\/p>\n<pre><code class=\"language-csharp\">[ReactMethod(\"getRegistryKey\")]\r\npublic async Task&lt;string&gt; GetRegistryKey(string key)\r\n{\r\n    var ns = ReactPropertyBagHelper.GetNamespace(\"RegistryChannel\");\r\n    var name = ReactPropertyBagHelper.GetName(ns, \"AppServiceConnection\");\r\n\r\n    var content = _reactContext.Handle.Properties.Get(name);\r\n\r\n    var _connection = content as AppServiceConnection;\r\n\r\n    ValueSet valueSet = new ValueSet\r\n    {\r\n        { \"RegistryKeyName\", key }\r\n    };\r\n\r\n    var result = await _connection.SendMessageAsync(valueSet);\r\n\r\n    string message = result.Message[\"RegistryKeyValue\"].ToString();\r\n    return message;\r\n}<\/code><\/pre>\n<p>This is the method that we&#8217;ll invoke from the React Native application when we want to retrieve the value of a registry key. Through the <code>ReactContext<\/code> object we have retrieved in the initialization of the module, we can use the <code>Properties<\/code> collection to access to the property bags. We look for one called <code>AppServiceConnection<\/code> in the <code>RegistryChannel<\/code> namespace, which contains the reference to our App Service channel.\nOnce we have the channel, we can use it to send a message with the name of the key we want to retrieve (encapsulated in a <code>ValueSet<\/code> object) to the classic Win32 process using the <code>SendMessageAsync()<\/code> method. The message will be received by the Win32 process, which will retrieve the value of the requested key from the registry, and then it will send it back to our native module, as result of the <code>SendMessageAsync()<\/code> method. The response will be included in the <code>Message<\/code> collection with key <code>RegistryKeyValue<\/code>: we simply return this value to the JavaScript layer, so that the React Native app can display it.<\/p>\n<p>There&#8217;s one last step to do. Since we have manually created this module, we have also to manually register it in the main host application. As first step, right click on the host app, choose <strong>Add reference<\/strong> and select the native module. Then move to the <code>App<\/code> class and, in the constructor, add the following line before the <code>InitializeComponent()<\/code> method is invoked:<\/p>\n<pre><code class=\"language-csharp\">PackageProviders.Add(new ReactNativeAppServiceModule.ReactPackageProvider());<\/code><\/pre>\n<p>In case you have created the native module with a different name, make sure to replace <code>ReactNativeAppServiceModule<\/code> with the correct namespace.<\/p>\n<h3>The Windows Application Packaging Project<\/h3>\n<p>The last step before we can try our solution is to add a Windows Application Packaging Project, which will help us to put together inside the same package the host UWP app and the classic Win32 process. Right click on the solution, choose <strong>Add -&gt; New project<\/strong> and look for the template called <strong>Windows Application Packaging Project<\/strong>. Once you have added it, right click on it and choose <strong>Add reference<\/strong>. Now you have to select two projects from your solution: the React Native host UWP app and the classic Win32 process. Once it&#8217;s done, expand the <strong>Applications<\/strong> node, right click on the name of the host UWP app and choose <strong>Set as entry point<\/strong>. This will ensure that, when you click on the app icon in the Start menu, the main React Native app will be the one being launched.<\/p>\n<p>Now we have to make a few changes to the manifest. One of the important differences you have to be aware when you introduce the Windows Application Packaging Project in a scenario like ours is that its manifest becomes the main one. As such, if you have previously customized the manifest of your host UWP app (for example, by adding assets for the icons, changing the identity or adding a few capabilities), you will have to port them in the manifest of the WAP project.\nFor this exact reason, make sure to make the following changes in the <code>Package.appxmanifest<\/code> file of the WAP project and not in the one of the host UWP app.<\/p>\n<p>The first change is declaring the App Service. If you remember, previously in code we had to specify two information to connect to the App Service from the Win32 classic process: the name and the Package Family Name. The name is defined exactly in the manifest. Double click on the <strong>Package.appxmanifest<\/strong> file, move to the <strong>Declarations<\/strong> tab and, from the dropdown, choose <strong>App Service<\/strong> and click <strong>Add<\/strong>. The only required field is <strong>Name<\/strong>, which we have to fill with the same name that we have previously specified in code, which is <code>RegistryService<\/code>. Since it&#8217;s an in-proc App Service, we don&#8217;t have to specify any other information.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/react-native\/wp-content\/uploads\/sites\/76\/2022\/11\/appservice-manifest.png\" alt=\"How to declare an App Service in the manifest\" \/><\/p>\n<p>The second change is declaring which is the classic Win32 process that we want to launch when we use the <code>FullTrustLauncher<\/code> API. This feature isn&#8217;t supported by the Visual Studio UI, so you&#8217;ll have to right click on the <code>Package.appxmanifest<\/code> file and choose <strong>View code<\/strong>. You will find a section called <code>Extensions<\/code>, where the App Service has been declared. Exactly below, add the following entry:<\/p>\n<pre><code class=\"language-xml\">&lt;Extensions&gt;\r\n  &lt;uap:Extension Category=\"windows.appService\"&gt;\r\n    &lt;uap:AppService Name=\"RegistryService\"\/&gt;\r\n  &lt;\/uap:Extension&gt;\r\n  &lt;desktop:Extension Category=\"windows.fullTrustProcess\" Executable=\"RegistryApp\\RegistryApp.exe\" \/&gt;\r\n&lt;\/Extensions&gt;<\/code><\/pre>\n<p>The <code>Executable<\/code> attribute specifies the path of the classic Win32 process inside the package. By default, the WAP project puts all the build outputs inside a folder with the same name of the project. As such, our classic Win32 app will be available at the path <code>RegistryApp\\RegistryApp.exe<\/code>.\nTo make this extension working, you will have also to declare the <code>desktop<\/code> namespace at the top, since it isn&#8217;t included by default:<\/p>\n<pre><code class=\"language-xml\">&lt;Package\r\n  xmlns=\"http:\/\/schemas.microsoft.com\/appx\/manifest\/foundation\/windows10\"\r\n  xmlns:uap=\"http:\/\/schemas.microsoft.com\/appx\/manifest\/uap\/windows10\"\r\n  xmlns:desktop=\"http:\/\/schemas.microsoft.com\/appx\/manifest\/desktop\/windows10\"\r\n  IgnorableNamespaces=\"uap desktop\"&gt;<\/code><\/pre>\n<p>The final change we would need to make is to add a capability called <strong>runFullTrust<\/strong>, which enables our package to include a classic Win32 component and not just a UWP application. However, the default manifest included in the WAP project already defines that. You can see it in the <code>Capabilities<\/code> section of the manifest:<\/p>\n<pre><code class=\"language-xml\">&lt;Capabilities&gt;\r\n  &lt;Capability Name=\"internetClient\" \/&gt;\r\n  &lt;rescap:Capability Name=\"runFullTrust\" \/&gt;\r\n&lt;\/Capabilities&gt;<\/code><\/pre>\n<h3>The React Native application<\/h3>\n<p>Finally, we now have all the pieces of the puzzle and we can start working on the JavaScript layer. As first step, we need to launch the classic Win32 process when the React Native application starts. If you&#8217;re using a functional component, you can use the <code>useEffect<\/code> hook; if you&#8217;re using a class component, you can use the <code>componentDidMount<\/code> event. In my case, I&#8217;m going for the first option, so I added in my application the following function:<\/p>\n<pre><code class=\"language-javascript\">useEffect(() =&gt; {\r\n  async function launchProcess() {\r\n    await NativeModules.ReactNativeAppServiceModule.launchFullTrustProcess();\r\n  }\r\n  launchProcess();\r\n}, []);<\/code><\/pre>\n<p>If you have used native modules before, the code should be easy to understand. We use the <code>NativeModules<\/code> API in React to access to our native module, by specifying its name (<code>ReactNativeAppServiceModule<\/code>, which we have set using the <code>[ReactModule]<\/code> attribute) and the method (<code>launchFullTrustProcess()<\/code>, which we have set using the <code>[ReactMethod]<\/code> attribute).<\/p>\n<p>The outcome is that, when you launch the main app from the Start menu, also the classic Win32 process will be launched. However, since it doesn&#8217;t have any UI, it will run in background. You&#8217;ll be able to see it using Task Manager:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/react-native\/wp-content\/uploads\/sites\/76\/2022\/11\/registryapp.png\" alt=\"The Win32 classic process running in background in Task Manager\" \/><\/p>\n<p>Now we need to store two information in the component&#8217;s state: the name of the registry key we want to get (which will be filled by the user using a <code>TextInput<\/code> control) and its value, which will be returned by our native module. Since I&#8217;m using a functional component, I&#8217;m going to use the <code>useState<\/code> hook:<\/p>\n<pre><code class=\"language-javascript\">const [registryKeyName, setRegistryKeyName] = useState(\"\");\r\nconst [registryKeyValue, setRegistryKeyValue] = useState(\"\");<\/code><\/pre>\n<p>Now let&#8217;s define the function that will invoke the native module to get the registry key and will store the result in the state:<\/p>\n<pre><code class=\"language-javascript\">const getRegistryKey = async () =&gt; {\r\n  var result = await NativeModules.ReactNativeAppServiceModule.getRegistryKey(\r\n    registryKeyName\r\n  );\r\n  setRegistryKeyValue(result);\r\n};<\/code><\/pre>\n<p>The approach is the same as the previous one: the only difference is that, this time, we&#8217;re invoking the <code>getRegistryKey()<\/code> function, which requires as parameter the name of the key we want to retrieve from the <code>HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion<\/code> hive.<\/p>\n<p>Now let&#8217;s build a minimal UI: a <code>TextInput<\/code> control, which will read the name of the registry key and store it in the state; a <code>Button<\/code>, which will invoke the <code>getRegistryKey()<\/code> function; a <code>Text<\/code>, which will display the value returned by the function.<\/p>\n<pre><code class=\"language-jsx\">&lt;View&gt;\r\n  &lt;TextInput onChangeText={(text) =&gt; setRegistryKeyName(text)} \/&gt;\r\n  &lt;Button title=\"Get registry key\" onPress={getRegistryKey} \/&gt;\r\n  &lt;Text&gt;{registryKeyValue}&lt;\/Text&gt;\r\n&lt;\/View&gt;<\/code><\/pre>\n<h3>Running the app<\/h3>\n<p>We&#8217;re ready to test our work! First, go to Visual Studio, right click on the Windows Application Packaging Project and choose Deploy. You might get the following error:<\/p>\n<pre><code class=\"language-plaintext\">Error Task 'AddProjectMetadata' failed. The expression \"[MSBuild]::MakeRelative(C:\\ReactCSharp, *Undefined*)\" cannot be evaluated. Illegal characters in path. C:\\ReactCSharp\\node_modules\\react-native-windows\\PropertySheets\\Autolink.props\r\nReactCSharp.Package C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\MSBuild\\Microsoft\\DesktopBridge\\Microsoft.DesktopBridge.targets 408\r\nError MSB4184 The expression \"[MSBuild]::MakeRelative(C:\\ReactCSharp, *Undefined*)\" cannot be evaluated. Illegal characters in path. C:\\ReactCSharp\\node_modules\\react-native-windows\\PropertySheets\\Autolink.props ReactCSharp.Package C:\\ReactCSharp\\node_modules\\react-native-windows\\PropertySheets\\Autolink.props 12<\/code><\/pre>\n<p>If that&#8217;s a case, this is a known issue that has already been addressed, but the fix isn&#8217;t available yet in the latest stable React Native for Windows version. However, the workaround is easy. Open the file in the path <code>node_modules\\react-native-windows\\PropertySheets\\Autolink.props<\/code> and replace the following line:<\/p>\n<pre><code class=\"language-xml\">&lt;AutolinkCommandArgs Condition=\"'$(AutolinkCommandArgs)' == '' And '$(SolutionPath)' != '' And '$(ProjectPath)' != ''\"&gt;--check --sln $([MSBuild]::MakeRelative($(AutolinkCommandWorkingDir), $(SolutionPath))) --proj $([MSBuild]::MakeRelative($(AutolinkCommandWorkingDir), $(ProjectPath)))&lt;\/AutolinkCommandArgs&gt;<\/code><\/pre>\n<p>with<\/p>\n<pre><code class=\"language-xml\">&lt;AutolinkCommandArgs Condition=\"'$(AutolinkCommandArgs)' == '' And '$(SolutionPath)' != '' And '$(SolutionPath)' != '*Undefined*' And '$(ProjectPath)' != ''\"&gt;--check --sln $([MSBuild]::MakeRelative($(AutolinkCommandWorkingDir), $(SolutionPath))) --proj $([MSBuild]::MakeRelative($(AutolinkCommandWorkingDir), $(ProjectPath)))&lt;\/AutolinkCommandArgs&gt;<\/code><\/pre>\n<p>If you&#8217;re building the project for the first time, it will take a while. Once it&#8217;s deployed, you will find two entries in the Start menu: one for the base host app (for example, <code>appservicedemo<\/code>) and one for the WAP project (for example, <code>appservicedemo.Package<\/code>). Don&#8217;t worry, when you will generate a MSIX package for release this won&#8217;t happen anymore. However, if you want to remove this confusion also while you&#8217;re debugging, just go back to Visual Studio, choose <strong>Build -&gt; Configuration Manager<\/strong> and make sure that the <strong>Deploy<\/strong> flag is turned on only for the WAP project.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/react-native\/wp-content\/uploads\/sites\/76\/2022\/11\/defaultproject.png\" alt=\"The Visual Studio configuration to deploy only the WAP project\" \/><\/p>\n<p>Before clicking on the Start menu entry for the WAP project, make sure to open a terminal on the folder which contains your project and run <code>yarn start<\/code> to launch the Metro packager.\nIf everything went well, the UI of the app should show up. Specify in the text box the name of one of the keys in the <code>HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion<\/code> registry hive (for example, <code>BuildLab<\/code>) and press the button. If you did everything correctly, the value of the key will be displayed:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/react-native\/wp-content\/uploads\/sites\/76\/2022\/11\/final-app.png\" alt=\"The final application running\" \/><\/p>\n<p>If you want to create a package for release (to publish on the Microsoft Store or sideload on another machines), make sure to start the wizard (<strong>Publish &#8211;&gt; Create App Packages<\/strong>) from the WAP project and not from the host app, otherwise the classic Win32 process won&#8217;t be included.<\/p>\n<h3>Conclusion<\/h3>\n<p>It was a long journey, but now we have a React Native for Windows application which can interact with the Win32 ecosystem. In this article we built a sample scenario based on registry access, but the opportunities are unlimited! You can integrate SDKs which aren&#8217;t supported by the Universal Windows Platform; or enhance your React Native application with features that otherwise won&#8217;t be supported. You can find the sample project built for this article <a href=\"https:\/\/github.com\/microsoft\/react-native-windows-samples\/tree\/main\/samples\/AppServiceDemo\">on GitHub<\/a>.<\/p>\n<h3>Credits<\/h3>\n<p>Icons used in the architecture:<\/p>\n<ul>\n<li><a href=\"https:\/\/iconscout.com\/icons\/react\">React Flat Icon<\/a> by <a href=\"https:\/\/iconscout.com\/contributors\/icon-mafia\">Icon Mafia<\/a><\/li>\n<li><a href=\"https:\/\/iconscout.com\/icons\/windows\">Windows Flat Logo Icon<\/a> <a href=\"https:\/\/iconscout.com\/contributors\/icon-mafia\">Icon Mafia<\/a><\/li>\n<li><a href=\"https:\/\/iconscout.com\/icons\/package\">Package Colored Outline Icon<\/a> by <a href=\"https:\/\/iconscout.com\/contributors\/ferdizzimo\">Vichanon Chaimsuk<\/a><\/li>\n<\/ul>\n<hr \/>\n<p>If you\u2019re interested in getting started with React Native for Windows, check out our website at <a href=\"https:\/\/aka.ms\/reactnative\">aka.ms\/reactnative<\/a>.<\/p>\n<p>You can also follow us on Twitter <a href=\"https:\/\/twitter.com\/reactnativemsft\">@ReactNativeMSFT<\/a> to keep up to date on news, feature roadmaps, and more.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How to use Win32 features from a React Native for Windows application<\/p>\n","protected":false},"author":777,"featured_media":156,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[2,3,8,10,6],"class_list":["post-139","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-react-native","tag-react-native","tag-react-native-windows","tag-tutorial","tag-win32","tag-windows"],"acf":[],"blog_post_summary":"<p>How to use Win32 features from a React Native for Windows application<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/posts\/139","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/users\/777"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/comments?post=139"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/posts\/139\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/media\/156"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/media?parent=139"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/categories?post=139"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/tags?post=139"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}