Skip to content
This repository was archived by the owner on Jul 19, 2024. It is now read-only.

Commit fd7d0cf

Browse files
author
David Kline
authored
Merge pull request #140 from davidkline-ms/master
merging per approval
2 parents 89d9406 + 8f02d22 commit fd7d0cf

24 files changed

+797
-161
lines changed

HoloLensCommander/HoloLensCommander/Controls/DeviceMonitorControl.xaml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
88
mc:Ignorable="d"
99
d:DesignHeight="40"
10-
d:DesignWidth="750">
10+
d:DesignWidth="800">
1111

1212
<UserControl.Resources>
1313
<Style TargetType="CheckBox">
@@ -80,7 +80,7 @@
8080
Command="{Binding Path=SetTagCommand}"
8181
FontFamily="Segoe MDL2 Assets" FontSize="10"
8282
Width="32" Height="22"
83-
Canvas.Left="186" Canvas.Top="24">
83+
Canvas.Left="186" Canvas.Top="22">
8484
<Button.RenderTransform>
8585
<CompositeTransform ScaleX="1.0" ScaleY=".8"/>
8686
</Button.RenderTransform>
@@ -125,9 +125,9 @@
125125
Content="&#xEB7E;"
126126
Command="{Binding Path=SetIpdCommand}"
127127
Visibility="{Binding Path=IpdVisibility}"
128-
FontFamily="Segoe MDL2 Assets" FontSize="10"
128+
FontFamily="Segoe MDL2 Assets" FontSize="10"
129129
Height="22" Width="32"
130-
Canvas.Left="89" Canvas.Top="24" >
130+
Canvas.Left="89" Canvas.Top="22" >
131131
<Button.RenderTransform>
132132
<CompositeTransform ScaleX="1.0" ScaleY="0.8"/>
133133
</Button.RenderTransform>
@@ -150,6 +150,18 @@
150150
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
151151
Width="262"/>
152152
</ScrollViewer>
153+
<Button
154+
x:Name="clearStatus"
155+
Content="&#xE947;"
156+
ToolTipService.ToolTip="Clear status message"
157+
Command="{Binding Path=ClearStatusMessageCommand}"
158+
FontFamily="Segoe MDL2 Assets" FontSize="10"
159+
Height="22" Width="32"
160+
Canvas.Left="750" Canvas.Top="22">
161+
<Button.RenderTransform>
162+
<CompositeTransform ScaleX="0.8" ScaleY="0.8"/>
163+
</Button.RenderTransform>
164+
</Button>
153165
</Canvas>
154166
</Grid>
155167
</Page>

HoloLensCommander/HoloLensCommander/Controls/DeviceMonitorControl.xaml.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,17 @@ public void Dispose()
123123
GC.SuppressFinalize(this);
124124
}
125125

126+
/// <summary>
127+
/// Clears the status message for this device.
128+
/// </summary>
129+
internal void ClearStatusMessage()
130+
{
131+
if (this.ViewModel.IsSelected)
132+
{
133+
this.ViewModel.ClearStatusMessage();
134+
}
135+
}
136+
126137
/// <summary>
127138
/// Closes all applications running on this device.
128139
/// </summary>

HoloLensCommander/HoloLensCommander/Controls/DeviceMonitorControlViewModel.cs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ partial class DeviceMonitorControlViewModel : INotifyPropertyChanged, IDisposabl
3232
/// <summary>
3333
/// Text labels describing the type of device.
3434
/// </summary>
35-
private static readonly string DeviceIsHoloLensLabel = ""; // no image
36-
private static readonly string DeviceIsPCLabel = ""; // E7F4 (PC monitor)
37-
private static readonly string DeviceIsUnknownLabel = ""; // E897 (question mark)
35+
private static readonly string DeviceIsHoloLensLabel = string.Empty; // no image
36+
private static readonly string DeviceIsPCLabel = ""; // E7F4 (PC monitor)
37+
private static readonly string DeviceIsUnknownLabel = ""; // E897 (question mark)
3838

