Skip to content

Commit

Permalink
AppControl Manager v.1.8.7.0 (#573)
Browse files Browse the repository at this point in the history
Added flyouts with buttons to the EVTX file path selector buttons in the Create Policy From Event Logs page. Now whenever you select EVTX files, a small flyout will open, displaying the path you selected and offers a Clear button so you can clear the selected path if you want. This is aligned with the rest of the browse button behaviors throughout the AppControl Manager's UI.

Added the same flyout feature to the MDE Advanced Hunting page for the browse for CSV button.

✨In the AppControl Manager, all buttons that allow you to browse for files and folders already feature flyouts—small pop-up areas that display the selected files or folders. Previously, these flyouts would only appear after a left-click or tap on the browse buttons, which would first launch the file/folder picker and then display the flyout. In this update, the flyouts can now also be triggered by right-clicking the buttons or, on touch-enabled devices, by tapping and holding the buttons. This enhancement improves your experience by making it easier to view your selected content without needing to click the browse button again to launch the file/folder picker.

Version bump from 1.8.6.0 to 1.8.7.0

Added JSON source generation support for the Intune class, making it Native AOT/Trim friendly and faster.

The Simulation page's folder picker now supports picking multiple folders. Previously it only supported picking 1 folder.

The Configure Policy Rule Options page now automatically shows you the available rule options in the XML file you select by checking/unchecking any boxes in the UI, they are dynamically updated to reflect the XML file's rule options.

The buttons were also simplified and there are no longer any Add/Remove/Select All buttons. They were replaced by "Apply the changes" and "Retrieve Rules Status" buttons.

Additionally, the entire row containing each checkbox is now clickable, making interaction easier.

When using a template, checkboxes update automatically in real time, reflecting the latest changes instantly. These enhancements significantly improve usability and efficiency.
  • Loading branch information
HotCakeX authored Jan 30, 2025
1 parent 07dad4d commit f5c2090
Show file tree
Hide file tree
Showing 26 changed files with 849 additions and 250 deletions.
2 changes: 1 addition & 1 deletion AppControl Manager/AppControl Manager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
<AssemblyName>AppControlManager</AssemblyName>
<PublishAot>False</PublishAot>
<ErrorReport>send</ErrorReport>
<FileVersion>1.8.6.0</FileVersion>
<FileVersion>1.8.7.0</FileVersion>
<AssemblyVersion>$(FileVersion)</AssemblyVersion>
<NeutralLanguage>en-US</NeutralLanguage>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
Expand Down
1 change: 0 additions & 1 deletion AppControl Manager/Main/SetCiRuleOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,6 @@ internal static void Set(

// Add the new Rule element to the Rules node
_ = RulesNode.AppendChild(NewRuleNode);

}

// Save the XML
Expand Down
36 changes: 36 additions & 0 deletions AppControl Manager/Others/CodeIntegrityPolicy.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
using AppControlManager.XMLOps;
Expand Down Expand Up @@ -29,6 +30,8 @@ internal sealed class CodeIntegrityPolicy
internal XmlNode PolicyIDNode { get; }
internal XmlNode BasePolicyIDNode { get; }

internal List<string>? Rules { get; }

internal XmlNode FileRulesNode { get; }

internal XmlNode SignersNode { get; }
Expand Down Expand Up @@ -248,8 +251,41 @@ internal CodeIntegrityPolicy(string? xmlFilePath, XmlDocument? xmlDocument)
VersionExNode = SiPolicyNode.SelectSingleNode("ns:VersionEx", NamespaceManager) ?? throw new InvalidOperationException($"VersionEx was not found.");

#endregion

#region Rules
Rules = LoadRules();
#endregion
}


