From 551ad399e50cc811c1c7b5eb28c05d962acc43ca Mon Sep 17 00:00:00 2001 From: RobinpZA <165141638+RobinpZA@users.noreply.github.com> Date: Tue, 6 Oct 2026 08:17:56 +0200 Subject: [PATCH 1/5] Fix IncludeTags not enabling small-batch job mode --- .../Private/2.ProcessingFunctions/Start-ARIAutProcessJob.ps1 | 2 +- Modules/Private/2.ProcessingFunctions/Start-ARIProcessJob.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Private/2.ProcessingFunctions/Start-ARIAutProcessJob.ps1 b/Modules/Private/2.ProcessingFunctions/Start-ARIAutProcessJob.ps1 index ac17386..004791e 100644 --- a/Modules/Private/2.ProcessingFunctions/Start-ARIAutProcessJob.ps1 +++ b/Modules/Private/2.ProcessingFunctions/Start-ARIAutProcessJob.ps1 @@ -27,7 +27,7 @@ function Start-ARIAutProcessJob { $JobLoop = 1 Write-Output ((get-date -Format 'yyyy-MM-dd_HH_mm_ss')+' - '+"Starting ARI Automation Processing Jobs...") - if ($Heavy.IsPresent -or $InTag.IsPresent) + if ($Heavy -or $InTag) { Write-Output ('Heavy Mode Detected. Jobs will be run in small batches to avoid CPU and Memory Overload.') $EnvSizeLooper = 2 diff --git a/Modules/Private/2.ProcessingFunctions/Start-ARIProcessJob.ps1 b/Modules/Private/2.ProcessingFunctions/Start-ARIProcessJob.ps1 index 00cf563..1251e7e 100644 --- a/Modules/Private/2.ProcessingFunctions/Start-ARIProcessJob.ps1 +++ b/Modules/Private/2.ProcessingFunctions/Start-ARIProcessJob.ps1 @@ -42,7 +42,7 @@ function Start-ARIProcessJob { } } - if ($Heavy.IsPresent -or $InTag.IsPresent) + if ($Heavy -or $InTag) { Write-Host ('Heavy Mode or InTag Mode Detected. Jobs will be run in small batches to avoid CPU and Memory Overload.') -ForegroundColor Red $EnvSizeLooper = 5 From 4ee8efc229afdd5bad150110990a9583a1210740 Mon Sep 17 00:00:00 2001 From: RobinpZA <165141638+RobinpZA@users.noreply.github.com> Date: Tue, 6 Oct 2026 08:17:57 +0200 Subject: [PATCH 2/5] Declare SecurityCenter parameter on Invoke-ARISecurityCenterJob --- .../2.ProcessingFunctions/Invoke-ARISecurityCenterJob.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Private/2.ProcessingFunctions/Invoke-ARISecurityCenterJob.ps1 b/Modules/Private/2.ProcessingFunctions/Invoke-ARISecurityCenterJob.ps1 index ec53c94..a266360 100644 --- a/Modules/Private/2.ProcessingFunctions/Invoke-ARISecurityCenterJob.ps1 +++ b/Modules/Private/2.ProcessingFunctions/Invoke-ARISecurityCenterJob.ps1 @@ -18,7 +18,7 @@ Authors: Claudio Merola #> function Invoke-ARISecurityCenterJob { - Param($Subscriptions, $Automation, $Resources, $ARIModule) + Param($Subscriptions, $Automation, $Resources, $SecurityCenter, $ARIModule) if ($Automation.IsPresent) { From 8767d60a7cb532dab229f591187606d675c7e600 Mon Sep 17 00:00:00 2001 From: RobinpZA <165141638+RobinpZA@users.noreply.github.com> Date: Tue, 6 Oct 2026 08:17:57 +0200 Subject: [PATCH 3/5] Replace exit with throw, fix Debug log upload check, use Get-Help for -Help, drop AzureGermanCloud --- .../Get-ARIManagementGroups.ps1 | 7 +- .../Start-ARIGraphExtraction.ps1 | 5 +- Modules/Public/PublicFunctions/Invoke-ARI.ps1 | 68 ++----------------- .../Invoke-AzureRAMPInventory.ps1 | 5 +- 4 files changed, 10 insertions(+), 75 deletions(-) diff --git a/Modules/Private/1.ExtractionFunctions/Get-ARIManagementGroups.ps1 b/Modules/Private/1.ExtractionFunctions/Get-ARIManagementGroups.ps1 index 5de192b..1f49be7 100644 --- a/Modules/Private/1.ExtractionFunctions/Get-ARIManagementGroups.ps1 +++ b/Modules/Private/1.ExtractionFunctions/Get-ARIManagementGroups.ps1 @@ -26,12 +26,7 @@ function Get-ARIManagementGroups { $LocalResults = $QueryResult if ($LocalResults.Count -lt 1) { - Write-Host "ERROR:" -NoNewline -ForegroundColor Red - Write-Host "No Subscriptions found for Management Group: $ManagementGroup!" - Write-Host "" - Write-Host "Please check the Management Group name and try again." - Write-Host "" - Exit + throw "No Subscriptions found for Management Group: $ManagementGroup! Please check the Management Group name and try again." } else { Write-Debug ((get-date -Format 'yyyy-MM-dd_HH_mm_ss')+' - '+'Subscriptions found for Management Group: ' + $LocalResults.Count) diff --git a/Modules/Private/1.ExtractionFunctions/Start-ARIGraphExtraction.ps1 b/Modules/Private/1.ExtractionFunctions/Start-ARIGraphExtraction.ps1 index 30e8330..c428327 100644 --- a/Modules/Private/1.ExtractionFunctions/Start-ARIGraphExtraction.ps1 +++ b/Modules/Private/1.ExtractionFunctions/Start-ARIGraphExtraction.ps1 @@ -55,10 +55,7 @@ Function Start-ARIGraphExtraction { if(![string]::IsNullOrEmpty($ResourceGroup) -and [string]::IsNullOrEmpty($SubscriptionID)) { Write-Debug ((get-date -Format 'yyyy-MM-dd_HH_mm_ss')+' - '+'Resource Group Name present, but missing Subscription ID.') - Write-Output '' - Write-Output 'If Using the -ResourceGroup Parameter, the Subscription ID must be informed' - Write-Output '' - Exit + throw 'If Using the -ResourceGroup Parameter, the Subscription ID must be informed' } else { diff --git a/Modules/Public/PublicFunctions/Invoke-ARI.ps1 b/Modules/Public/PublicFunctions/Invoke-ARI.ps1 index 55d189c..89f1467 100644 --- a/Modules/Public/PublicFunctions/Invoke-ARI.ps1 +++ b/Modules/Public/PublicFunctions/Invoke-ARI.ps1 @@ -125,7 +125,7 @@ Function Invoke-ARI { param ( [ValidateSet(1, 2, 3)] [int]$Overview = 1, - [ValidateSet('AzureCloud', 'AzureUSGovernment', 'AzureChinaCloud', 'AzureGermanCloud')] + [ValidateSet('AzureCloud', 'AzureUSGovernment', 'AzureChinaCloud')] [string]$AzureEnvironment = 'AzureCloud', [string]$TenantID, [string]$AppId, @@ -188,8 +188,7 @@ Function Invoke-ARI { $RunLite = $true if (!$StorageAccount -or !$StorageContainer) { - Write-Output "Storage Account and Container are required for Automation mode. Aborting." - exit + throw "Storage Account and Container are required for Automation mode. Aborting." } } if ($Overview -eq 1 -and $SkipAPIs) @@ -198,65 +197,11 @@ Function Invoke-ARI { } $TableStyle = "Light19" - <######################################################### Help ######################################################################> - - Function Get-ARIUsageMode() { - Write-Host "" - Write-Host "Parameters" - Write-Host "" - Write-Host " -TenantID : Specifies the Tenant to be inventoried. " - Write-Host " -SubscriptionID : Specifies Subscription(s) to be inventoried. " - Write-Host " -ResourceGroup : Specifies one (or more) unique Resource Group to be inventoried, This parameter requires the -SubscriptionID to work. " - Write-Host " -AppId : Specifies the ApplicationID that is used to connect to Azure as service principal. This parameter requires the -TenantID and -Secret to work. " - Write-Host " -Secret : Specifies the Secret that is used with the Application ID to connect to Azure as service principal. This parameter requires the -TenantID and -AppId to work. If -CertificatePath is also used the Secret value should be the Certifcate password instead of the Application secret. " - Write-Host " -CertificatePath : Specifies the Certificate path that is used with the Application ID to connect to Azure as service principal. This parameter requires the -TenantID, -AppId and -Secret to work. The required certificate format is pkcs#12. " - Write-Host " -TagKey : Specifies the tag key to be inventoried, This parameter requires the -SubscriptionID to work. " - Write-Host " -TagValue : Specifies the tag value be inventoried, This parameter requires the -SubscriptionID to work. " - Write-Host " -SkipAdvisory : Do not collect Azure Advisory. " - Write-Host " -SkipPolicy : Do not collect Azure Policies. " - Write-Host " -SecurityCenter : Include Security Center Data. " - Write-Host " -IncludeTags : Include Resource Tags. " - Write-Host " -Online : Use Online Modules. " - Write-Host " -Debug : Run in a Debug mode. " - Write-Host " -AzureEnvironment : Change the Azure Cloud Environment. " - Write-Host " -ReportName : Change the Default Name of the report. " - Write-Host " -ReportDir : Change the Default Path of the report. " - Write-Host "" - Write-Host "" - Write-Host "" - Write-Host "Usage Mode and Examples: " - Write-Host "If you do not specify Resource Inventory will be performed on all subscriptions for the selected tenant. " - Write-Host "e.g. /> Invoke-ARI" - Write-Host "" - Write-Host "To perform the inventory in a specific Tenant and subscription use <-TenantID> and <-SubscriptionID> parameter " - Write-Host "e.g. /> Invoke-ARI -TenantID -SubscriptionID " - Write-Host "" - Write-Host "Including Tags:" - Write-Host " By Default Azure Resource inventory do not include Resource Tags." - Write-Host " To include Tags at the inventory use <-IncludeTags> parameter. " - Write-Host "e.g. /> Invoke-ARI -TenantID -IncludeTags" - Write-Host "" - Write-Host "Skipping Azure Advisor:" - Write-Host " By Default Azure Resource inventory collects Azure Advisor Data." - Write-Host " To ignore this use <-SkipAdvisory> parameter. " - Write-Host "e.g. /> Invoke-ARI -TenantID -SubscriptionID -SkipAdvisory" - Write-Host "" - Write-Host "Using the latest modules :" - Write-Host " You can use the latest modules. For this use <-Online> parameter." - Write-Host " It's a pre-requisite to have internet access for ARI GitHub repo" - Write-Host "e.g. /> Invoke-ARI -TenantID -Online" - Write-Host "" - Write-Host "Running in Debug Mode :" - Write-Host " To run in a Debug Mode use <-Debug> parameter." - Write-Host ".e.g. /> Invoke-ARI -TenantID -Debug" - Write-Host "" - } - $TotalRunTime = [System.Diagnostics.Stopwatch]::StartNew() if ($Help.IsPresent) { - Get-ARIUsageMode - Exit + Get-Help Invoke-ARI -Full + return } $PlatOS = Test-ARIPS @@ -289,8 +234,7 @@ Function Invoke-ARI { Set-AzContext -SubscriptionName $AzureConnection.Subscription -DefaultProfile $AzureConnection } catch { - Write-Output "Failed to set Automation Account requirements. Aborting." - exit + throw "Failed to set Automation Account requirements. Aborting. $_" } } @@ -455,7 +399,7 @@ Function Invoke-ARI { Write-Output "Sending Diagram file to Storage Account:" Write-Output $DDFile Set-AzStorageBlobContent -File $DDFile -Container $StorageContainer -Context $StorageContext | Out-Null - if($Debug.IsPresent) + if($PSBoundParameters.ContainsKey('Debug')) { $LogFilePath = Join-Path $DefaultPath 'DiagramLogFile.log' Set-AzStorageBlobContent -File $LogFilePath -Container $StorageContainer -Context $StorageContext -Force | Out-Null diff --git a/Modules/Public/PublicFunctions/Invoke-AzureRAMPInventory.ps1 b/Modules/Public/PublicFunctions/Invoke-AzureRAMPInventory.ps1 index b481163..1945421 100644 --- a/Modules/Public/PublicFunctions/Invoke-AzureRAMPInventory.ps1 +++ b/Modules/Public/PublicFunctions/Invoke-AzureRAMPInventory.ps1 @@ -1,7 +1,7 @@ function Invoke-AzureRAMPInventory { [CmdletBinding(PositionalBinding=$false)] param ( - [ValidateSet('AzureCloud', 'AzureUSGovernment', 'AzureChinaCloud', 'AzureGermanCloud')] + [ValidateSet('AzureCloud', 'AzureUSGovernment', 'AzureChinaCloud')] [string]$AzureEnvironment = 'AzureCloud', [string]$TenantID, [string]$AppId, @@ -38,8 +38,7 @@ function Invoke-AzureRAMPInventory { Set-AzContext -SubscriptionName $AzureConnection.Subscription -DefaultProfile $AzureConnection } catch { - Write-Output "Failed to set Automation Account requirements. Aborting." - exit + throw "Failed to set Automation Account requirements. Aborting. $_" } } From 80572e2c8ab8fa4d33da050f576d215d8d9fe75a Mon Sep 17 00:00:00 2001 From: RobinpZA <165141638+RobinpZA@users.noreply.github.com> Date: Tue, 6 Oct 2026 08:44:18 +0200 Subject: [PATCH 4/5] Load background jobs from the running module copy instead of the installed one --- Modules/Private/2.ProcessingFunctions/Start-ARIExtraJobs.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Private/2.ProcessingFunctions/Start-ARIExtraJobs.ps1 b/Modules/Private/2.ProcessingFunctions/Start-ARIExtraJobs.ps1 index 925412b..a4f2a53 100644 --- a/Modules/Private/2.ProcessingFunctions/Start-ARIExtraJobs.ps1 +++ b/Modules/Private/2.ProcessingFunctions/Start-ARIExtraJobs.ps1 @@ -37,7 +37,7 @@ function Start-ARIExtraJobs { $IncludeCosts, $CostData) - $ARIModule = 'AzureResourceInventory' + $ARIModule = Join-Path $MyInvocation.MyCommand.Module.ModuleBase 'AzureResourceInventory.psd1' #$ARIModule = 'C:\usr\src\PSModules\AzureResourceInventory\AzureResourceInventory' <######################################################### DRAW IO DIAGRAM JOB ######################################################################> From 30d7f5f5012b048ef028a5f9ce8c1f44acb9b042 Mon Sep 17 00:00:00 2001 From: RobinpZA <165141638+RobinpZA@users.noreply.github.com> Date: Tue, 6 Oct 2026 11:04:28 +0200 Subject: [PATCH 5/5] Document that IncludeTags writes one row per tag and enables Heavy mode batching Co-Authored-By: Claude Opus 5.5 --- Modules/Public/PublicFunctions/Invoke-ARI.ps1 | 2 +- docs/user-guide/faq.md | 2 ++ docs/user-guide/parameters.md | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/Public/PublicFunctions/Invoke-ARI.ps1 b/Modules/Public/PublicFunctions/Invoke-ARI.ps1 index 89f1467..14abf27 100644 --- a/Modules/Public/PublicFunctions/Invoke-ARI.ps1 +++ b/Modules/Public/PublicFunctions/Invoke-ARI.ps1 @@ -32,7 +32,7 @@ Use this parameter to include Quota information .PARAMETER IncludeTags - Use this parameter to include Tags of every Azure Resources + Use this parameter to include Tags of every Azure Resources. Each tag is written as its own row, and Heavy mode batching is enabled automatically to limit memory use. .PARAMETER Debug Output detailed debug information. diff --git a/docs/user-guide/faq.md b/docs/user-guide/faq.md index b3d25e6..0cb94d2 100644 --- a/docs/user-guide/faq.md +++ b/docs/user-guide/faq.md @@ -100,6 +100,8 @@ To speed up report generation: The `-IncludeTags` parameter includes all resource tags in the report. This is useful for environments that use tagging extensively for organization or governance. +Each tag is written as its own row, so a resource with 10 tags appears on 10 rows. Because this increases memory use, `-IncludeTags` automatically enables the same small-batch processing as `-Heavy`. Expect longer run times. + ### Can I run ARI without an internet connection? No, ARI needs to connect to Azure APIs to collect resource information. diff --git a/docs/user-guide/parameters.md b/docs/user-guide/parameters.md index 275095c..9d14840 100644 --- a/docs/user-guide/parameters.md +++ b/docs/user-guide/parameters.md @@ -32,7 +32,7 @@ Azure Resource Inventory (ARI) offers a wide range of parameters to customize yo | Parameter | Description | Example | |-----------|-------------|---------| | **SecurityCenter** | Include Security Center data | `-SecurityCenter` | -| **IncludeTags** | Include resource tags | `-IncludeTags` | +| **IncludeTags** | Include resource tags (one row per tag; also enables Heavy mode batching, so runs take longer) | `-IncludeTags` | | **SkipPolicy** | Skip Azure Policy collection | `-SkipPolicy` | | **SkipVMDetails** | Skip Azure VM Extra Details collection | `-SkipVMDetails` | | **SkipAdvisory** | Skip Azure Advisory collection | `-SkipAdvisory` |