In most enterprise environments, software inventory is treated as a solved problem. Tools like Microsoft Endpoint Configuration Manager (MECM/SCCM), Intune, or even basic registry parsing are deployed, tuned, and assumed to provide complete visibility.
But inventory tools only report what is formally installed via Windows Installer, MSI, or recognized deployment mechanisms. They miss what lives outside those boundaries.
In our environment, we faced a compliance-driven cleanup of 1C:Enterprise instances. SCCM showed 100% compliance. Field audits and user reports showed otherwise. The gap? Legacy remnants, offline archives, and fully portable deployments running directly from network shares or user directories. These binaries never touched the registry, never registered in Appwiz.cpl, and remained invisible to standard CM inventories.
This article documents the exact architecture, implementation, and operational tuning used to detect, collect, and report on unauthorized or portable software across a Windows domain. The methodology is vendor-agnostic and can be adapted for any shadow-IT or compliance cleanup scenario.
Architecture & Design Rationale
Before diving into configuration, it’s critical to understand why we chose this stack:
| Component | Why It Was Chosen |
|---|---|
| Group Policy (Computer Config) | Centralized, auditable, runs in System context without user interaction. |
| Scheduled Task (At Startup) | Executes before user login, ensures full drive access, and leverages SYSTEM privileges. |
| VBScript Wrapper | Consistently hides PowerShell console output in GPO contexts and avoids rare startup crashes that can occur when PowerShell is launched directly in System context on certain Windows builds. |
| PowerShell Detection Script | Native, zero-dependency, recursive file/folder scanning with exclusion logic to protect I/O. |
| UNC Network Share | Centralized, agent-less collection. Each endpoint writes its own CSV, enabling easy scaling and audit trails. |
Key Design Decisions:
- Startup Trigger, not Logon: Ensures coverage for locked machines, shared terminals, and remote servers.
NT AUTHORITY\SYSTEMContext: Guarantees read access to all volumes, including those with restrictive ACLs.- Overwrite vs Append: Each boot generates a fresh report. No data accumulation, no stale state, simpler aggregation.
Implementation: Step-by-Step Deployment
1. Create & Link the GPO
Launch gpmc.msc to open the Group Policy Management Console. Navigate to the OU containing your target computer objects. Create a new GPO tailored for this detection scope.

Name it descriptively: Det_PortableSoftware_1C_Inventory. Ensure it’s linked to an OU with computer objects, not users.
2. Configure Computer Configuration → Scheduled Tasks
Open the GPO editor. Navigate to:Computer Configuration → Preferences → Control Panel Settings → Scheduled Tasks

3. Create the Scheduled Task (Action & General Settings)
Right-click → New → Scheduled Task (At least Windows 7).

General Tab:
- Action:
Update(ensures idempotent deployment across GPO refresh cycles) - Name:
Det_1C_Portable_Scan - Run as:
NT AUTHORITY\SYSTEM - ✅
Run whether user is logged on or not - ✅
Run with highest privileges - ✅
Hidden(prevents UI flicker during boot)

Triggers Tab:
- Begin the task:
At startup - ✅
Delay task for: 1 minute(allows network stack and DFS/DFS-R to stabilize before share access)

Actions Tab:
Instead of launching PowerShell directly, we use a VBScript wrapper to handle console suppression reliably.
- Program/script:
C:\Windows\System32\wscript.exe - Add arguments:
"\\yourdomain\SYSVOL\yourdomain.com\scripts\Det_1C_Wrapper.vbs"