private List<string>? LoadRules()
{
XmlNode? rulesNode = SiPolicyNode.SelectSingleNode("ns:Rules", NamespaceManager);

if (rulesNode is null)
{
return null;
}

List<string> rulesList = [];

XmlNodeList? ruleOptions = rulesNode.SelectNodes("ns:Rule/ns:Option", NamespaceManager);

if (ruleOptions is not null)
{
foreach (XmlNode ruleNode in ruleOptions)
{
if (!string.IsNullOrWhiteSpace(ruleNode.InnerText))
{
rulesList.Add(ruleNode.InnerText);
}
}
}

return rulesList.Count > 0 ? rulesList : null;
}


private XmlNode EnsureFileRulesRefNode(XmlNode parentNode, string mode)
{
// Find the FileRulesRef node
Expand Down
37 changes: 25 additions & 12 deletions AppControl Manager/Others/Intune.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using static AppControlManager.Others.Intune;

namespace AppControlManager.Others;

Expand All @@ -27,12 +28,6 @@ internal static class Intune

private const string DeviceConfigurationsURL = "https://graph.microsoft.com/v1.0/deviceManagement/deviceConfigurations";

private static readonly JsonSerializerOptions JsonOpt = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = true
};

private static AuthenticationResult? authenticationResult;

// Initialize the Public Client Application
Expand Down Expand Up @@ -74,7 +69,8 @@ internal static async Task FetchGroups()
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
JsonElement groupsJson = JsonSerializer.Deserialize<JsonElement>(content);
JsonElement groupsJson = JsonSerializer.Deserialize(content, IntuneJsonContext.Default.JsonElement);


if (groupsJson.TryGetProperty("value", out JsonElement groups))
{
Expand Down Expand Up @@ -266,17 +262,17 @@ private static async Task AssignPolicyToGroup(string policyId, string accessToke
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

// Create the payload with a Dictionary to handle special characters like @odata.type
var assignmentPayload = new
AssignmentPayload assignmentPayload = new()
{
target = new Dictionary<string, object>
Target = new Dictionary<string, object>
{
{ "@odata.type", "#microsoft.graph.groupAssignmentTarget" },
{ "groupId", groupID }
}
};

// Serialize the assignment payload to JSON
string jsonPayload = JsonSerializer.Serialize(assignmentPayload, JsonOpt);
string jsonPayload = JsonSerializer.Serialize(assignmentPayload, IntuneJsonContext.Default.AssignmentPayload);

using StringContent content = new(jsonPayload, Encoding.UTF8, "application/json");

Expand Down Expand Up @@ -342,7 +338,7 @@ private static async Task AssignPolicyToGroup(string policyId, string accessToke
};

// Serialize the policy object to JSON
string jsonPayload = JsonSerializer.Serialize(customPolicy, JsonOpt);
string jsonPayload = JsonSerializer.Serialize(customPolicy, IntuneJsonContext.Default.Windows10CustomConfiguration);

using SecHttpClient httpClient = new();

Expand All @@ -366,7 +362,8 @@ private static async Task AssignPolicyToGroup(string policyId, string accessToke
Logger.Write(responseContent);

// Extract the policy ID from the response
JsonElement responseJson = JsonSerializer.Deserialize<JsonElement>(responseContent);
JsonElement responseJson = JsonSerializer.Deserialize(responseContent, IntuneJsonContext.Default.JsonElement);

return responseJson.GetProperty("id").GetString();
}
else
Expand Down Expand Up @@ -494,6 +491,12 @@ public sealed class OmaSettingBase64
}


public sealed class AssignmentPayload
{
[JsonPropertyName("target")]
public Dictionary<string, object>? Target { get; set; }
}


private static string ConvertBinFileToBase64(string filePath, int maxSizeInBytes)
{
Expand All @@ -511,3 +514,13 @@ private static string ConvertBinFileToBase64(string filePath, int maxSizeInBytes
}

}


[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(JsonElement))]
[JsonSerializable(typeof(AssignmentPayload))]
[JsonSerializable(typeof(Windows10CustomConfiguration))]
[JsonSerializable(typeof(OmaSettingBase64))]
internal sealed partial class IntuneJsonContext : JsonSerializerContext
{
}
2 changes: 1 addition & 1 deletion AppControl Manager/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<Identity
Name="AppControlManager"
Publisher="CN=SelfSignedCertForAppControlManager"
Version="1.8.6.0" />
Version="1.8.7.0" />

