
App Control for Business – Hope Is Not a Deployment Strategy
Learn how to safely deploy App Control in audit mode, analyze events, document rules, and prepare for enforcement.
There is no easy button for App Control for Business. If you find one, it is probably sitting in the same drawer as the current network diagram and the documentation your predecessor promised to finish.
I am starting there because application control walkthroughs have a habit of making the job look like a quick afternoon project. Create a policy. Upload the XML. Assign a group. Grab another cup of coffee and wait for the green check mark.
App Control for Business (WDAC) is one of the strongest security controls you can place on a Windows endpoint. It is also very good at exposing how little anyone truly knows about the software running in an environment. Somewhere in yours is an unsigned utility named after an employee’s initials, compiled when Windows 7 was still current, and used by three departments that cannot explain what it does. Mine has one too.
That is why my allowlist cannot be your allowlist. A vendor sample policy is a useful starting point, but it is not an answer. Your devices are the only reliable source of truth about what actually runs in your environment.
This is also why the series is split into two posts.
Part 1 is about evidence. We will build a custom XML base policy with the App Control Wizard, deploy it through Microsoft Intune in audit mode, generate activity on purpose, and review what Windows records. Nothing should be blocked.
Part 2 is about enforcement. We will turn the audit findings into supplemental policies, move a smaller pilot into enforced mode, give the help desk a runbook, and test the rollback path before anyone needs it.
The space between those two posts is not filler. App Control needs time, testing, and evidence. Give it all three.
What You Will Have When This Post Ends
By the end of this guide, you will have a pilot Windows device running a custom App Control for Business policy in audit mode. You will also have a test matrix for generating useful audit events and a backlog of proposed rules based on evidence from your own environment.
You will not have enforcement enabled. Not yet.
Prerequisites
Check these items before building the policy:
- On SCCM co-managed devices, move the Endpoint Protection workload slider to Intune.
- Azure Virtual Desktop is supported, including multi-session devices, but App Control for Business remains device scoped.
- Your admin account needs an Intune RBAC role that includes the App Control for Business permission.
Create two device groups now. Use one for the audit pilot and one for the enforcement pilot in Part 2. Do not recycle an existing production workstation group. Also, do not target the device that provides your only remote path back into the environment. That is the kind of shortcut that becomes a story you tell for years.
Build the Base Policy with the App Control Wizard
Download the App Control for Business Wizard from aka.ms/appcontrolwizard. The Wizard is Microsoft’s official open-source policy authoring tool. One of my other favorites, that I will not cover in this blog is App Control Manager.
Open the Wizard and select Policy Creator. On the policy type page, leave Multiple Policy Format and Base Policy selected. Multiple policy format allows the base policy to accept supplemental policies later. That will matter when different teams need different application exceptions and you do not want to weaken the base policy for everyone.
The next page asks you to choose a base template. This decision sets the starting circle of trust for the policy. The Wizard includes three primary options:
- Default Windows mode allows Windows operating system components, Microsoft Store apps, Microsoft 365 apps, OneDrive, Teams, and Windows Hardware Compatible drivers.
- Allow Microsoft mode includes everything in Default Windows mode, plus all Microsoft-signed software.
- Signed and Reputable mode expands trust by using the Intelligent Security Graph to authorize signed or reputation-approved software.
Think of these as the most restrictive on the left, and the least (still secure) restrictive on the right.

Configuring the Policy Rules
The Wizard applies a set of default rule options based on the template. Most of the work on this page is verification, but there are several options worth checking carefully.
- Enabled: Audit Mode. Files that would fail the policy are allowed to run and generate audit events. Leave this enabled.
- Enabled: Allow Supplemental Policies. Turn this on before deployment. A base policy must explicitly allow supplemental policies, and changing that later requires updating the base. More on Supplemental Policies in Part 2.
- Enable (based on your needs): Intelligent Security Graph Authorization. The Intelligent Security Graph, or ISG, uses the same Microsoft reputation intelligence that supports Defender SmartScreen and Microsoft Defender Antivirus. It is not a static allowlist. ISG evaluates a file’s hash and signing information to determine whether the file has a known-good reputation.
ISG can reduce rule maintenance in production, but business-critical applications should still be authorized through explicit rules or a managed installer. - Enabled: Managed Installer. This is an important one. Managed Installer allows App Control to trust applications deployed through a service you already manage, such as Intune or Configuration Manager. This can greatly reduce the number of individual application rules you need to create.
Leave this option enabled, but do not assume the switch does everything. Intune or Configuration Manager must still be configured as a managed installer. Applications that were installed earlier, or applications that update themselves outside your normal deployment process, may still need additional rules.
We will dig deeper into Managed Installer in Part 2. We will configure it through Intune. - Enabled: Update Policy No Reboot. This allows future policy updates to take effect without restarting the device. You will update this policy more than once.
- Enabled: Unsigned System Integrity Policy. Keep the lab policy unsigned. Policy signing improves tamper protection, but it also changes the update and recovery process. Save that conversation for production planning.
- Enabled: UMCI. User Mode Code Integrity extends the policy beyond kernel-mode binaries to user-mode executables and scripts. Without it, you are not testing the applications your users actually run.
One option deserves more than a quick glance: Disabled: Script Enforcement.
Script Enforcement can change how PowerShell and other scripting tools behave. Even in audit mode, some PowerShell sessions may run with limited capabilities. If your help desk relies on scripts for troubleshooting or automation, include those workflows in the pilot. It is much better to find compatibility issues now than after enforcement begins.

