C# - Cortana voice commands to launch external application - c#

I am trying to integrate different files and links to the Cortana voice commands using C#. Most of the applications are working fine when i copy those particular files in the Cortana voice command application folder but i am unable to launch an *.exe file (copied in the same folder). The usual error i am getting is access denied even after launching VS as admin. I am attaching the code line along with the error screenshot.
{"Abrir NAV", (Action)(async () => {
StorageFile file = await Package.Current.InstalledLocation.GetFileAsync(#"Microsoft.Dynamics.Nav.Client.exe");
await Launcher.LaunchFileAsync(file);
})
},
Cortana Error

You could not launch executable file from your UWP app directly.
MSDN document has mentioned this point:
This API also imposes several restrictions on what types of files it can launch. Many file types that contain executable code, for example .exe, .msi, and .js files, are blocked from launching. This restriction protects users from potentially malicious files that could modify the system. From launcher documentation.
According to your description, your ".exe" file was contained in your UWP project. So, you could use the FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync() method to activate the full-trust Win32 component of an application from a Universal Windows app component in the same application package.
Please note the "full-trust" concept. You would need to declare "full-trust" for your ".exe" file in "Package.appxmanifest". For example:
<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:rescap= "http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
IgnorableNamespaces="uap mp rescap desktop">
<Applications>
<Application>
...
<Extensions>
<desktop:Extension Category="windows.fullTrustProcess" Executable="MyFiles\ConsoleApp1.exe"/>
</Extensions>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust"/>
</Capabilities>
</Package>
Then, in code, you could call this method to launch that ".exe" file.
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();

Related

Problems with AppServiceConnection when a third project is the package's entry point

I have a solution consisting of a Windows Application Packaging Project that groups two other projects:
A UWP project, named UwpUI, which is the entry point of the package. It can also be launched by protocol activation.
A .NET framework project, named FrameworkLogic, declared as Fulltrust.
An AppServiceConnection connects the two projects and allows a bi-directional communication between them.
It works using a well known pattern, described in this blog post by Stefan Wick:
Uwp with desktop extension-part 3
The package.appxmanifest (of my app) contains this.
<Extensions>
<desktop:Extension
Category="windows.fullTrustProcess"
Executable="FrameworkLogic\FrameworkLogic.exe">
</desktop:Extension>
<uap:Extension Category="windows.appService">
<uap:AppService Name="BidirectionalCom" />
</uap:Extension>
<uap:Extension Category="windows.protocol" Executable="UwpUI.exe"
EntryPoint="UwpUI.App">
<uap:Protocol Name="protoLaunch" />
</uap:Extension>
The uwp starts the fulltrust process like that:
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
In the entrypoint of the fulltrust .net framework, the connection is made with:
Connection = new AppServiceConnection();
Connection.AppServiceName = "BidirectionalCom";
var familyName = Package.Current.Id.FamilyName;
Connection.PackageFamilyName = familyName;
Connection.RequestReceived += Connection_RequestReceived;
Connection.ServiceClosed += Connection_ServiceClosed;
AppServiceConnectionStatus status = await Connection.OpenAsync();
opening the connection result in a call on the uwp side in the method
OnBackgroundActivated(BackgroundActivatedEventArgs args)
Where a reference to the connection is kept. Everything works.
The new requirement is this : set a console app (or a WPF app) as the package entry point.
If the package is launched without arguments, the new console app launches the uwp project by protocol activation. The bi-directional communication between the UWP and the .NET framework is instantiated and used.
If the app is launched with arguments (in my case, from the jumplist), then only the console app is used.
Adding the new project and setting it as the package entry point results in the following error:
DEP0700: Registration of the app failed. [0x80073CF6] AppxManifest.xml(44,10): error 0x80080204: Cannot register the package because the extension is missing an EntryPoint or StartPage attribute.
The solution on this SO post got me further.
Seems logical : the appservice must be defined under the project that uses it, which is not the package's entrypoint anymore.
My package manifest now include a second app (UwpUI) and looks like this:
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
<uap:VisualElements DisplayName="Home" Description="Package" BackgroundColor="white" Square44x44Logo="Images\Square44x44Logo.png">
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.protocol" Executable="UwpUI.exe" EntryPoint="UwpUI.App" ><uap:Protocol Name="protoLaunch" />
</uap:Extension>
<desktop:Extension Category="windows.fullTrustProcess" Executable="FrameworkLogic\FrameworkLogic.exe">
</desktop:Extension>
</Extensions>
</Application>
<Application Id="App2" Executable="UwpUI.exe" EntryPoint="UwpUI.App">
<uap:VisualElements AppListEntry="none" DisplayName="Home" Description="Package" BackgroundColor="white" Square44x44Logo="Images\Square44x44Logo.png" Square150x150Logo="Images\Square150x150Logo.png">
<uap:DefaultTile ShortName="-TestApp-" Square71x71Logo="Images\SmallTile.png" Wide310x150Logo="Images\Wide310x150Logo.png" Square310x310Logo="Images\LargeTile.png"/>
<uap:SplashScreen BackgroundColor="white" Image="Images\SplashScreen.png" a:Optional="true"/>
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.appService" >
<uap:AppService Name="BidirectionalCom" uap4:SupportsMultipleInstances="false"/>
</uap:Extension>
</Extensions>
</Application>
Doing that works as far as launching the fulltrust project, and establishing the connection, with a call to OnBackgroundActivated(BackgroundActivatedEventArgs args). There, I can succesfuly send a request and get an answer.
But I hit two major problems:
Any (static or instance) field or event instantiated in app.xaml.cs of the UwpUI project is null when it is called from another method, including the reference to the connection.
Prior to the modification, in debug mode at least, I could set breakpoints in both the UWP and the .NET framework project by doing 'detach all', then 'attach to process'. Now When attaching, the .NET framework project is greyed out.
Any idea what I'm missing? Problem 1 is the worse, since it breaks the app, but I need to solve the two.
Thank you.
EDIT : When looking at Task Manager, I see two processes with the same entry point (UwpUI.exe). Indeed, breakpoints show me that the call to the uwp constructor ( App.xaml.cs.App()), is called twice.
That certainly explains problem 1: fields are set in one instance and are of course null in the second instance.
Seems I need to structure my manifest differently, but I have yet to find how.
EDIT: Example project Here

UWP LaunchFullTrustProcessForCurrentAppAsync - EXE file not found

We are creating a UWP application which is intended for Side loading only.
At various times this application needs to reboot the PC (it's desktop only), to do this we intend to use LaunchFullTrustProcessForCurrentAppAsync() to call a simple external EXE which uses Process.Start("shutdown") to reboot the PC.
We have created the EXE called RebootPC.exe and on it's own it works fine.
We now include it in our UWP project:
First we add the desktop and rescap namespaces to our project and we also add rescap to our IgnorableNamspaces
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp uap5 rescap">
Then, we then modify the Extension section to include our EXE, we know we cannot put the EXE in our project root as C# compiler removes it so we have put it in a sub folder (in this case \Assets). We also set the EXE's type to 'Content' and 'Copy always' in the Solution explorer
<desktop:Extension Category="windows.fullTrustProcess" Executable="Assets\RebootPC.exe">
<desktop:FullTrustProcess>
<desktop:ParameterGroup GroupId="rebooter" Parameters=""/>
</desktop:FullTrustProcess>
</desktop:Extension>
finally in the manifest we add rescap to the Capabilities section - we know it has to be first in the list otherwise you get a manifest error when packaging
<Capabilities>
<rescap:Capability Name="runFullTrust"/>
<Capability Name="internetClient" />
<DeviceCapability Name="bluetooth" />
<DeviceCapability Name="radios" />
OK, so the manifest is changed. We now go to our C# code:
In that we perform the following:
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
{
try
{
await Windows.ApplicationModel.FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
When we build and run the project in Visual Studio it seems to work fine, under the intended circumstances the PC will reboot as intended.
The problem comes when we try to package it for installation on other PCs. We use Store->Create App Packages (remember this application is for side loading only).
The creation of the package works fine and we can install it on other PCs with no problem. The problem is that when we run the Application and it comes time to run the external EXE to reboot the PC a command window opens but we get an exception saying "System can't find c:\users.......\Assets\RebootPC.exe"
So, even though the packaging is done without error and even though we have set the properties of RebootPC.exe to 'Content' and 'Copy always' it is either not being included in the package or not being installed along with the App?
So, does anyone know how we can check if it is being included in the package? and if so how we can check if and where it is being installed on the target machine? or has anyone else had this issue and found the solution?
This has had us baffled for days and is driving us crazy!!!
UPDATE: I think the issue may not be that RebootPC.exe can't be found but rather shutdown.exe - If this is the case then it's a bit of a school boy error!!!
Anyway, I will sort this and see if that fixes the issue
I will leave the rest of the question up as it might provide useful information for others
As Mentioned in the official sample the exe file has to in the Appx folder of your project
Make sure the RebootPC.exe was copied to the Appx folder -
UWP\bin\x64\Release\AppX if not rebuild the solution or copy it
manually.
https://github.com/Microsoft/DesktopBridgeToUWP-Samples/tree/master/Samples/AppServiceBridgeSample#builddeploy-and-run-the-sample
try
{
await Windows.ApplicationModel.FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("rebooter");
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}

FindPackagesForCurrentPublisher in Windows 10 for PC

Is there a way to use or an alternative to InstallationManager.FindPackagesForCurrentPublisher? It looks like it is only for the phone.
I know you can launch an app by creating and then launching a URI, but I need to know if the app I want to launch is installed.
EDIT:
The app I want to launch is by the same publisher.
If we use the LaunchUriAsync(Uri) method to launch an app, system will firstly try to launch the installed app which registered this protocol, if the target app is not installed, then it will open the Store app and show the recommended apps which registered this protocol.
FindPackagesForCurrentPublisher method can only find the app packages with the same publisher ID as your app, for other app which is not with the same publisher, you will need to use FindPackages method, and this method requires ID_CAP_OEM_DEPLOYMENT. For desktop, there is no method now, you need special access to do that work, otherwise you can't break the sand box of UWP app.
But if your app won't be published into the Store, there is method which use PackageManager class to find the installed package. To use this class, you will need to add packageManagement capability into your app's manifest like this:
<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:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp rescap">
...
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="packageManagement" />
</Capabilities>
</Package>
For this capability, you can refer to Special and restricted capabilities.
At last you can use this class in your app, for example list all the installed packages:
var packageManager = new PackageManager();
IEnumerable<Windows.ApplicationModel.Package> packages = (IEnumerable<Windows.ApplicationModel.Package>)packageManager.FindPackagesForUser("");
var list = packages.ToList();

TypeLoadException using WinRT Brokered Component

I am building a Windows Store App using a brokered component. The brokered component is meant to enable interaction with an RFID reader on the device. When I try to initialize an instance of the class exposed by the brokered component, I received a System.TypeLoadException with the message Could not find or load a type. (Exception from HRESULT: 0x80131522).
I'm working against a clean installation of Windows 8.1 Professional on two different tablet devices. Both are currently experiencing this issue. The solution has worked in the past; something I've done recently must be causing this. I've also verified that the RFID reader can be accessed using a sample application provided by the hardware vendor.
My Package.appxmanifest file looks similar to this:
<Package ...>
...
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>clrhost.dll</Path>
<ActivatableClass ActivatableClassId="MyApp.RFID.Component.RfidDevice" ThreadingModel="STA">
<ActivatableClassAttribute Name="DesktopApplicationPath" Type="string" Value="C:\Program Files (x86)\MyApp\RFID" />
</ActivatableClass>
</InProcessServer>
</Extension>
</Extensions>
</Package>
The solution is being built to target an x86 platform. I've registered my components on the target device under C:\Program Files (x86)\MyApp\RFID using the following commands (per this whitepaper):
icacls . /T /grant "ALL APPLICATION PACKAGES":RX
regsvr32 MyApp.RFID.Proxy.dll
I've installed the Visual Studio 2013 x86 Redistributable Package on the target device. I've also placed an additional dependency .dll in the same directory, just as I have been doing during all of my development.
Some other things I've tried:
Using %PROGRAMFILES% instead of C:\Program Files (x86) as the value for the ActivatableClassAttribute in the manifest.
Using 'STA', 'MTA', and 'Both' as the threading models.
Added a trailing slash to the ActivatableClassAttribute value path.
Completely uninstalled everything and tried again from scratch.
Explicitly add an empty default constructor to the RfidDevice class.

Brokered components when using TFS Build

When using TFS to build my application, it fails when I have an application with Brokered components.
Here is what I am using in my Package.appxmanifest, and it works when I build/run locally. How can I still build/deploy using TFS and keep my brokered components? Is this possible?
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>clrhost.dll</Path>
<ActivatableClass ActivatableClassId="BrokeredRuntimeComponent.{ClassName}" ThreadingModel="MTA">
<ActivatableClassAttribute Name="DesktopApplicationPath"
Type="string"
Value="C:\Source\{AppName}\Debug\BrokeredRuntimeComponentProxy" />
</ActivatableClass>
</InProcessServer>
</Extension>
</Extensions>
When I run the build, I get the following error. I do not have access to run the regsvr32 /s on our TFS. Is this something that needs to be done on every client or can it be done on the build server and run on every device? I think it might work if it's possible to get the build service to run as administrator. Is this even possible?
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppCommon.targets (1620): Failed to register output. Please try enabling Per-user Redirection or register the component from a command prompt with elevated permissions.
Please let me know if anything I've put here is unclear so I can hopefully clarify.
You need to have everything installed on your build server that your need to run a build locally. If you need certain registered components then that needs done in advance or at build time.
If at build time then the account that TF build runs under needs permission to perform that action.

Categories