Open another application from the current one - c#

We have a UWP app in the Windows Store. From this app we would like to launch various apps on the same system. For this process we need to do 2 things.
Check if the app exists on the system
If yes, launch it. If no, give feedback
We tried a couple of things but i'm searching for the best way to do this.
We would like to launch both other UWP apps and Standalone apps.
I tried messing with the Unity PlayerPrefs, but that acts weird. It works if I make a custom PlayerPref and check if it exists from within 1 app, but as soon as I make a playerpref in the UWP and check for it in the Standalone I get nothing. And vice versa ofcourse. (Yes I know UWP saves its playerprefs somewhere else)
What would be the best general solution to this? Continue messing around with Playerprefs and search for different paths depending on the app we want to open?(Standalone, UWP) or some other way?
EDIT: What I have so far:
if (Input.GetKeyDown(KeyCode.Backspace))
{
PlayerPrefs.SetString("42069" , "testing_this");
PlayerPrefs.Save();
Debug.Log("Wrote key 42069 to registry with: -value testing_this-");
}
if (Input.GetKeyDown(KeyCode.Space))
{
if (PlayerPrefs.HasKey("42069"))
{
Debug.Log("I found the key 42069 in my registry");
cube.SetActive(true);
}
else
{
Debug.Log("I cant find key 42069 in my registry");
}
}
if (Input.GetKeyDown(KeyCode.S))
{
const string registry_key = #"SOFTWARE\DefaultCompany";
using(RegistryKey key = Registry.CurrentUser.OpenSubKey(registry_key))
{
if (key != null)
foreach (string subKeyName in key.GetSubKeyNames())
{
if (subKeyName == "RegistryTesting")
{
Debug.Log("I found the key on path: " + registry_key);
}
}
}
}
EDIT: No one? I know there is a way. All I need to do is check whether a standalone app exists from a UWP app. But I do not have acces to the register in a UWP app. I know there are some ways with bridges etc, but I have no clue how and where to start.

I encountered a somewhat similar situation but I was checking to see if the app was running and if not, start it. In my situation, the app I wanted to check and launch was not something I wrote nor was it UWP so my solution may not work for you as the capabilities to do so are restricted.
First adding restricted capabilities to the package.appxmanifest (code).
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp rescap"
Then adding "appDiagnostics" capability to the app.
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="appDiagnostics" />
</Capabilities>
Now you have the ability to request permission to access running processes and check.
using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.System;
using Windows.System.Diagnostics;
class ProcessChecker
{
public static async Task<bool> CheckForRunningProcess(string processName)
{
//Requests permission for app.
await AppDiagnosticInfo.RequestAccessAsync();
//Gets the running processes.
var processes = ProcessDiagnosticInfo.GetForProcesses();
//Returns result of searching for process name.
return processes.Any(processDiagnosticInfo => processDiagnosticInfo.ExecutableFileName.Contains(processName));
}
}
Launching a non UWP app/process is a bit dirty but possible.
First, a simple console (non uwp) app is needed. Replace the directoryPath in the code below with your applicable directory path.
using System;
using System.Diagnostics;
namespace Launcher
{
class Program
{
static void Main(string[] args)
{
try
{
if (args.Length != 3) return;
string executable = args[2];
string directoryPath = "C:\\Program Files (x86)\\Arduino\\hardware\\tools\\";
Process.Start(directoryPath + executable);
}
catch (Exception e)
{
Console.ReadLine();
}
}
}
}
Build the console app and place the Launcher.exe in your UWP app asset folder.
Now you need to add the capability to run the Launcher and to do so, add "runFullTrust" capability to the UWP app.
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
<rescap:Capability Name="appDiagnostics" />
</Capabilities>
For desktop, you also need to add desktop capabilities and extension to the package.appxmanifest (code).
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"
Then further below in the package.appxManifest and inside .
<Extensions>
<desktop:Extension Category="windows.fullTrustProcess" Executable="Assets\Launcher.exe" >
<desktop:FullTrustProcess>
<desktop:ParameterGroup GroupId="SomeGroup1" Parameters="ProcessName1.exe"/>
<desktop:ParameterGroup GroupId="SomeGroup2" Parameters="ProcessName2.exe"/>
</desktop:FullTrustProcess>
</desktop:Extension>
</Extensions>
Finally, add the "Windows Desktop Extensions for the UWP" references needed for your app versions.
Now you can call your Launcher and start the necessary process.
public static async void LaunchProcess(int groupId)
{
switch (groupId)
{
case 1:
await FullTrustProcessLauncher.LaunchFullTrustProcessForAppAsync("SomeGroup1");
break;
case 2:
await FullTrustProcessLauncher.LaunchFullTrustProcessForAppAsync("SomeGroup2");
break;
}
}
Combining the above, one possibility may be...
public enum ProcessResult
{
ProcessAlreadyRunning,
FailedToLaunch,
SuccessfulLaunch
}
public static async Task<ProcessResult> CheckLaunchCheckProcess1()
{
if (await CheckForRunningProcess("ProcessName1.exe")) return ProcessResult.ProcessAlreadyRunning;
LaunchProcess(1);
return await CheckForRunningProcess("ProcessName1.exe") ? ProcessResult.SuccessfulLaunch : ProcessResult.FailedToLaunch;
}
This is just an example of how to accomplish launching non uwp apps within a single uwp app. For a windows store app submissions, restricted capabilities require approval and can delay or halt deployment if denied.
If the both the calling app and launching app are uwp and written by you, the appropriate solution may be using URI for app to app communication, MS doc link Launch an app with a URI