3939
/// <summary>
4040
/// Text label indicating that an initial connection has not yet been established
@@ -83,8 +83,6 @@ public DeviceMonitorControlViewModel(
8383
{
8484
this.deviceMonitorControl = control;
8585

86-
this.RegisterCommands();
87-
8886
this.firstContact = false;
8987
this.deviceMonitor = monitor;
9088
this.deviceMonitor.HeartbeatLost += Device_HeartbeatLost;
@@ -98,6 +96,7 @@ public DeviceMonitorControlViewModel(
9896
this.Address = deviceMonitor.Address;
9997
this.IsSelected = true;
10098

99+
this.RegisterCommands();
101100
}
102101

103102
/// <summary>
@@ -633,7 +632,7 @@ private void Device_HeartbeatReceived(DeviceMonitor sender)
633632
// Did we recover from a heartbeat loss?
634633
if (this.StatusMessage == HeartbeatLostMessage)
635634
{
636-
this.StatusMessage = "";
635+
this.ClearStatusMessage();
637636
}
638637

639638
// Handle whether or not we were previously selected
@@ -702,6 +701,12 @@ private void NotifyPropertyChanged(string propertyName)
702701
/// </summary>
703702
private void RegisterCommands()
704703
{
704+
this.ClearStatusMessageCommand = new Command(
705+
(parameter) =>
706+
{
707+
this.ClearStatusMessage();
708+
});
709+
705710
this.DisconnectCommand = new Command(
706711
(parameter) =>
707712
{
@@ -711,13 +716,31 @@ private void RegisterCommands()
711716
this.SetIpdCommand = new Command(
712717
async (parameter) =>
713718
{
714-
await this.SetIpdAsync();
719+
try
720+
{
721+
await this.SetIpdAsync();
722+
}
723+
catch(Exception e)
724+
{
725+
this.StatusMessage = string.Format(
726+
"Failed to set IPD ({0})",
727+
e.Message);
728+
}
715729
});
716730

717731
this.SetTagCommand = new Command(
718732
async (parameter) =>
719733
{
720-
await this.TagDeviceAsync();
734+
try
735+
{
736+
await this.TagDeviceAsync();
737+
}
738+
catch (Exception e)
739+
{
740+
this.StatusMessage = string.Format(
741+
"Failed to set the device name ({0})",
742+
e.Message);
743+
}
721744
});
722745

723746
this.ShowContextMenuCommand = new Command(

HoloLensCommander/HoloLensCommander/Controls/DeviceMonitorControlViewModelCommands.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ private enum MonitorContextMenuCommandIds
3535
public ICommand ClearStatusMessageCommand
3636
{ get; private set; }
3737

38+
/// <summary>
39+
/// Implementation of the clear status message command.
40+
/// </summary>
41+
internal void ClearStatusMessage()
42+
{
43+
this.StatusMessage = string.Empty;
44+
}
45+
3846
/// <summary>
3947
/// Command used to disconnect from the device.
4048
/// </summary>

HoloLensCommander/HoloLensCommander/Controls/DeviceMonitorControlViewModelProperties.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ private set
3636
/// Gets the battery level of this device, as a percentage remaining.
3737
/// </summary>
3838
/// <remarks>The returned string is formatted to two significant decimal places.</remarks>
39-
private string batteryLevel = "";
39+
private string batteryLevel = string.Empty;
4040
public string BatteryLevel
4141
{
4242
get
@@ -99,7 +99,7 @@ private set
9999
/// <summary>
100100
/// Gets or sets a string representation of the interpuplliary distance recorded on this device.
101101
/// </summary>
102-
private string ipd = "";
102+
private string ipd = string.Empty;
103103
public string Ipd
104104
{
105105
get

HoloLensCommander/HoloLensCommander/Device/DeviceMonitor.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,14 @@ public partial class DeviceMonitor : IDisposable
4646
public static readonly string DefaultConnectionAddressAsIp = "127.0.0.1:10080";
4747

4848
/// <summary>
49-
/// The executable name of the HoloLens shell application.
49+
/// The file names of applications that will remain running after the user
50+
/// requests all apps to be closed.
5051
/// </summary>
51-
private static readonly string ShellApp = "HoloShellApp.exe";
52+
private static readonly string[] DoNotCloseApps = new string[]
53+
{
54+
"HoloShellApp.exe",
55+
"MixedRealityPortal.exe"
56+
};
5257

5358
/// <summary>
5459
/// Options used to connect to this device.

HoloLensCommander/HoloLensCommander/Device/DeviceMonitorCommands.cs

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

44
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
57
using System.Threading;
68
using System.Threading.Tasks;
79
using Windows.Security.Cryptography.Certificates;
10+
using Windows.UI.Core;
811
using Microsoft.Tools.WindowsDevicePortal;
912
using static Microsoft.Tools.WindowsDevicePortal.DevicePortal;
10-
using Windows.UI.Core;
1113

1214
namespace HoloLensCommander
1315
{
@@ -154,6 +156,39 @@ public void Disconnect()
154156
Timeout.Infinite);
155157
}
156158

159+
/// <summary>
160+
/// Find the installed application name that is associated with the specified package name.
161+
/// </summary>
162+
/// <param name="packageName">Name of the application package.</param>
163+
/// <returns>The application display name, or null if not found.</returns>
164+
private async Task<string> FindAppNameFromPackageName(string packageName)
165+
{
166+
string appName = null;
167+
168+
// Get the collection of installed applications.
169+
AppPackages apps = await this.GetInstalledApplicationsAsync();
170+
171+
// Remove the version/plaform from the package name and squash
172+
string squashedPackageName = SquashPackageName(packageName);
173+
174+
foreach (PackageInfo package in apps.Packages)
175+
{
176+
// Squash the name so there are no underscores or spaces
177+
string squashedName = SquashName(package.FamilyName);
178+
179+
180+
// Try to match with the squashed package name
181+
if (squashedPackageName == squashedName)
182+
{
183+
appName = package.Name;
184+
break;
185+
}
186+
}
187+
188+
// Return the un-squashed name
189+
return appName;
190+
}
191+
157192
/// <summary>
158193
/// Gets the collection of installed applications.
159194
/// </summary>
@@ -202,8 +237,8 @@ public Uri GetMixedRealityViewUri()
202237
return this.devicePortal.GetLowResolutionMrcLiveStreamUri(
203238
true, // Include holograms.
204239
true, // Include color camera.
205-
true, // Include microphone.
206-
true); // Include application audio.
240+
true, // Include microphone.
241+
true); // Include application audio.
207242
}
208243

209244
/// <summary>
@@ -225,8 +260,10 @@ public async Task InstallApplicationAsync(AppInstallFiles installFiles)
225260
await Task.Run(
226261
async () =>
227262
{
263+
string appName = await this.FindAppNameFromPackageName(installFiles.AppPackageFile.Name);
264+
228265
await this.devicePortal.InstallApplicationAsync(
229-
null,
266+
appName,
230267
installFiles.AppPackageFile,
231268
installFiles.AppDependencyFiles,
232269
installFiles.AppCertificateFile);
@@ -296,6 +333,47 @@ public async Task ShutdownAsync()
296333
await this.devicePortal.ShutdownAsync();
297334
}
298335

336+
/// <summary>
337+
/// Returns a "compressed" (spaces and underscores removed) string.
338+
/// </summary>
339+
/// <param name="name">The name to squash.</param>
340+
/// <returns>The modified name.</returns>
341+
private string SquashName(string name)
342+
{
343+
string squashedName = name;
344+
345+
squashedName = squashedName.Replace(" ", "");
346+
squashedName = squashedName.Replace("_", "");
347+
348+
return squashedName;
349+
}
350+
351+
/// <summary>
352+
/// Returns a "compressed" (spaces, underscores, version and platform info removed) version of a package name
353+
/// </summary>
354+
/// <param name="name">The package name to squash.</param>
355+
/// <returns>The modified package name.</returns>
356+
private string SquashPackageName(string name)
357+
{
358+
string squashedName = "";
359+
int versionIndex = -1;
360+
361+
string[] nameParts = name.Split('_');
362+
for (int i = 0; i < nameParts.Length; i++)
363+
{
364+
Version v;
365+
if (Version.TryParse(nameParts[i], out v))
366+
{
367+
versionIndex = i;
368+
break;
369+
}
370+
371+
squashedName += nameParts[i];
372+
}
373+
374+
return squashedName;
375+
}
376+
299377
/// <summary>
300378
/// Starts a mixed reality recording on this device.
301379
/// </summary>
@@ -326,10 +404,15 @@ public async Task TerminateAllApplicationsAsync()
326404
{
327405
RunningProcesses runningApps = await this.GetRunningProcessesAsync();
328406

407+
List<string> doNotClose = new List<string>();
408+
doNotClose.AddRange(DoNotCloseApps);
409+
329410
foreach (DeviceProcessInfo processInfo in runningApps.Processes)
330411
{
331-
// Do not terminate the shell.
332-
if (ShellApp.ToLower() == processInfo.Name.ToLower())
412+
// Skip applications that should not be closed.
413+
if (doNotClose.Contains(
414+
processInfo.Name,
415+
StringComparer.OrdinalIgnoreCase))
333416
{
334417
continue;
335418
}

HoloLensCommander/HoloLensCommander/Dialogs/ConnectToDeviceDialog.xaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@
127127
Canvas.Top="5" Canvas.Left="25"/>
128128
</Canvas>
129129
<Canvas
130-
Width="450" Height="90"
130+
Width="450" Height="95"
131131
Visibility="{Binding Path=ShowNetworkSettings}">
132132
<TextBlock
133133
x:Name="ssidLabel"
@@ -137,7 +137,7 @@
137137
<TextBox
138138
x:Name="ssid"
139139
Text="{Binding Path=Ssid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
140-
ToolTipService.ToolTip="The SSID on which to configure the device"
140+
ToolTipService.ToolTip="The SSID on which to configure the device (this may make the device unreachable from this network)"
141141
TextWrapping="NoWrap"
142142
Width="360"
143143
Canvas.Left="80" Canvas.Top="5" />
@@ -155,7 +155,7 @@
155155
Canvas.Left="80" Canvas.Top="45" />
156156
</Canvas>
157157
<Canvas
158-
Width="450" Height="40">
158+
Width="450" Height="35">
159159
<CheckBox
160160
x:Name="useInstalledCertificate"
161161
Content="Use Installed Device Certificate"
@@ -164,7 +164,7 @@
164164
Canvas.Top="0"/>
165165
</Canvas>
166166
<Canvas
167-
Width="450" Height="40">
167+
Width="450" Height="35">
168168
<CheckBox
169169
x:Name="updateConnection"
170170
Content="Update Connection"

0 commit comments

Comments
 (0)