Save the XML in a controlled location. The Wizard writes the policy to the path you choose, and the PolicyID inside the XML is what future supplemental policies will reference.
Deploy the XML Through Intune
In the Microsoft Intune admin center, go to Endpoint security > App Control for Business > Create.
On the Basics page, enter a clear name and description. On Configuration settings, change Policy Creation Type to XML Upload, then upload the XML created by the Wizard.
Target devices and keep the pilot small.
Plan the Exit Before You Need It
Removing an App Control policy from Intune does not immediately make it disappear from the device. A policy deleted through the ApplicationControl CSP can remain active.
Microsoft’s documented removal process is to replace the existing policy with a version that allows everything, using the rules in %windir%\schemas\CodeIntegrity\ExamplePolicies\AllowAll.xml. After the updated policy reaches the device, delete it from Intune. The allow-all version stops the policy from blocking applications, and the next reboot completes the removal.
Build that AllowAll XML now, while the lab is calm and nobody is waiting on you. We will test the process in Part 2.
Confirm the Policy Actually Landed
Intune can tell you that a profile reached the device. The device can tell you whether Windows loaded the policy. Those are different facts, so confirm both.
open an elevated PowerShell prompt on the pilot device and run:
(CiTool -lp -json | ConvertFrom-Json).Policies |
Select-Object -Property PolicyID, FriendlyName, IsEnforced |
Format-ListFind the policy by its FriendlyName. The IsEnforced value should be False, confirming that the policy is active in audit mode.
Read the Events, Not Just the Portal Status
App Control records activity in two main event logs. If you check only Code Integrity, you can miss the script and installer behavior that matters most to your support teams.
CodeIntegrity > Operational covers executables, DLLs, and drivers:
- 3076 is the primary audit-mode event. It means the file would have been blocked if the policy were enforced.
- 3077 is the enforced-mode equivalent. You should not see it from this audit policy.
- 3089 contains signature information. Windows creates one 3089 event for each signature on a file. An unsigned file produces a single event with TotalSignatureCount set to 0. Use the Correlation ActivityID in the System section to connect it to the related 3076 event.
- 3033 and 3034 relate to revoked signatures or Lifetime Signing EKU expiration. Event 3034 is the audit-mode version.
AppLocker > MSI and Script covers installers, scripts, and COM objects. Events 8028 and 8029 are the audit and block events generated when Windows Lockdown Policy evaluates script-host activity.
Never create an allow rule from a file name alone. A name does not tell you whether the file is a legitimate dependency, a short-lived installer artifact, or something a user downloaded five minutes ago.
Scale It Up with Advanced Hunting
Event Viewer is fine when the pilot consists of one device. At twenty devices, it starts to feel like punishment.
If the pilot devices are onboarded to Microsoft Defender for Endpoint, you can review their App Control activity centrally in advanced hunting through DeviceEvents. The relevant action types begin with AppControl, so start wide and see what the lab has collected during the last seven days:
DeviceEvents
| where Timestamp > ago(7d)
| where ActionType startswith "AppControl"
| summarize Events=count(), Machines=dcount(DeviceName) by ActionType
| order by Machines descThat query gives you the shape of the data.
Next, pull the detail behind the audit events that matter most. AppControlCodeIntegrityPolicyAudited maps to event 3076, the primary App Control for Business audit event. These are the files that would have been blocked if you had already moved the policy into enforcement.
AdditionalFields contains useful policy and signing data, but leaving it as one JSON blob makes the results harder to work with. Parse it so the policy name, policy ID, publisher, issuer, Authenticode hash, and Fully Qualified Binary Name become their own columns:
DeviceEvents
| where Timestamp > ago(7d)
| where ActionType == "AppControlCodeIntegrityPolicyAudited"
| extend AF = todynamic(AdditionalFields)
| extend PolicyName = tostring(AF.PolicyName),
PolicyID = tostring(AF.PolicyID),
PublisherName = tostring(AF.PublisherName),
IssuerName = tostring(AF.IssuerName),
AuthenticodeHash = tostring(AF.AuthenticodeHash),
FQBN = tostring(AF.FQBN)
| project Timestamp, DeviceName, FileName, FolderPath,
PublisherName, IssuerName, AuthenticodeHash, FQBN,
InitiatingProcessFileName,
InitiatingProcessVersionInfoCompanyName,
PolicyName, PolicyID
| order by Timestamp descOnce the results start piling up, do not turn the review into an endless scroll. Collapse the events into a decision list. Grouping by publisher can turn a thousand individual events into a much shorter list of potential rules that deserve an actual conversation. This version also separates signed files from unsigned ones, because the two do not lead to the same decision:
DeviceEvents
| where Timestamp > ago(7d)
| where ActionType == "AppControlCodeIntegrityPolicyAudited"
| extend AF = todynamic(AdditionalFields)
| extend PublisherName = tostring(AF.PublisherName)
| extend Trust = iff(isempty(PublisherName), "Unsigned", "Signed")
| summarize Hits=count(),
Devices=dcount(DeviceName),
Folders=make_set(FolderPath, 10),
Files=make_set(FileName, 25)
by Trust, PublisherName
| order by Trust asc, Devices desc, Hits descRead the two groups differently. Signed rows are publisher rule candidates. Unsigned rows cannot get a publisher rule no matter how politely you ask.
Executables and DLLs are only half the story. Scripts and MSI files evaluated through Windows Lockdown Policy use a separate action type. Add this query or you may decide PowerShell is fine simply because you were looking in the wrong place:
DeviceEvents
| where Timestamp > ago(7d)
| where ActionType == "AppControlCIScriptAudited"
| project Timestamp, DeviceName, FileName, FolderPath, SHA256,
InitiatingProcessFileName, AdditionalFields
| order by Timestamp descWhen the review settles and you are ready to hand the evidence to the App Control Wizard, run one last query. The Wizard’s CSV import requires fifteen specific columns with specific names, and it is strict about both. This is Microsoft’s documented export query with a thirty-day window added, and the safest move is to change nothing else:
DeviceEvents
| where Timestamp > ago(30d)
| where ActionType startswith "AppControlCodeIntegrity"
| extend IssuerName = parsejson(AdditionalFields).IssuerName
| extend IssuerTBSHash = parsejson(AdditionalFields).IssuerTBSHash
| extend PublisherName = parsejson(AdditionalFields).PublisherName
| extend PublisherTBSHash = parsejson(AdditionalFields).PublisherTBSHash
| extend AuthenticodeHash = parsejson(AdditionalFields).AuthenticodeHash
| extend PolicyId = parsejson(AdditionalFields).PolicyID
| extend PolicyName = parsejson(AdditionalFields).PolicyName
| project-keep Timestamp, DeviceId, DeviceName, ActionType,
FileName, FolderPath, SHA1, SHA256,
IssuerName, IssuerTBSHash, PublisherName, PublisherTBSHash,
AuthenticodeHash, PolicyId, PolicyNameAdvanced hunting keeps DeviceEvents for 30 days. The seven-day windows in the earlier queries suit a weekly review, and the CSV export doubles as your archive once the pilot outlives retention. Export the results from the portal, set the file aside, and the next section puts it to work.
Turn Events Into Proposed Rules
The App Control Wizard can turn the Advanced Hunting results we collected earlier into policy rules. This saves us from manually recreating every finding in XML.
Start by exporting the results of the earlier Advanced Hunting query as a CSV file. In the App Control Wizard, select Policy Editor, choose Convert Event Log to an App Control Policy, and then select Parse Advanced Hunting. Browse to the exported CSV and allow the Wizard to process the results.
On the Configure Event Log Rules page, the Wizard organizes the findings into a list of applications and files that can be reviewed. Do not treat this as an automatic allowlist. Select only the applications you recognize, understand, and can connect to a legitimate business workflow.
For each approved application, choose the most appropriate rule type and select Add Allow Rule. Publisher and file attribute rules are usually easier to maintain because they can survive application updates. Hash rules are tied to a specific file version, while broad path rules can create more trust than intended.

