Downloads
ExecutingExternalProcessfromWindows8MetroApplicationUsingNativeProxy-noexe.zip
Introduction
This is probably the best solution I could think of for executing external process from Windows 8 metro application by using proxy application running as native application. But take note, this is not for production because you will be asking your clients to download an external application to be able to use your Metro application. What I done here is for a Proof of Concept only.
Background
The trick here is simple and basic
- Metro create a text file with some sort of command
- Proxy monitors the file changes
- Once changed, proxy reads that file and process it
- Then proxy executes the file needed to run.
So how's that possible?
We will be using 2 Visual Studio version here.
- Visual Studio for creating Metro application
- and your VS IDE where you can create a Windows Forms Application
Let's take a look at this code written for Metro application
public async void CreateTextCommand(string file_to_run)
{
file = await KnownFolders.DocumentsLibrary.CreateFileAsync("proxyfile.txt", CreationCollisionOption.ReplaceExisting);
string command = string.Format("run={0},{1}", file_to_run, DateTime.Now.Ticks);
await FileIO.WriteTextAsync(file, command);
}
This method writes a file in your Documents folder called "proxyfile.txt" that contains 1 line of command.
run=<file_to_execute>
Then we let our proxy application process and execute that file once there are changed made from our Metro application. Monitoring the file changes is done via FileSystemWatcher.
void ProcessCommand()
{
System.Threading.Thread.Sleep(100);
string file_to_run = string.Empty;
string UID = string.Empty;
string filename = Path.Combine(this.path, this.file);
if (!File.Exists(filename))
{
MessageBox.Show("proxyfile.txt is missing!");
}
using (StreamReader reader = new StreamReader(filename))
{
string data = reader.ReadToEnd();
string[] cmd2 = data.Split('=')[1].Split(',');
file_to_run = cmd2[0];
UID = cmd2[1];
}
if (!this.running_apps.Contains(file_to_run + UID))
{
RunOnce(file_to_run, UID);
}
else
{
Debug.WriteLine(file_to_run + " is already running");
}
}
void RunOnce(string fullpath, string UID)
{
ProcessStartInfo psi = new ProcessStartInfo()
{
FileName = fullpath,
UseShellExecute = true
};
Process.Start(psi);
this.running_apps.Add(fullpath + UID);
}
That's just it. Now you can execute any external application or file from your Metro application. If you want to put more complex commands, then you can use JSON
Points of Interest
FileSystemWatcher's job is to monitor the last changes made in the file that we are monitoring "proxyfile.txt" so we set our NotifyFilter to LastWrite
FileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite
So everytime we click the button on LeLaunch Metro application buttons, FileSystemWatcher.Changed is triggered.
but the problem was FileSystemWatcher.Changed is triggered 5 times for each click on the button. so we have to filter this out by using UID.