Related

How do you access android permissions in c#

I'm building an application for android using Unity and I need to access permissions in the phone.
So far I've been able to reference camera and microphone, but there doesn't seem to be references for the other two permissions; storage and telephone. How do I access them?
void OnGUI()
{
//microphone
#if PLATFORM_ANDROID
if (!Permission.HasUserAuthorizedPermission(Permission.Microphone))
{
dialog.AddComponent<PermissionsRationaleDialog>();
}
if (!Permission.HasUserAuthorizedPermission(Permission.Camera))
{
dialog.AddComponent<PermissionsRationaleDialog>();
}
else if (dialog != null)
{
Destroy(dialog);
}
#endif
}
As you can see permission and camera have reference but I can't find anywhere on the internet that has the solution to this.
See in your code Permission.Microphone is actually a String. So you can use and directly the permission as if you use in Android Manifest.
This one Can be used to get the Android Storage Read and Write Permission.(Write Permission Implies Read Permission also)
using UnityEngine;
using UnityEngine.Android;
public class RequestPermissionScript : MonoBehaviour
{
void Start()
{
if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
{
// The user authorized use of the microphone.
}
else
{
// We do not have permission to use the microphone.
// Ask for permission or proceed without the functionality enabled.
Permission.RequestUserPermission(Permission.ExternalStorageWrite);
}
}
}
This is What is said in Unity Documentation For Requesting Permission in Android
A string that describes the permission to request. For permissions
which Unity has not predefined you may also manually provide the
constant value obtained from the Android documentation here:
https://developer.android.com/guide/topics/permissions/overview#permission-groups
such as "android.permission.READ_CONTACTS".
That means instead of using permission.ExternalStorageWrite you may directly use "android.permission.WRITE_EXTERNAL_STORAGE". Similarly for any other permission that is available on Android platform.
For Telephone permission the Unity doesn't have a built-in constant defined so you need to use that permission as if we use in android. Here am just giving an example for requesting permissions for reading contacts. As I did not exactly understood what you actually meant by telephone permission. Unity has nothing to do with Android Permission these are actually set of permission strings that are understood by Android. So for some standard permissions that are most often used unity have some predefined constant string values. That is actually for ease of use for developers.
public class RequestPermissionScript : MonoBehaviour
{
void Start()
{
if (Permission.HasUserAuthorizedPermission("android.permission.READ_CONTACTS"))
{
// The user authorized use of the microphone.
}
else
{
// We do not have permission to use the microphone.
// Ask for permission or proceed without the functionality enabled.
Permission.RequestUserPermission("android.permission.READ_CONTACTS");
}
}
}
Hope this solves your issue. Thank You.

Determine if library loaded into Console, Desktop, or UWP app

I have a libary which needs to behave differently for console applications, desktop application (e.g. WPF), and for UWP apps.
How can I determine at run-time into which application type my libary is loaded?
Determining if it is a console application seems easy: How to tell if there is a console
For UWP, I can probably determine if WinRT is loaded. But how?
What distinguishing attributes do desktop applications have?
I ended up defining following enum:
public enum ExecutionMode
{
Console,
Desktop,
UniversalWindowsPlatform
}
which is passed to the constructor of the main class of my libary. Not a new idea, but very reliable (if used correctly).
Create a CustomAttribute in an assembly that is available to all of the applications like so
using System;
namespace MyNamespace.Reflection {
[System.AttributeUsage(AttributeTargets.Assembly)]
public class ApplicationTypeAttribute : Attribute {
public enum ApplicationTypes {
Console,
Desktop,
UWP,
ClassLibrary
}
public ApplicationTypeAttribute(ApplicationTypes appType) {
ApplicationType = appType;
}
public ApplicationTypes ApplicationType { get; private set; } = ApplicationTypes.Console;
}
}
Then add this attribute to your AssemblyInfo.cs file for a console application
using MyNamespace.Reflection;
[assembly: ApplicationType(ApplicationTypeAttribute.ApplicationTypes.Console)]
or a Desktop application
[assembly: ApplicationType(ApplicationTypeAttribute.ApplicationTypes.Desktop)]
etc.
Then wherever you want to check the calling type of the application that was started, use this
using MyNamespace.Reflection;
var assy = System.Relection.Assembly.GetEntryAssembly();
var typeAttribute = assy.GetCustomAttribute(typeof(ApplicationTypeAttribute));
if (typeAttribute != null) {
var appType = ((ApplicationTypeAttribute)typeAttribute).ApplicationType;
}
There is one caveat to this method. .NET Core apps have a different project structure and the AssemblyInfo.cs file is auto-generated at build time by default. You can override this behavior by specifying the following in the .csproj file in the Project node.
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
To match the old project file structure, you can create a Properties directory in the project directtory and then you can add an AssemblyInfo.cs file to that directory. Otherwise you can place the Custom Attribute definition in any file (after the usings and before the namespace declaration).