4. VBScript Wrapper (Det_1C_Wrapper.vbs)
Store this in SYSVOL\...scripts\. It launches PowerShell silently.
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "powershell.exe -ExecutionPolicy Bypass -File ""\\yourdomain\SYSVOL\yourdomain.com\scripts\Det_1C_Detection.ps1""", 0, False
Why not direct PowerShell? GPO Scheduled Tasks sometimes inherit inconsistent execution policies or console handles in System context. wscript.exe guarantees a detached, silent execution path across Windows 10/11/Server 2016-2022.
The Detection Engine: PowerShell & Performance Tuning
Scanning every drive recursively at boot is a major I/O risk. The following script is optimized for production:
- Dynamically discovers drives
- Excludes known high-traffic/system directories
- Overwrites (not appends) to prevent bloated logs
- Includes execution timing for baseline monitoring
- Handles CSV parsing safely for paths with commas


# Det_1C_Detection.ps1
# Production-ready, performance-tuned portable software scanner
$ComputerName = $env:COMPUTERNAME
$SharePath = "\\fileserver\1c_inventory"
$ReportPath = Join-Path $SharePath "$ComputerName.csv"
# Patterns to flag
$filePatterns = @("1cv8.exe", "1cv8s.exe", "1cestart.exe", "1cv8c.exe", "1cv8cons.exe")
$folderPatterns = @("1c*", "*1cv8*", "*1centerprise*")
# Critical exclusions to prevent boot I/O spikes
$excludeDirs = @(
"$env:ProgramData",
"C:\Windows",
"C:\Program Files",
"C:\Program Files (x86)",
"$env:SystemRoot\System32"
)
# Dynamically discover all local & mapped drives
$drives = Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Root -ne "\\" }
# Initialize report (overwrite, not append)
"ComputerName,Type,FullPath,FileSize,LastWriteTime" | Out-File -FilePath $ReportPath -Encoding UTF8 -Force
function Test-IsExcluded {
param([string]$Path)
foreach ($ex in $excludeDirs) {
if ($Path.StartsWith($ex, [System.StringComparison]::OrdinalIgnoreCase)) {
return $true
}
}
return $false
}
$sw = [System.Diagnostics.Stopwatch]::StartNew()
foreach ($drive in $drives) {
$root = $drive.Root
if (-not (Test-Path $root)) { continue }
# 1. File scan (usually faster & more targeted)
try {
Get-ChildItem -Path $root -Filter "*.exe" -Recurse -ErrorAction SilentlyContinue |
Where-Object { $filePatterns -contains $_.Name -and -not (Test-IsExcluded $_.FullName) } |
ForEach-Object {
"$ComputerName,File,$($_.FullName),$($_.Length),$($_.LastWriteTime)" |
Out-File -FilePath $ReportPath -Append -Encoding UTF8
}
} catch {
# Silently continue on permission/access errors
}
# 2. Folder scan (limited recursion depth to protect I/O)
try {
Get-ChildItem -Path $root -Directory -Depth 5 -ErrorAction SilentlyContinue |
Where-Object {
$folderPatterns -contains $_.Name -or
$_.Name -like "1c*" -or
$_.Name -like "*1cv8*"
} |
Where-Object { -not (Test-IsExcluded $_.FullName) } |
ForEach-Object {
"$ComputerName,Folder,$($_.FullName),$($_.Length),$($_.LastWriteTime)" |
Out-File -FilePath $ReportPath -Append -Encoding UTF8
}
} catch {}
}
$sw.Stop()
Write-Host "[$ComputerName] Scan completed in $($sw.Elapsed.TotalSeconds) seconds" -ForegroundColor Green
Key Optimizations:
Get-PSDrivedynamically maps volumes. No hardcodedD:\, E:\.-Depth 5on folder scans prevents infinite recursion on massive data drives.Test-IsExcludedprotects system & program directories.- Execution time is logged. If a machine consistently exceeds 30s, investigate high I/O or large data volumes.
Data Aggregation: From CSVs to Actionable Reports
Each endpoint generates a CSV at \\fileserver\1c_inventory\<COMPUTERNAME>.csv. Raw CSVs are useful for forensics, but leadership & compliance teams need a consolidated view.