<mp:PhoneIdentity PhoneProductId="199a23ec-7cb6-4ab5-ab50-8baca348bc79" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

Expand Down
8 changes: 5 additions & 3 deletions AppControl Manager/Pages/AllowNewApps/AllowNewAppsStart.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@
<controls:WrapPanel Grid.Row="1" Orientation="Horizontal" VerticalSpacing="15" HorizontalSpacing="15">

<TextBox x:Name="SupplementalPolicyNameTextBox" Header="Supplemental Policy Name" PlaceholderText="Enter a name for the Supplemental Policy" />
<Button x:Name="BrowseForXMLPolicyButton" Click="BrowseForXMLPolicyButton_Click" Margin="0,27,0,0" ToolTipService.ToolTip="Click/Tap to choose a XML policy file from your device.">
<Button x:Name="BrowseForXMLPolicyButton" Click="BrowseForXMLPolicyButton_Click" Margin="0,27,0,0"
RightTapped="BrowseForXMLPolicyButton_RightTapped" Holding="BrowseForXMLPolicyButton_Holding" ToolTipService.ToolTip="Click/Tap to choose a XML policy file from your device.">

<Button.Flyout>
<Flyout x:Name="BrowseForXMLPolicyButton_FlyOut">
Expand Down Expand Up @@ -155,10 +156,11 @@ LargeChange="10" Minimum="2" Maximum="1000000" ValueChanged="LogSizeNumberBox_Va

<controls:WrapPanel Grid.Row="1" Orientation="Horizontal" VerticalSpacing="8" HorizontalSpacing="8">

<Button x:Name="BrowseForFoldersButton" Click="BrowseForFoldersButton_Click" Content="Browse for folders" ToolTipService.ToolTip="Browse for folders of your new or existing apps that are installed and are getting blocked">
<Button x:Name="BrowseForFoldersButton" RightTapped="BrowseForFoldersButton_RightTapped"
Holding="BrowseForFoldersButton_Holding" Click="BrowseForFoldersButton_Click" Content="Browse for folders" ToolTipService.ToolTip="Browse for folders of your new or existing apps that are installed and are getting blocked">

<Button.Flyout>
<Flyout>
<Flyout x:Name="BrowseForFoldersButton_FlyOut">

<controls:WrapPanel Orientation="Vertical" HorizontalSpacing="15" VerticalSpacing="15">

Expand Down
31 changes: 30 additions & 1 deletion AppControl Manager/Pages/AllowNewApps/AllowNewAppsStart.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
using AppControlManager.SiPolicyIntel;
using AppControlManager.XMLOps;
using Microsoft.UI;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;


namespace AppControlManager.Pages;

public sealed partial class AllowNewAppsStart : Page, Sidebar.IAnimatedIconsManager
Expand Down Expand Up @@ -1052,4 +1053,32 @@ private void BrowseForXMLPolicyButton_Flyout_Clear_Click(object sender, RoutedEv
selectedXMLFilePath = null;
tempBasePolicyPath = null;
}


private void BrowseForXMLPolicyButton_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
if (!BrowseForXMLPolicyButton_FlyOut.IsOpen)
BrowseForXMLPolicyButton_FlyOut.ShowAt(BrowseForXMLPolicyButton);
}

private void BrowseForXMLPolicyButton_Holding(object sender, HoldingRoutedEventArgs e)
{
if (e.HoldingState is HoldingState.Started)
if (!BrowseForXMLPolicyButton_FlyOut.IsOpen)
BrowseForXMLPolicyButton_FlyOut.ShowAt(BrowseForXMLPolicyButton);
}


