Preparing for VBScript Deprecation: An Audit Guide for VBA and Internal Tools

· · VBScript, VBA, Excel, PowerShell, Office, Windows, Legacy Asset Reuse

Executive Summary

As of April 2026, Microsoft has published its policy of deprecating VBScript in phases: in Windows 11 version 24H2 it first becomes a Feature on Demand enabled by default, in the next phase it becomes disabled by default, and in the final phase it is planned for removal from a future Windows release. In other words, what you really should do now — before any “full rewrite” — is “make visible where the VBScript dependencies are”.

For VBA and Excel macros, the realistic concerns are two. One is cases that execute external .vbs files; the other is references to VBScript-type libraries such as VBScript.RegExp. For the latter, starting with Office version 2508 (Build 19127.20154) the RegExp class ships in the VBE as standard, so at least some RegExp-dependent code has become easier to migrate. On the other hand, in mixed environments where older Office clients remain, the same VBA can easily work on some machines and fail on others.

What makes migration hard is less VBScript itself than “the surrounding operations”. For example, even if you replace things so that Excel launches powershell.exe, it will not run in production if it trips over the attack surface reduction rules “Block all Office applications from creating child processes” or “Block Win32 API calls from Office macros”, or AppLocker, App Control for Business, PowerShell execution policy, signing operations, or the macro controls for MOTW-tagged files. The migration plan should be designed to include not just code conversion but policy, signing, and log auditing.

The shortest route is inventory → static detection → execution log collection → choosing the replacement → testing → phased rollout. This article organizes things in that order, for practical use.

The code that appears in this article is published on GitHub as a runnable, testable sample set (PowerShell audit scripts, replacement samples, reference VBA and Office Scripts code, and Pester tests).

vbscript-deprecation-vba-excel-macro-internal-tools-audit-guide - komurasoft-blog-samples (GitHub)

Sorting Out What Is Changing

The first thing to grasp is that this is not a story about “VBA being deprecated”. What Microsoft has published is strictly the phased deprecation of VBScript, and the impact on VBA projects concentrates mainly on execution of external .vbs files and references to VBScript-family libraries. The Microsoft 365 Developer Blog likewise identifies .vbs execution from VBA and use of VBScript.RegExp as the representative impact points.

For practical prioritization, this table makes the decisions easier.

Dependency pattern What happens Priority
Direct execution of .vbs from VBA/Excel From Phase 2 it fails depending on device configuration; in Phase 3 it stops as a rule High
VBScript.RegExp references Easily turn into defects in mixed environments where pre-2508 Office remains High
External process launches via WScript.Shell / Shell Even after replacement, may be stopped by ASR or AppLocker High
GPO logon/startup/shutdown scripts, Scheduled Tasks, Intune-deployed scripts Prone to mass outages on OS updates or policy switches High
VBScript Custom Actions in MSIs Install, repair, and uninstall suddenly fail High

This prioritization is a practical judgment based on the Windows-side VBScript deprecation plan, the official detection strategy, and the ASR/AppLocker/App Control specifications.

RegExp alone is a slightly different story. From Office version 2508 onward, the VBE includes the RegExp class as standard, so for RegExp use specifically, “part of the VBScript dependency can be resolved by an Office update”. However, this does not resolve automatically in organizations with old Office, slow update channels, mixed environments, or stale device images. Put both “the Office update” and “the Windows phase switch” into your ledger — that is the important part.

How to Run the Inventory

An inventory needs more than file-name searches. At minimum, we recommend keeping the following ten aspects as columns, per project, per tool, per business process.

  • (1) Method of detecting VBScript-dependent locations Record file search, code analysis, and log analysis separately.
  • (2) Use of CreateObject / GetObject / Execute / ExecuteGlobal etc. inside VBA The dependency hides inside strings, so static-search misses are common.
  • (3) External script calls from Excel macros Track WScript.Shell, the Shell function, wscript.exe / cscript.exe, and .vbs / .js / .ps1 separately.
  • (4) Script dependencies of internal batch jobs and tools Include Scheduled Tasks, GPO, Intune, operational scripts on shared folders, and installers.
  • (5) Security, permissions, signing, policy AppLocker, App Control for Business, ASR, PowerShell execution policy, digital signatures, whether admin rights are required.
  • (6) Replacement technologies and migration cost comparison Compare native VBA, PowerShell, .NET/VSTO, Office Scripts, and Power Automate.
  • (7) Test plan Separate unit, integration, user acceptance, and re-testing after policy application.
  • (8) Operating procedures and rollback State explicitly what must be reverted to recover, and how far to automate.
  • (9) Compatibility and performance Office version differences, 32/64bit, device performance, log-collection load, cloud-flow timeouts.
  • (10) A sample migration case study Build one representative example usable for explaining to the field.

