Automated Batch Export of SSRS Reports via PowerShell & SQL Agent
Overview: This solution automates bulk document extraction and rendering from SQL Server Reporting Services (SSRS). It documents the transition between the legacy native subscription injection mechanism and the PowerShell queue-driven export pipeline. The environment utilizes dedicated SQL Server Agent jobs to orchestrate batch student performance graphs, handle parameter XML serialization, and render files to network shares.
Architecture & End-to-End Workflow
[ Crystal Reports / Application UI ]
│
├─► Legacy: Writes to [dbo.uReportServerSubscriptionLog]
│ └─► SQL Agent: "Graphinator" executes dbo.uspgReportServerSubscription
│ └─► Calls ReportServer.dbo.CreateTask / CreateSubscription
│
└─► Modern: Writes to [dbo.uReportServerBatchQueue] (StatusCode = 0)
│
│ Polled via SQL Agent / Scheduled Script
▼
[ Get-BatchReports.ps1 ]
│ │
│ LoadReport() │ SetExecutionParameters()
│ & Render() │
▼ ▼
[ SSRS SOAP Web Service ] (http://localhost/ReportServer)
│
│ Returns binary stream
▼
[ File System Destination ] (e.g. \\Server\Share\ExportFolder\...)
│
│ Updates StatusCode = 2 (Success) or 3 (Failure)
▼
[ dbo.uReportServerBatchQueue ]
│
▼
[ SQL Agent: Rename / Post-Processing Jobs ]- Batch Request Ingestion: An application routine or Crystal Reports batch export identifies the target student cohort and inserts execution metadata into either the modern queue (
dbo.uReportServerBatchQueue) or the legacy subscription log (dbo.uReportServerSubscriptionLog). - Queue Polling & Dispatch:
- Modern Pipeline: A scheduled script or task invokes
Get-BatchReports.ps1, retrieving all pending jobs whereStatusCode = 0. - Legacy Pipeline: The SQL Server Agent job "The Graphinator" polls
uReportServerSubscriptionLogfor unprocessed records modified within the past 3 days (len(OwnerID) = 0) and processes them viadbo.uspgReportServerSubscription.
- Modern Pipeline: A scheduled script or task invokes
- Web Service Proxy Initialisation: In the PowerShell pipeline, the script instantiates a SOAP client against the local SSRS execution endpoint using
New-WebServiceProxyand Windows Integrated credentials (-UseDefaultCredential). - Session Instantiation & Parameter Binding: The report definition is loaded via
LoadReport(), parameters are unpacked from XML, and then explicitly bound to the execution session usingSetExecutionParameters(). - Stream Rendering & File Creation: The SOAP
Render()method exports the document to binary (such asPDF). After validating that the byte stream is non-zero, the array is written to disk via .NET file I/O. - Queue Reconciliation & Renaming: The database record is updated to
StatusCode = 2(Success) orStatusCode = 3(Failure). Downstream jobs (such asRename graph reports) standardize file naming conventions.
SQL Server Agent Jobs in Play
SQL Server Agent manages scheduling, triggering, and file handoffs across several specific jobs:
| Job Name | Step Name | Type | Role & Function |
|---|---|---|---|
| The Graphinator | Push out the scheduled graph reports | T-SQL | Polls uReportServerSubscriptionLog for items where len(OwnerID) = 0 and ModifiedDate > DATEADD(dd, -3, CURRENT_TIMESTAMP), executing dbo.uspgReportServerSubscription @scheduleid in a loop with a 3-second delay. |
| Rename graph reports | File Post-Processing | CmdExec / PowerShell | Executes post-export file renaming, stripping temporary prefixes, or moving finalized PDFs into student archive directories. |
| Batch Reports Dispatcher | Execute Get-BatchReports.ps1 | CmdExec | Runs powershell.exe -ExecutionPolicy Bypass -File "C:\Scripts\graphreports\Get-BatchReports.ps1" to process pending records in uReportServerBatchQueue. |
Database Objects in Play
| Database | Object Name | Object Type | Role & Description |
|---|---|---|---|
| Application DB | dbo.uReportServerBatchQueue | Table | Primary modern queue holding pending (StatusCode = 0), successful (2), and failed (3) export records. |
| Application DB | dbo.uReportServerSubscriptionLog | Table | Legacy queue table storing subscription GUIDs, target UNC paths, and serialized SSRS parameters. |
| Application DB | dbo.uspgReportServerSubscription | Stored Procedure | Legacy stored procedure that dynamically injected temporary subscriptions into the ReportServer catalog tables. |
ReportServer | dbo.ExecutionLog3 | System View | SSRS execution log used to diagnose render formats (RPL, PDF), execution time, byte counts, and engine errors. |
ReportServer | dbo.Catalog | System Table | SSRS metadata catalog containing report RDL definitions, folder hierarchies, and parameter validation constraints. |
Queue Table Schema (dbo.uReportServerBatchQueue)
BatchSeq(int, PK): Unique batch row sequence.ReportPath(varchar): SSRS catalog path (e.g.SiteReports/PerformanceGraph).FileName(varchar): Destination file name.ExportFilePath(varchar): Local or UNC target directory path.ReportParameters(xml): Serialized parameters (e.g.<ParameterValues><ParameterValue><Name>ID</Name><Value>12345</Value></ParameterValue></ParameterValues>).StatusCode(int): Execution state (0= Pending,1= In-progress,2= Success,3= Failure).LastStatusMsg(varchar): Status text or caught exception details.CreatedDate/ModifiedDate(datetime): Record audit timestamps.
Script Configuration Reference
Global execution options are isolated in C:\Scripts\graphreports\config.ps1:
| Variable | Type | Description | Generic Example |
|---|---|---|---|
$dbserver | String | Target SQL Server instance hosting the batch queue table. | "sqlserver.domain.local\INSTANCE" |
$database | String | Application database containing the queue table. | "Application_PRD" |
$rsserver | String | SSRS host name. Always use localhost when running locally to prevent loopback authentication rejections. | "localhost" |
$rsinstance | String | SSRS ReportServer virtual directory name. Typically ReportServer (default), not the database name. | "ReportServer" |
$FileYear | Integer | Fallback calendar/academic year passed when omitted by queue records. | 2026 |
$FileSemester | Integer | Fallback semester/term parameter passed when omitted. | 1 |
$FileType | String | Document category code required by cascading parameter chains. | 'Academic' |
Common Failure Modes & Troubleshooting
1. 0-Byte Destination Files
Root Cause: Writing to disk using [System.IO.FileMode]::Create before verifying that the SOAP render call returned bytes. If SSRS throws a parameter validation error or the session aborts, an empty file is written.
Resolution: Ensure commonCode.ps1 validates $null -ne $RenderOutput -and $RenderOutput.Length -gt 0 before opening the file stream, and wrap execution in a structured try/catch block.
2. HTTP 503: Service Unavailable
Root Cause: Setting $rsinstance to an invalid virtual directory (e.g. using the SQL instance name ReportServer_INSTANCE instead of ReportServer), or pointing $rsserver to an external FQDN blocked by Windows loopback security.
Resolution: Configure $rsserver = "localhost" and $rsinstance = "ReportServer". Verify availability in a local browser at http://localhost/ReportServer/ReportExecution2005.asmx?WSDL.
3. "Value provided for parameter 'X' is not valid" (rsInvalidReportParameter)
Root Cause: Cascading parameter validation failure. SSRS rejects child parameters (such as student ID) if the parent parameters (FileYear, FileSemester) are missing from the execution session, because the child value does not exist in the filtered "Available Values" query.
Resolution: Verify the ReportParameters XML column in dbo.uReportServerBatchQueue contains all required parent filter values.
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article