private void BrowseForFoldersButton_RightTapped(object sender, RightTappedRoutedEventArgs e)
{
if (!BrowseForFoldersButton_FlyOut.IsOpen)
BrowseForFoldersButton_FlyOut.ShowAt(BrowseForFoldersButton);
}

private void BrowseForFoldersButton_Holding(object sender, HoldingRoutedEventArgs e)
{
if (e.HoldingState is HoldingState.Started)
if (!BrowseForFoldersButton_FlyOut.IsOpen)
BrowseForFoldersButton_FlyOut.ShowAt(BrowseForFoldersButton);
}
}
3 changes: 2 additions & 1 deletion AppControl Manager/Pages/BuildNewCertificate.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
</controls:WrapPanel>

<Button Grid.Row="1" HorizontalAlignment="Center" x:Name="BuildCertificateButton"
HorizontalContentAlignment="Center" Margin="15" Click="BuildCertificateButton_Click">
HorizontalContentAlignment="Center" Margin="15" Click="BuildCertificateButton_Click"
ToolTipService.ToolTip="Build the certificate based on the configurations displayed below">
<Button.Content>
<StackPanel Orientation="Horizontal">
<ProgressRing Visibility="Collapsed" x:Name="ProgressRing" Margin="5,5,15,5" Value="0" IsIndeterminate="True" Minimum="0" Maximum="100"/>
Expand Down
21 changes: 8 additions & 13 deletions AppControl Manager/Pages/ConfigurePolicyRuleOptions.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>


<controls:WrapPanel Grid.Row="0" VerticalSpacing="4" HorizontalSpacing="4" Orientation="Horizontal" Margin="6,5,6,5">

<TextBlock TextWrapping="WrapWholeWords" Style="{StaticResource BodyTextBlockStyle}">
Expand All @@ -50,9 +49,8 @@
</controls:WrapPanel>



<Button Grid.Row="1" Margin="0,0,0,20" x:Name="PickPolicyFileButton" Click="PickPolicyFileButton_Click"
HorizontalAlignment="Center"
HorizontalAlignment="Center" RightTapped="PickPolicyFileButton_RightTapped" Holding="PickPolicyFileButton_Holding"
ToolTipService.ToolTip="Click/Tap to choose a XML policy file from your device.">

<Button.Flyout>
Expand Down Expand Up @@ -104,16 +102,13 @@
HeaderIcon="{ui:FontIcon Glyph=&#xE71D;}">

<controls:WrapPanel Orientation="Horizontal" HorizontalSpacing="15" VerticalSpacing="10">
<Button x:Name="Add" Content="Add"
Style="{StaticResource AccentButtonStyle}" />
<Button x:Name="Remove" Content="Remove"
Style="{StaticResource AccentButtonStyle}" />
<Button x:Name="ResetSelections" Content="Reset Selections"
Style="{StaticResource AccentButtonStyle}" />

<!-- Select All button to select all checkboxes -->
<Button x:Name="SelectAll" Content="Select All"
Style="{StaticResource AccentButtonStyle}" />
<Button x:Name="ApplyTheChangesButton" Content="Appy the Changes" Click="ApplyTheChangesButton_Click"
Style="{StaticResource AccentButtonStyle}" ToolTipService.ToolTip="If you checked or unchecked any new check boxes among the rule options, use this button to apply them to the policy you selected" />

<Button x:Name="RefreshRuleOptionsState" Content="Retrieve Rules States" Click="RefreshRuleOptionsState_Click"
ToolTipService.ToolTip="Retrieve the latest state of policy rule options from the policy file you selected"/>

<TeachingTip x:Name="MainTeachingTip" Target="{x:Bind PolicyRuleExpander}" Title="Error"/>
</controls:WrapPanel>
</controls:SettingsExpander>
<controls:SettingsCard x:Name="PolicyTemplate"
Expand Down
Loading

0 comments on commit f5c2090

Please sign in to comment.