Use ImportExcel (cross-platform compatible) to merge, clean, and export. Note the shift from Get-Content to Import-Csv for robust comma/quote handling.
# Aggregation Script (Run on admin workstation/CI server)
Import-Module ImportExcel -ErrorAction Stop
$SourceFolder = "D:\1c_inventory_reports"
$OutputExcel = "D:\1c_inventory_reports\1C_Scan_Aggregated.xlsx"
$data = foreach ($csv in Get-ChildItem -Path $SourceFolder -Filter "*.csv") {
$Computer = $csv.BaseName
try {
$rows = Import-Csv -Path $csv.FullName -ErrorAction Stop
$found = $rows | Where-Object { $_.FullPath -ne $null } | Select-Object -ExpandProperty FullPath -Unique
if ($found.Count -gt 0) {
[PSCustomObject]@{
Computer = $Computer
FoundItems = ($found -join "; ")
ItemCount = $found.Count
LastScan = (Get-Item $csv.FullName).LastWriteTime
}
}
} catch {
Write-Warning "Failed to process $csv : $($_.Exception.Message)"
}
}
if ($data.Count -eq 0) {
Write-Host "No findings detected." -ForegroundColor Yellow
exit
}
$data | Export-Excel -Path $OutputExcel -WorksheetName "DetectedPortable" -BoldTopRow -FreezeTopRow -AutoSize -PassThru | Format-Table -AutoSize
Why Import-Csv? If a path contains commas (e.g., C:\Users\Name, Jr\1C), Get-Content will break your column alignment. Import-Csv handles RFC 4180 escaping natively.
Operational Pitfalls & Troubleshooting
Even well-architected scripts fail in production without addressing these real-world constraints:
| Issue | Root Cause | Fix |
|---|---|---|
| Empty CSVs or “Access Denied” | DOMAIN COMPUTERS lacks Write permissions on Share/NTFS | Grant Change on Share, Modify on NTFS. Use icacls & net share to verify. |
| Boot stalls / High Disk Queue | Recursive scan on 10TB data volume | Add drive-specific exclusions, reduce -Depth, or schedule via at startup + 5min delay. |
| False Positives | Backup folders named 1C_Export or dev sandboxes | Add keyword exclusions: Where-Object { $_.Name -notlike "*Backup*" -and $_.Name -notlike "*Dev*" } |
| Task kills scan mid-way | Default Scheduled Task timeout (3 days/1 hour) | GPO Task → Settings tab → ✅ Do not stop the task if it runs longer than: |
| GPO not applying | Computer blocked, offline during refresh, or OU filtering | Run gpupdate /force, check gpresult /h report.html, verify WMI/Security filtering. |
Pro-Tip: GPO Processing Order & Security Filtering
By default, Authenticated Users (which includes DOMAIN COMPUTERS) have Read access. If you’re using Security Filtering, ensure the computer group is explicitly added, or revert to Authenticated Users for simplicity.
Conclusion
SCCM and Intune are excellent for tracking formally deployed software. But shadow IT, portable executables, and legacy remnants live outside those boundaries. This GPO + PowerShell architecture closes that visibility gap without installing agents, licensing third-party scanners, or compromising system performance.
By combining:
- System-context startup execution
- Performance-aware scanning logic
- Centralized CSV collection
- Robust CSV→Excel aggregation
…you get a lightweight, auditable, and compliant inventory overlay that actually reflects reality.
Next Steps in Production:
- Validate on a pilot OU first.
- Monitor execution times & I/O counters during initial boots.
- Integrate findings into your CM/Intune compliance dashboard via REST API or scheduled import.
- Automate remediation (e.g.,
Remove-Itemor quarantine) once patterns are confirmed safe.
Have you encountered portable software blind spots in your environment? What detection layers are missing from your current stack? Drop a comment below.

Infrastructure Engineer with hands-on experience in Windows Server, Active Directory, SCCM, Exchange, and Linux environments. Concentrated on resolving production issues and keeping systems stable and reliable.
Привет!
Дима я тобой горжусь.
Круто!
Доброго времени суток!Спасибо (^_^)