UWP: Cannot load PWM Controllers using Lightning on Raspberry Pi 2?

i justed started working on an older Project i started once, but unfortunately the PWM Controller is not working anymore with the Lightning Driver. I am using Visual Studio 2017, the RPi2 is running at 10.0.15063.414 and I've installed the following Nuget-Packages:
Microsoft.IoT.Lightning (v1.1.0)
Microsoft.NETCore.UniversalWindowsPlatform (v5.3.3)
WinRTXamlToolkit.Controls.DataVisualization (v2.3.0)
The Project includes references to
Analyzer
Microsoft.IoT.Lightning
Microsoft.NETCore.UniversalWindowsPlatform
%ClassesLibrary%
UniversalWindows
Windows IoT Extensions for the UWP
WinRTXamlToolkit.Controls.DataVisualization,
where %ClassesLibrary% is an user-defined Project containing some classes for my Project. In the configuration web Interface of Windows IoT Core in the devices section, the Direct Memory Mapped Driver (Current Driver) is selected.
My initialization Code Looks like this
private static async Task InitOnboardHardware()
{
if (LightningProvider.IsLightningEnabled)
{
LowLevelDevicesController.DefaultProvider = LightningProvider.GetAggregateProvider();
GpioController gpioController = GpioController.GetDefault();
var pwmControllers = await PwmController.GetControllersAsync(LightningPwmProvider.GetPwmProvider());
if (pwmControllers != null)
{
m_PWMController = pwmControllers[1];
//m_PWMController = (await PwmController.GetControllersAsync(LightningPwmProvider.GetPwmProvider()))[1];
m_PWMController.SetDesiredFrequency(100);
m_RPin = m_PWMController.OpenPin(18);
m_GPin = m_PWMController.OpenPin(23);
m_BPin = m_PWMController.OpenPin(24);
m_WPin = m_PWMController.OpenPin(25);
m_RPin.SetActiveDutyCyclePercentage(0);
m_GPin.SetActiveDutyCyclePercentage(0);
m_BPin.SetActiveDutyCyclePercentage(0);
m_WPin.SetActiveDutyCyclePercentage(0);
m_RPin.Start();
m_GPin.Start();
m_BPin.Start();
m_WPin.Start();
m_IsHardwareInitialized = true;
}
}
}
The PwmController.GetControllersAsync-method never completes and my application gets stuck on starting up. Also the commented Shorter Version is not working anymore?!
I have really no clue what i could be missing. Therefore, i would greatly appreciate any help.
Thank you in advance!
EDIT: I also tried another sample (https://github.com/lprichar/WindowsIotPwmExample), where i replaced the embedded C/C++ lightning library by the NuGet Package (same Version as in my Project). The sample also Fails: the Pins are all null, because PwmController.GetControllersAsync never completes :-(
EDIT2: I forgot to mention that my package.appxmanifest file also includes the following changes
<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:iot="http://schemas.microsoft.com/appx/manifest/iot/windows10"
IgnorableNamespaces="uap mp iot">
as well as
<Capabilities>
<Capability Name="internetClient" />
<iot:Capability Name="lowLevelDevices" />
<DeviceCapability Name="109b86ad-f53d-4b76-aa5f-821e2ddf2141" />
</Capabilities>
Please also see my comment to the first post. I had to Change this line
GpioController gpioController = GpioController.GetDefault();
to an async method call
GpioController gpioController = await GpioController.GetDefaultAsync();
and now everythings runs fine!

Squirrel.windows create multi shortcut on desktop

We are trying create an installer using Squirrel.Windows for our .NET application
The application contain multi .exe files.
We using command:
squirrel --releasify BIN_PATH\MyApp.2.0.33404.nupkg
However, when run the setup.exe, it create multi shortcut on desktops correspond to multi .exe files
How to specify create one shortcut only ?
The Squirrel documentation states that creating a shortcut for every EXE in your package is the default behaviour.
That same documentation page explains that to override the default behaviour you need to make at least one of your EXE Squirrel aware and then implement the Squirrel event handlers as you want to.
You better make the one EXE you want a shortcut for Squirrel aware by adding the following to its AssemblyInfo.cs:
[assembly: AssemblyMetadata("SquirrelAwareVersion", "1")]
Then in your EXE implement Squirrel events like that:
static bool ShowTheWelcomeWizard;
...
static int Main(string[] args)
{
// NB: Note here that HandleEvents is being called as early in startup
// as possible in the app. This is very important! Do _not_ call this
// method as part of your app's "check for updates" code.
using (var mgr = new UpdateManager(updateUrl))
{
// Note, in most of these scenarios, the app exits after this method
// completes!
SquirrelAwareApp.HandleEvents(
onInitialInstall: v => mgr.CreateShortcutForThisExe(),
onAppUpdate: v => mgr.CreateShortcutForThisExe(),
onAppUninstall: v => mgr.RemoveShortcutForThisExe(),
onFirstRun: () => ShowTheWelcomeWizard = true);
}
}

Using Reflection to use a namespace on certain OSs

I'm creating a program that uses the CodeProject CoreAudioApi (pretty popular framework for manipulating audio), but the problem is the CoreAudioApi uses system calls that aren't available in any versions of Windows earlier than Vista. If I run a program with CoreAudioApi compiled with it (using a using statement as normal), the program will crash on anything earlier than Vista.
I've created this function to get the version number of the current environment:
win_version = Environment.OSVersion.Version.Major;
That returns the major version number I need. '6' is Vista/7, anything else is not, which is all I need to determine. Utilizing this, I need to determine whether or not to include the CoreAudioApi namespace if the OS is over or equal to '6'. From research, usings need to be compiled with the program, but I've also read about something called Reflection - which might be what I need.
Once I get the CoreAudioApi namespace using'd (sorry for the lack of terminology), the rest is easy. How can I do this?
TL;DR
I need some form of code that would effectively do this:
using System;
using System.Text;
//etc
if(currentWindowsVersion>=6) using CoreAudioApi;
Except control structures won't work outside of a class, and all namespaces are compiled with the program, not controlled individually.
Thanks!
EDIT: So far, I'm using this to load the CoreAudioApi namespace as a compiled assembly:
if(win_version>=6){
CoreAudioApi = Assembly.LoadFrom("CoreAudio.dll");
CoreAudioApi.GetLoadedModules();
CoreAudioApi.GetTypes();
MessageBox.Show("Loaded CoreAudioApi");
}
From here, what I need to do is actually use the types, and methods from the API. My code that works on Windows Vista/7 is this:
public static MMDeviceEnumerator devEnum;
public static MMDevice defaultDevice;
//later in a mute method:
defaultDevice.AudioEndpointVolume.Mute = true/false;
I don't even really need devEnum AFAIK, so really the only important lines are the last two (besides the comment).
I've just tried the following:
Create a new console application project
Add the CoreAudioApi project from CodeProject to the solution
Add a project reference to CoreAudioApi in my console app
Create the following classes:
interface IAudio { void SetVolume(float level); }
class XpAudio : IAudio {
public void SetVolume(float level) {
// I do nothing, but this is where your old-style code would go
}
}
class VistaAudio : IAudio {
public void SetVolume(float level) {
MMDeviceEnumerator devEnum = new MMDeviceEnumerator();
MMDevice defaultDevice = devEnum
.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
defaultDevice.AudioEndpointVolume.MasterVolumeLevel = level;
}
}
class Program {
static void Main(string[] args) {
IAudio setter = Environment.OSVersion.Version.Major >= 6
? (IAudio)new VistaAudio()
: (IAudio)new XpAudio();
float val = float.Parse(Console.ReadLine());
setter.SetVolume(val);
Console.ReadLine();
}
}
This runs on both my server (~ Windows 7) and local (Windows XP) machines. On my XP machine it'll happily take in a value and ignore it; on my server, it throws an exception, (presumably because I don't have a sound output). If I make my XP machine run the CoreAudioApi, I get an exception when I input a value, not before.
The question is, what are you doing differently to make your application break? Are you using CoreAudioApi code at startup?
EDIT: After seeing your edit, if you do this, you shouldn't need to mess about with Assembly.LoadFrom at all. The framework should dynamically load that assembly if (and only if) and when it needs to.
COREAUDIOAPI.dll does not work on XP or earlier, because they cant handle MMDEVICE API (Device Enumeration). I dont know about Vista.

Categories