Build the Tuning Backlog
If you’ve made it this far, I feel this is the MOST IMPORTANT part of my blog. An audit event tells you that a file ran. It does not tell you whether the business needs it, who owns it, or whether it deserves a permanent place in the policy.
I have worked in too many customer environments where nobody could explain why a rule existed. The person who created it had moved on, the original ticket was missing, and everyone was afraid to remove the rule because it might break something important. That is not policy management. That is archaeology.
Before adding a rule to the policy, record it in a tuning backlog and document the decision. Every rule should have a clear business reason, a named owner, an approver, supporting evidence, and a date when someone will review it again.
| Finding | Source event | Owner | Proposed rule type | Decision | Review date |
Include the related ticket or change record whenever possible. Six months from now, a filename, publisher, or hash will not explain why the rule exists. The documentation should.
If a rule has no business reason, owner, or approver, it is not ready for the policy. It is simply an unexplained rule waiting to become permanent.
Wrapping Up
There is still no easy button. What you have now is better: evidence from your own devices collected before anything was blocked.
At this point, you have built a custom XML base policy in the App Control Wizard, deployed it with Intune, and confirmed on the device that it is active in audit mode. You have also exercised real applications and support workflows, reviewed the resulting events, and started a tuning backlog with proposed rules tied to business owners.
Most importantly, nobody has been blocked and the help desk has not called.
In Part 2, we will turn those findings into supplemental policies, define evidence-based gates for enforcement, move a smaller pilot into enforced mode, build the help desk runbook for blocked applications, and test the rollback path with the AllowAll policy prepared earlier.