Of these ten items, GPO, Scheduled Tasks, Intune-deployed scripts, MSI Custom Actions, and detection via Sysmon/AppLocker/App Control are explicitly highlighted as focus areas in Microsoft’s official guidance.

The overall migration flow stays on track if you think of it like this diagram.

External .vbs executionVBScript.RegExpGPO / Tasks / MSIUnknown / buried dependenciesAsset inventoryType of dependencyReplace with PowerShell or native VBAConsolidate onto the built-in RegExp of Office 2508+Fix centrally managed settings and deployed artifactsCollect execution logs via Sysmon / AppLocker / App ControlUnit testingIntegration testingPilot rollout in audit modePhased disabling of the VBScript FOD

Keep this order and you greatly reduce the classic do-over of “we rewrote it first, and then GPO or ASR knocked it down afterwards”.

Practical Detection and Code Examples

File Search and Enumerating Configuration

Microsoft’s detection guidance recommends recursively searching for .vbs while prioritizing paths with a clear purposeC:\Users, C:\ProgramData, C:\Scripts, etc. — and checking GPO, Scheduled Tasks, Intune-deployed scripts, and MSI packages on separate tracks. Sysmon’s vbscript.dll monitoring is effective, but Image Load monitoring carries heavy log volume and operational load, so it should be validated in a small pilot first.

# Roughly sweep script dependencies on devices and shared folders
$paths = @("C:\Users", "C:\ProgramData", "C:\Scripts")
$patterns = @(
  'wscript\.exe',
  'cscript\.exe',
  '\.vbs(\s|$)',
  'VBScript\.RegExp',
  'WScript\.Shell',
  'CreateObject\("VBScript\.RegExp"\)',
  'ExecuteGlobal'
)

$hits = foreach ($path in $paths) {
  if (Test-Path $path) {
    Get-ChildItem -Path $path -Recurse -File `
      -Include *.vbs,*.ps1,*.bat,*.cmd,*.wsf,*.hta,*.txt `
      -ErrorAction SilentlyContinue |
      Select-String -Pattern $patterns -AllMatches |
      Select-Object Path, LineNumber, Line
  }
}

$hits | Export-Csv .\vbscript-dependency-hits.csv -NoTypeInformation -Encoding UTF8

Next, sweep Task Scheduler. With internal tools, more often than in files, wscript.exe / cscript.exe / .vbs is buried inside task definitions.

# Extract VBScript invocations from Scheduled Tasks
Get-ScheduledTask | ForEach-Object {
  foreach ($a in $_.Actions) {
    if ($a.Execute -match 'wscript|cscript|mshta' -or $a.Arguments -match '\.vbs\b') {
      [pscustomobject]@{
        TaskName  = $_.TaskName
        TaskPath  = $_.TaskPath
        Execute   = $a.Execute
        Arguments = $a.Arguments
      }
    }
  }
} | Export-Csv .\task-vbscript-dependencies.csv -NoTypeInformation -Encoding UTF8

VBA Code Analysis

On the VBA side, looking only at the references dialog is not enough. CreateObject and GetObject can instantiate COM from a string, so code can be dependent even when nothing shows in the references. Microsoft’s VBA/Office documentation describes CreateObject as the basic means of creating COM objects, and FileSystemObject and Scripting.Dictionary are used in that form too. Also, reading a VBA project programmatically requires “Trust access to the VBA project object model”.

' Prerequisites:
'  - Enable "Trust access to the VBA project object model" in the Trust Center
'  - Protected projects require separate source export or confirmation with the owner
Sub ScanProjectForVbScriptRisks()

    Dim comp As Object
    Dim cm As Object
    Dim ws As Worksheet
    Dim nextRow As Long
    Dim patterns As Variant
    Dim p As Variant
    Dim i As Long
    Dim lineText As String

    patterns = Array( _
        "CreateObject(""VBScript.RegExp"")", _
        "VBScript.RegExp", _
        "WScript.Shell", _
        "Shell(", _
        ".vbs", _
        "wscript.exe", _
        "cscript.exe", _
        "ExecuteGlobal", _
        "Execute(" _
    )

    Set ws = ThisWorkbook.Worksheets.Add
    ws.Range("A1:D1").Value = Array("Module", "Line", "Pattern", "Code")
    nextRow = 2

    For Each comp In ThisWorkbook.VBProject.VBComponents
        Set cm = comp.CodeModule

        For i = 1 To cm.CountOfLines
            lineText = cm.Lines(i, 1)
            For Each p In patterns
                If InStr(1, lineText, CStr(p), vbTextCompare) > 0 Then
                    ws.Cells(nextRow, 1).Value = comp.Name
                    ws.Cells(nextRow, 2).Value = i
                    ws.Cells(nextRow, 3).Value = p
                    ws.Cells(nextRow, 4).Value = lineText
                    nextRow = nextRow + 1
                End If
            Next p
        Next i
    Next comp

    ws.Columns.AutoFit
    MsgBox "Scan finished: " & (nextRow - 2) & " hits"

