C# uwp launch apps - c#

With this code below:
await Windows.System.Launcher.LaunchUriAsync(new Uri(#"ms-windows-store://review/?ProductId=9wzdncrfj2wl"));
I am opening Facebook app in Microsoft Store. There is a Launch button on that page. With it user runs the application.
How can I run the application with it's product ID?
I managed to open app with this code:
await Windows.System.Launcher.LaunchUriAsync(new Uri("fb:post?text=foo"));
But I want to open it with ID.
I have found this code, but it is not working:
await Windows.System.Launcher.LaunchUriAsync(new Uri(#"ms-windows-store://pdp/?ProductId=9wzdncrfj2wl"));
How to open installed app with ID? Or, if there is another way to check if App is installed, if it is then launch it, if it is not then show it in store, so user can install it manually. The app I am developing is Windows 10 UWP...
I have a situation where there is no URI for application, so I have to open it via it's ProductID or ProductFamily...
So, this is the shortcut's target that is opening that app:
C:\Windows\explorer.exe shell:AppsFolder\A88BB54F.N1info_gvc78jvcn5cg0!App
Is there any chance I can use this in UWP app to launch app?
Does anyone got the link from LAUNCH button in Windows Store? So, I would put that in URI, just like link from GET button:
ms-windows-store:PDP?PFN=A88BB54F.N1info_gvc78jvcn5cg0&referrer=unistoreweb&webig=39694073-f9af-436f-a82b-abb9d9f644f0&muid=097C7AA3CA2C6EE22D237359CE2C689A&websession=c9916902dd014ec2b5a9e0390a28c26d
I am using it like this:
await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-windows-store:PDP?PFN=A88BB54F.N1info_gvc78jvcn5cg0&referrer=unistoreweb&webig=39694073-f9af-436f-a82b-abb9d9f644f0&muid=097C7AA3CA2C6EE22D237359CE2C689A&websession=c9916902dd014ec2b5a9e0390a28c26d"));
and it is showing app in store.
Thanx.

It is possible by using Package Manager:
using Windows.Management.Deployment;
var app = await GetAppByPackageFamilyNameAsync("Microsoft.WindowsCalculator_8wekyb3d8bbwe");
if(app != null)
{
await app.LaunchAsync();
}
static async Task<AppListEntry> GetAppByPackageFamilyNameAsync(string packageFamilyName)
{
var pkgManager = new PackageManager();
var pkg = pkgManager.FindPackagesForUser("", packageFamilyName).FirstOrDefault();
if (pkg == null) return null;
var apps = await pkg.GetAppListEntriesAsync();
var firstApp = apps.FirstOrDefault();
return firstApp;
}
And add one capability to the Package.appxmanifest :
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns:...
xmlns:rescap = "http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="... rescap">
...
<Capabilities>
...
<rescap:Capability Name="packageQuery" />
</Capabilities>
</Package>
Learn more about restricted capabilities: https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations#restricted-capabilities

If you want to launch one app from another, the target app must have registered URI activation and handle that case. More about that you can read at MSDN.
Lots of apps in the store has registered URI scheme, there are some lists over the internet, like this one, however I'm not sure if it's actual and which apps work with UWP.

Or, if there is another way to check if App is installed, if it is then launch it, if it is not then show it in store, so user can install it manually.
You could call Launcher.QueryUriSupportAsync to see if the app is installed. This method will return LaunchQuerySupportStatus enumeration value, you could decide to open the app or windows store by this value.
Please check the following code for details:
var ret = await Windows.System.Launcher.QueryUriSupportAsync(new Uri("fb:post?text=foo"), Windows.System.LaunchQuerySupportType.Uri);
if (ret == LaunchQuerySupportStatus.Available)
{
await Windows.System.Launcher.LaunchUriAsync(new Uri("fb:post?text=foo"));
}
else
{
await Windows.System.Launcher.LaunchUriAsync(new Uri(#"ms-windows-store://pdp/?ProductId=9wzdncrfj2wl"));
}

Related

How do I programmatically add a file to a fileupload control from a windows form to a webpage

I am using WebView2 in a C# windows application and I want to be able to upload screen captures.
I capture the screen and save it to a file (jpg) on the local hard drive. I want to attach this file (upload) it to the FILEUPLOAD control on a web page being displayed on a windows form using WebView2.
I was using CEFSHARP browser and was using DOM to upload the file before we switched to WebView2.
CEFSHAPRP had the DOM objects wrapped in the browser control so it was very
easy to use this code :
if (client == null)
{
client = browser.GetDevToolsClient();
dom = client.DOM.GetDocumentAsync();
}
await Task.Run(async () =>
{
QuerySelectorResponse querySelectorResponse = await client.DOM.QuerySelectorAsync(dom.Result.Root.NodeId, "#fileupload");
_ = client.DOM.SetFileInputFilesAsync(new string[] { filename }, querySelectorResponse.NodeId);
});
I do not see anything like this built into the WebView2 control. I did see that WebView has another nuget called WebView2.DOM but it requires me to convert my entire project from .NET framework 4.7.2 to .netCore.
Any help would be greatly appreciated. I am very new to WebView2 and cannot see how I can access the DOM to make this happen. I am using .net framework 4.7.2
******* June 17 Update *****
I installed the Microsoft.Web.WebView2.DevToolsProtocolExtension and tried to use the existing framework I already had working with CEFSHARP.
DevToolsProtocolHelper helper = webView21.CoreWebView2.GetDevToolsProtocolHelper();
Task<DOM.Node> t = helper.DOM.GetDocumentAsync(-1,false);
await Task.Run(async () =>
{
var querySelectorResponse = await helper.DOM.QuerySelectorAsync(t.Result.NodeId, "#fileupload");
_ = helper.DOM.SetFileInputFilesAsync(new string[] { filename }, querySelectorResponse);
});
It gives me the following error when I try to execute the line :
var querySelectorResponse = await helper.DOM.QuerySelectorAsync(t.Result.NodeId, "#fileupload");
Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Web.WebView2.Core.Raw.ICoreWebView2'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{76ECEACB-0462-4D94-AC83-423A6793775E}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
Any ideas. Thank you for all the advice and help I have received already.
I believe there would be three ways to do this;
Get the screen co-ordinates of the button, and then using send keys send an enter key to open the dialog. Then (currently webview2 cannot intercept this dialog like CefSharp) you would need to use the WinAPI to manipulate the file dialog window.
I have used 1 before. It is a little unreliable with the send keys and in waiting for the dialog to appear and then getting the timing right with the dialog.
Using javascript you should be able to add to the filelist files and then add them to the element. I have not tried this with Webview2.
Finally, and the one you already know can be used. In your question here you use DOM.SetFileInputFilesAsync which as amaitland pointed out comes from the chrome devtools protocol.. WebView2 also supports the Chrome Devtools protocols so you can effectively use the same code you already know.

How to self-register a standalone desktop C# WPF app (distributed as an exe) for local toast notifications?

We have a desktop Windows app (written in WFP/C#) that we distribute as a single .exe file with no installer (it bundles all its dependencies via a Fody/Costura plugin).
We would like to integrate a local Action Center toast functionality where the app can display a toast and respond to it when it's clicked.
Displaying the toast is straightforward and can be done by using the Microsoft.Toolkit.Uwp.Notifications nuget package. However, in order to actually receive proper notifications when the toast is clicked in the Action Center (as opposed to the balloon tip) we need to register with notification platform.
The guide on how to do this seems to be focused on apps with an installer (e.g. Wix): https://learn.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop?fbclid=IwAR2AoHRKI88VNGRG-pTUytwhkMuovWT4bEr0RoXEayWpWsoGlghtZeq4Mo4#step-4-register-with-notification-platform
The specific task we're trying to achieve is, from the documentation:
If you're using classic Win32 (or if you support both), you have to declare your Application User Model ID (AUMID) and toast activator CLSID (the GUID from step #3) on your app's shortcut in Start.
How can we do it without writing an installer? We would like our app to do this registration on first run.
Note: the app already has provisions for elevating itself through UAC if needed by restarting itself in Administrator context.
Additional references: WPF native windows 10 toasts
[Update]
I managed to follow the instructions in https://learn.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast-desktop
and https://learn.microsoft.com/en-us/windows/win32/shell/enable-desktop-toast-with-appusermodelid to put together what should have been a working solution, but in the end, clicking on toasts in the Action Center does not trigger OnActivated() in my NotificationActivatior.
Salient points:
Sending notification
var toast = new ToastNotification(toastXml);
DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
Registration:
string shortcutPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Programs),
"Toasty.lnk");
DesktopNotificationManagerCompat.RegisterAumidAndComServer
<MyNotificationActivator>(AppName);
DesktopNotificationManagerCompat.RegisterActivator
<MyNotificationActivator>();
if (!File.Exists(shortcutPath))
{
ShortcutManager.RegisterAppForNotifications(
shortcutPath,
Assembly.GetExecutingAssembly().Location,
null,
AppName,
ActivationId);
}
Creating a shortcut
public static void RegisterAppForNotifications(
string shortcutPath,
string appExecutablePath,
string arguments,
string appName,
string activatorId)
{
var shellLinkClass = new ShellLinkCoClass();
IShellLinkW shellLink = (IShellLinkW)shellLinkClass;
shellLink.SetPath(appExecutablePath);
IPropertyStore propertyStore = (IPropertyStore)shellLinkClass;
IPersistFile persistFile = (IPersistFile)shellLinkClass;
if (arguments != null)
{
shellLink.SetArguments(arguments);
}
// https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-id
propertyStore.SetValue(
new PropertyKey("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3", 5),
new PROPVARIANT(appName));
// https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-toastactivatorclsid
propertyStore.SetValue(
new PropertyKey("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3", 26),
new PROPVARIANT(new Guid(activatorId)));
propertyStore.Commit();
persistFile.Save(shortcutPath, true);
}
[Update]
Finally got it to work - not sure what was wrong before, but the final version seems to be okay. Full code: https://gist.github.com/davidair/c4ea207bf6eece4ef08b97ab29a3036f
I have the same problem with my project now.
Managed to find this repository - https://github.com/felixrieseberg/electron-windows-interactive-notifications
Here's C++ implementation for installing shortcut (InteractiveNotifications file, InstallShortcut method). I guess the problem is how we set the value to PropertyStore, string GUID is not suitable for some reason. Still, I wasn't able to solve the problem for now.
UPDATED: Finally, was able to install shortcut from code! Check my example at Github. https://github.com/romayavorskyi/WpfNotificationTest (still a lot of hardcode, but it should give you the general idea). And you were right, shortcut path matters. It seems shortcut should be in the ProgramData folder for correct work.

Error when calling two fullTrust apps on the load of the page

I have a UWP app that does the recording and calling functionality. For this I have added two FullTrust Apps using Desktop bridge application. When I call just one fullTrust app everything works perfectly, but when I call two FullTrust apps by passing parameters (of the FullTrust apps to be started) the the first app that was started behaves incorrectly. For these two FullTrust apps I have used two different Appservice names declared in the Package.Manifest file of the Windows Packaging Project.
I have noticed that whenever I switch the position of the Fulltrust app call the last application that is called always remains active(has the priority of the Appservice connection) even if both has different app service names.
Here is the code I have added when user opens a page in UWP that starts Win32 app and background App
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
{
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("Win32");
}
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
{
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync("Background");
}
In the above code, the first app that is Started calls my Win32.exe and second background.exe.
How can I call these two apps independently? whenever we want to start them and close whenever required or may be in future I would like to start two apps at the same time but also I may need to close any app whenever required. Can anyone tel me how can I handle the correct communication path when calling two fullTrust apps at the same time?
How can I call these two apps independently?
For launching multiple desktop app, we suggest to make Launcher app to manage multiple apps, then call LaunchFullTrustProcessForCurrentAppAsync(string parameterGroupId) and pass GroupId parameter. And at first we need add the group in the desktop bridge appxmanifes file.
<Extensions>
<desktop:Extension Category="windows.fullTrustProcess" Executable="Launcher\Launcher.exe">
<desktop:FullTrustProcess>
<desktop:ParameterGroup GroupId="Background" Parameters="/background" />
<desktop:ParameterGroup GroupId="Win32" Parameters="/win32" />
</desktop:FullTrustProcess>
</desktop:Extension>
</Extensions>
Then use the Launcher to start all apps with parameter
static void Main(string[] args)
{
// determine the package root, based on own location
string result = Assembly.GetExecutingAssembly().Location;
int index = result.LastIndexOf("\\");
string rootPath = $"{result.Substring(0, index)}\\..\\";
// process object to keep track of your child process
Process newProcess = null;
if (args.Length > 2)
{
// launch process based on parameter
switch (args[2])
{
case "/background":
newProcess = Process.Start(rootPath + #"FullTrust_Background\FullTrust_Background.exe");
break;
case "/win32":
newProcess = Process.Start(rootPath + #"FullTrust_Win32\FullTrust_Win32.exe");
break;
}
}
}
For more detail please refer this tutorial.

Xamarin nfc pinned app

I am implementing NFC into an Xamarin Forms existing app, initially for a Zebra TC51 (android 6.0).
The app must be pinned so that users cannot access the rest of the device.
In OnCreate, within MainActivity.cs, I have the following lines:
NfcManager NfcManager = (NfcManager)Android.App.Application.Context.GetSystemService(Context.NfcService);
_nfcAdapter = NfcManager.DefaultAdapter;
I then use the following class to receive the tag:
[Activity IntentFilter(new[] { "android.nfc.action.NDEF_DISCOVERED" },
DataMimeType = MainActivity.ViewApeMimeType,
Categories = new[] { "android.intent.category.DEFAULT" })]
public class NfcActivity : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
//SetContentView(Resource.Layout.DisplayHominid);
if (Intent == null)
{
return;
}
var intentType = Intent.Type ?? String.Empty;
if (MainActivity.ViewApeMimeType.Equals(intentType))
{
var rawMessages = Intent.GetParcelableArrayExtra(NfcAdapter.ExtraNdefMessages);
var tag = Intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
var id = System.Text.Encoding.Default.GetString(tag.GetId());
var msg = (NdefMessage)rawMessages[0];
var tagMessage = msg.GetRecords()[0];
var content = Encoding.ASCII.GetString(tagMessage.GetPayload());
// Call another function with Tag ID and contents here
}
}
}
This code works to retrieve the tag ID and contents, but only if the app is not pinned. If the app is pinned, then the NFC service window can not be displayed, and the tag is ignored.
Can anyone suggest a way around this. I do not want to use the NFCforms NUGET package due to licecing restrictions.
TIA. Pete
Given that you want to have your application running in a kiosk mode like scenario (restricting the user to access the device) a better option could be to use Zebra's Enterprise Home Screen.
In this way you can lock down the device, restricting access to notification, disabling the keyguard and more (if needed). And you can still add other apps that may be useful to the user.
In EHS' configuration you can specify that your app is launched automatically so that you're there as soon as the device is booted.
If you need to have only your app, a better solution than screen pinning maybe installing a Device Policy Controller and use the taskLockMode that has been introduced in Marshmallow for the COSU (Corporate Owned - Single Use) devices.
If still have issue you can try asking the question on Zebra's developer forum.
Disclaimer: I work for Zebra Technologies.

Is it possible to launch system/third party app using an NDEFLaunchApp record to get the URI and by using LaunchUriAsync without NFC Tags?

So I have spent the whole night looking like a zombie in the morning trying to figure out how the OS handles an NFC tap for an NDEFLaunchApp Record and I have known the following.
I'm pretty sure that there is a workaround which lets you launch a system app / third party app (if you know the product Id / GUID) from your app. As there are apps in the Windows Phone Store which I have somehow figured out what I've been trying to.
I have come up with the following code:
NdefLaunchAppRecord appLaunchRecord = new NdefLaunchAppRecord();
appLaunchRecord.AddPlatformAppId("WindowsPhone", "{App GUID}");
appLaunchRecord.Arguments = "_default";
// Creating a new NdefMessage from the above record.
var message = new NdefMessage { appLaunchRecord };
// Getting the record from the message that we just created
foreach (NdefLaunchAppRecord record in message)
{
var specializedType = record.CheckSpecializedType(false);
if (specializedType == typeof(NdefLaunchAppRecord))
{
var x = String.Join(" ", record.Payload);
// Getting the payload by GetString gets a formatted Uri with args
string result = System.Text.Encoding.UTF8.GetString(record.Payload, 0, record.Payload.Length);
// result = "\0\fWindowsPhone&{5B04B775-356B-4AA0-AAF8-6491FFEA5630}\0\b_default";
// result = "(null)(form feed)WindowsPhone&{App GUID}(null)(backspace)_default
// So this will be sent to the OS and I believe the OS will then launch the specified app by an unknown protocol
// like xxx://result
// and the app will be launched?
// So is it then possible to somehow call the following:
await Windows.System.Launcher.LaunchUriAsync(new Uri("OUR MAGIC RESULT?", UriKind.RelativeOrAbsolute));
If anyone has / can figure out a way for this, it would be a REAL Service to the WP Community as developers are restricted by Microsoft to open certain settings / apps which are actually needed by those apps. For instance (speech settings, audio settings, about settings, alarms, region settings, date+time);
APPS that possibly have a workaround:
Music Hub Tile (Launches the old Music+Videos Hub)
http://www.windowsphone.com/en-gb/store/app/music-hub-tile/3faa2f9e-6b8d-440a-bb60-5dd76a5baec1
Tile for Bing Vision
http://www.windowsphone.com/en-gb/store/app/tile-for-bing-vision/05894022-e18c-40a4-a6cc-992383aa7ee8
There are reserved uri schemes for bing and zune.
See: http://msdn.microsoft.com/en-us/library/windows/apps/jj207065(v=vs.105).aspx
Those two apps propably use these and have found some undocumented use of the scheme.
If there is an uri scheme that launches any app by guid from within your app, it is hidden well.
Currently you can only launch apps that registered for an uri scheme or file association.

Categories