End Sub

This scan picks up, at minimum, CreateObject("VBScript.RegExp"), WScript.Shell, Shell(, .vbs, and ExecuteGlobal. String-based execution like Execute / ExecuteGlobal in particular is a hotbed of inventory misses, because the dependency target and the executed code are assembled dynamically.

Log Analysis

At the stage of examining execution logs, the combination of Sysmon + AppLocker/App Control is powerful. Sysmon can track loads of vbscript.dll via Event ID 7, and AppLocker’s allow/audit events for scripts and MSIs are visible in Event Viewer. Run App Control for Business in audit mode, and scripts and MSIs are recorded in the AppLocker\MSI and Script log.

# Sysmon: find processes that loaded vbscript.dll
Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" -MaxEvents 2000 |
  Where-Object { $_.Id -eq 7 -and $_.Message -match 'vbscript\.dll' } |
  Select-Object TimeCreated, MachineName, Message

# AppLocker / App Control: check audit logs for scripts and MSIs
Get-WinEvent -LogName "Microsoft-Windows-AppLocker/MSI and Script" -MaxEvents 2000 |
  Where-Object { $_.Id -in 8005, 8006 } |
  Select-Object TimeCreated, Id, Message

The important thing here is collecting not just the “it ran” logs but also the “audit says it would have been blocked” logs. AppLocker’s audit events and App Control’s audit mode are well suited to safety checks before blocking in production.

Minimal Replacement Samples

For processing on the level of calling an external .vbs to write out a CSV, the shortest path is replacing it with native VBA first.

Sub ExportCsvNativeVba()

    Dim f As Integer
    Dim outPath As String

    outPath = ThisWorkbook.Path & "\out.csv"
    f = FreeFile

    Open outPath For Output As #f
    Print #f, "Code,Name"
    Print #f, "1001,Tokyo"
    Print #f, "1002,Osaka"
    Close #f

    MsgBox "CSV exported: " & outPath

End Sub

If you need to call external processing from Excel — including the OS, shared folders, AD, installers, and log collection — leaning on PowerShell is more realistic. Microsoft recommends PowerShell as the VBScript replacement, and the PowerShell side has official operational mechanisms for execution policy, signing, and Authenticode verification. Note that VBA’s Shell is asynchronous by default, so processing that needs ordering requires separate flow design or wait handling.

Sub RunModernPs()

    Dim cmd As String
    cmd = "powershell.exe -NoProfile -File """ & ThisWorkbook.Path & "\Normalize.ps1""" & _
          " -InputFile """ & ThisWorkbook.Path & "\in.csv""" & _
          " -OutputFile """ & ThisWorkbook.Path & "\out.csv"""

    Shell cmd, vbNormalFocus

End Sub
param(
  [string]$InputFile,
  [string]$OutputFile
)

Import-Csv $InputFile |
  Sort-Object Code |
  Export-Csv $OutputFile -NoTypeInformation -Encoding UTF8
# Apply and verify a signature
$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
Set-AuthenticodeSignature -FilePath .\Normalize.ps1 -Certificate $cert
Get-AuthenticodeSignature -FilePath .\Normalize.ps1

If the Excel processing completes entirely inside the workbook — formatting, aggregation, transformation — Office Scripts is also a strong option. Office Scripts targets Excel and is well suited to cloud-based, cross-platform use and Power Automate integration.

function main(workbook: ExcelScript.Workbook) {
  const sheet = workbook.getActiveWorksheet();
  const used = sheet.getUsedRange();
  used.getFormat().autofitColumns();

  const tables = workbook.getTables();
  if (tables.length > 0) {
    tables[0].getSort().apply([{ key: 0, ascending: true }], true);
  }
}

Choosing the Replacement Technology

The replacement should be chosen not by “what can it be written in” but by how much responsibility it will carry. PowerShell leans toward Windows, files, tasks, and installers; native VBA toward the inside of Office; Office Scripts toward Excel workbook processing; VSTO/.NET toward heavy desktop integration; Power Automate toward orchestration. The table below is a practical estimate built on the officially published characteristics of each approach. The effort figures are the author’s rough guide.

Alternative Suited processing Main strengths Main constraints Effort Priority
Native VBA Cell manipulation, reports, simple file output, light fixes to existing macros Easy to leverage existing assets, low user-training cost Weak governance over OS operations, signing, and distribution; external-process dependencies tend to remain Low High
PowerShell File operations, shared folders, AD, tasks, installers, ops automation Microsoft’s recommended replacement; signing and execution-policy operations available Requires tuning of execution policy, signing, ASR, AppLocker Medium High
.NET / VSTO Complex business logic, long-lived internal add-ins, heavy UI integration Deep Office integration; can deliver functionality as an application Windows-only; requires the VSTO runtime and distribution design High Medium
Office Scripts Routine formatting inside Excel workbooks, cloud execution, Power Automate integration Cross-platform, easy to share, tidy if Excel-centric Excel-only, unsuited to external OS work, limits with huge data Medium Medium
Power Automate Scheduled runs, approvals, file-arrival triggers, integrating other services Whole flow is easy to visualize; can embed PowerShell/.NET Operations design splits across desktop/cloud; permission design needed Medium–High Medium

Sketching the selection guideline a bit more intuitively:

YesYes, and sharing/cloud mattersNoYesNoYesFlow-triggered or approval-centricDiscovered VBScript dependencyCompletes inside the Excel workbook?Native VBAOffice ScriptsTouches the OS, files, tasks, AD?PowerShellHeavy UI integration or long-lived add-in?.NET / VSTOPower Automate

One addition about RegExp specifically: in environments where only Office version 2508 or later exists, consolidating onto Dim re As RegExp / Set re = New RegExp is quite effective. But if even one machine with older Office remains, that code hits the compile-compatibility wall. In mixed environments, decide first whether the migration policy is “new syntax”, “old syntax”, or “a branching wrapper”.

Testing and Operations

Test Plan

A VBScript migration is not covered by unit testing alone. Unless you re-test under production-equivalent conditions with the security policies active, the replacement PowerShell or .NET scripts will stop for entirely different reasons. Microsoft’s materials likewise treat PowerShell execution policy, AppLocker, App Control audit mode, ASR, and the macro controls for MOTW-tagged files as separate rules.

Level What to examine Example pass criteria
Unit testing Input/output, exception handling, encodings, regex results Returns the same results as the old processing
Integration testing Excel⇔PowerShell, shared folders, tasks, AD, report output The whole batch completes without errors
Security testing Signing, execution policy, AppLocker, App Control, ASR, MOTW Runs / audits as expected even after policies are applied
Acceptance testing Operating steps, duration, error-time messages Field procedures are simplified or preserved
Compatibility / performance testing Office version differences, large data, log-collection load Stable within acceptable performance on mixed devices

The points most often missed are these:

  • A replacement where Excel launches PowerShell may trip over ASR’s “Block all Office applications from creating child processes”.
  • Leaving VBA declarations or API calls in place may trip over ASR’s “Block Win32 API calls from Office macros”.
  • Test .xlsm / .ps1 files distributed via downloads or mail attachments behave differently depending on MOTW and signature state.
  • The Office Scripts + Power Automate combination is convenient, but with large CSVs or huge cell counts you must mind timeouts and data-transfer limits.
  • Sysmon’s Image Load monitoring is useful, but spread carelessly across the whole company it inflates log volume.

Migration Procedure Checklist

  • Statically searched for .vbs, wscript.exe, cscript.exe, VBScript.RegExp, WScript.Shell, Shell(, ExecuteGlobal
  • Inventoried GPO, Scheduled Tasks, Intune, shared-folder operations, and MSIs on separate tracks
  • Put Office versions and update channels into a ledger and identified remaining pre-2508 installs
  • Decided the replacement among “native VBA / PowerShell / .NET / Office Scripts / Power Automate”
  • Decided the signing policy and the certificate distribution policy
  • Tested the impact of AppLocker / App Control / ASR / execution policy
  • Collected audit logs in a pilot department
  • Documented the rollback procedure
  • Preserved the evidence of “unused” before disabling the VBScript FOD

Risks and Countermeasures

Risk Typical symptom Countermeasure
Hidden dependencies remain Month-start processing fails only in some departments Combine static search with Sysmon/AppLocker/App Control auditing
Security policies stop the replacement Converted to PowerShell, yet it won’t run when launched from Excel Put ASR, AppLocker, App Control into audit mode in a test environment first
Signing gaps cause production-only failures Works on the developer PC, refused on user PCs Lock in signing operations with Set-AuthenticodeSignature and Get-AuthenticodeSignature
RegExp breaks on mixed Office Compile errors on some machines Ledger the pre-2508 remainder; lead with a wrapper or with updates
Office Scripts / Flow are slow Timeouts on large CSVs Split files, batch the work, design synchronization points

The countermeasures in this table translate the design constraints in Microsoft’s official materials into internal operations.

Rollback means more than “reverting the code”. At minimum, think of restoring previous versions of deployed artifacts, reverting policies, the headroom to re-enable the optional feature, and continued log collection as a set. While VBScript still exists as a FOD, there is room to re-enable it as an optional feature per the Phase 2 guidance — but once it is removed in Phase 3, that escape hatch is gone.

A Sample Migration Case Study

As a typical example, take the accounting department’s monthly aggregation macro. Today, the Excel macro launches cleanup.vbs via WScript.Shell, validates codes with VBScript.RegExp after CSV formatting, and finally writes the output to a shared folder. This setup takes a direct hit from VBScript deprecation — and even with a naive port to PowerShell, it stalls again on ASR and signing operations.

The right answer in this case is to split it apart. Validation, formatting, and aggregation that complete inside Excel move to native VBA or the built-in RegExp of Office 2508+. File conversion and shared-folder I/O move to PowerShell. If the trigger is “a file arrived” or “daily at a set time”, move that to Power Automate. This untangles the responsibilities that had been stuffed into a single .vbs.

An example post-migration structure:

  • Excel macro: input checks, screen interaction, user-facing messages
  • PowerShell: CSV normalization, shared-folder I/O, log output
  • Signing: Authenticode signatures on the PowerShell scripts
  • Security: verify AppLocker/App Control in audit mode first; decide whether ASR exceptions are needed
  • Future extension: phase routine in-Excel processing over to Office Scripts

The advantage of this approach is that you cut loose the VBScript runtime dependency early without having to rebuild everything at once. Absorb RegExp via the Office update, move operational scripts to PowerShell, move the business flow to Power Automate — split by responsibility, and the blast radius of any failure shrinks too.

We recommend reading the official materials in this order.

  • VBScript deprecation: Timelines and next steps The starting point for confirming the overall roadmap and what each Phase means.
  • VBScript deprecation: Detection strategies for Windows Practical detection guidance covering Sysmon, GPO, Scheduled Tasks, Intune, and MSI Custom Actions.
  • Prepare your VBA projects for VBScript deprecation in Windows The most important from the VBA perspective. Covers the built-in RegExp, the handling of Office 2508 and later, and a compatibility table.
  • Differences between Office Scripts and VBA macros Helps decide whether Excel-centric processing should move to Office Scripts.
  • about_Execution_Policies / about_Signing / Set-AuthenticodeSignature / Get-AuthenticodeSignature The basic set for signing and execution-policy operations during a PowerShell migration.
  • Using Event Viewer with AppLocker / Use audit events to create App Control policy rules / Script enforcement with App Control for Business Needed for understanding audit-mode design, event collection, and script enforcement behavior.
  • Attack surface reduction rules reference The material for checking the block rules around Office child processes, Win32 APIs, and JS/VBS download execution.
  • Macros from the internet are blocked by default in Office Required reading for understanding MOTW issues during test distribution and production rollout.

As supporting tools, these come up often in our practice.

  • Sysmon The basis for monitoring vbscript.dll loads and collecting process-level events.
  • Sysmon configuration templates on GitHub SwiftOnSecurity’s sysmon-config is a high-quality starting template, and Olaf Hartong’s sysmon-modular is a modular, operations-friendly starting point.
  • oletools / olevba Suited to extracting VBA source from Office files and assisting detection of suspicious keywords and auto-executing macros.

In conclusion, preparing for VBScript deprecation takes more than “find the VBScript and replace it with PowerShell”. Managing the Office updates, code analysis, operational configuration, signing, ASR/AppLocker/App Control, and UAT in a single ledger is the fastest reliable way forward. Rescue early the areas an Office update can rescue, like RegExp; and detach with priority the areas that break on the Windows-side phase switches — .vbs execution and the GPO/task/MSI dependencies.

Recent articles sharing the same tags. Deepen your understanding with closely related topics.

These topic pages place the article in a broader service and decision context.

This article connects naturally to the following service pages.

Author Profile

Profile page for the article author.

Go Komura

Representative of KomuraSoft LLC

Focused on Windows software development, technical consulting, and investigations into failures that are difficult to reproduce.

Back to the Blog