Public/Get-ServiceNowTable.ps1
function Get-ServiceNowTable { [OutputType([System.Data.DataTable])] <# .SYNOPSIS Gets table from ServiceNow and writes data back to Dashworks database table .DESCRIPTION Uses ServiceNow REST API to read table data and writes data back to a Dashworks database table Creates the table in Custom if it does not already exist Supports OAuth and Basic Auth .PARAMETER TableName Name of ServiceNow table to import. .PARAMETER DBPath SQLite DB file to write data too. .PARAMETER DLLPath Path to the System.Data.SQLite.dll file .PARAMETER NameValuePairs Optional . Specify name value pairs to be imported from table. If ommited all name value pairs are imported. .PARAMETER ChunkSize Specifies number of rows to import from each ServiceNow table at a time. Default is 5000 rows. .PARAMETER UseOAuth If true use OAuth otherwise use Basic Auth. Default is true. .INPUTS None. You cannot pipe objects to Add-Extension. .OUTPUTS None. .EXAMPLE PS> Get-ServiceNowTableSQLite -TableName cmdb_ci_computer -DLLPath $DLLPath -DBPath $DBPath .LINK Online version: https://dashworks.atlassian.net/wiki/spaces/DWY/pages/1111949418/ServiceNow+preview #> param ( [Parameter(Mandatory=$true)][string] $TableName, [Parameter(Mandatory=$false)][string] $NameValuePairs, [Parameter(Mandatory=$false)][string] $ChunkSize = 1000, [Parameter(Mandatory=$true)][PSObject] $AuthToken ) $OAuthToken=$AuthToken.PSObject.Copy() Write-Debug ("INFO: Get-ServiceNowTable") Write-Debug ("INFO: Table Name: {0}" -f $tablename) Write-Debug ("INFO: Chunk Size: {0}" -f $ChunkSize) [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # Set headers for ServiceNow Requests $headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' $headers.Add('Accept','application/json') $headers.Add('Content-Type','application/json') if ($OAuthToken.expires -lt (Get-date).AddMinutes(10)) { $OAuthToken = Update-ServiceNowToken -OAuthToken $OAuthToken [void]$headers.Add('Authorization',$OAuthToken.AuthHeader) } else{ [void]$headers.Add('Authorization',$OAuthToken.AuthHeader) } $method = 'Get' $response = $null $offset=0 $limit = $ChunkSize $count=$limit $stopwatch = [system.diagnostics.stopwatch]::StartNew() $stopwatch2 = [system.diagnostics.stopwatch]::StartNew() while ($count -eq $limit) { #Check to see if the OAuth token is still going to be valid for the request. If not, get a new one. if ($OAuthToken.expires -lt (Get-date).AddMinutes(10)) { Write-Debug ("INFO: Token Expires at: {0}, current time: {1} - forcing new OAuth token" -f $OAuth.expires, (get-date)) $OAuthToken = Update-ServiceNowToken -OAuthToken $OAuthToken [void]$headers.Remove("Authorization") [void]$headers.Add('Authorization',$OAuthToken.AuthHeader) } # Specify endpoint uri $uri="$($OAuthToken.ServerURL)/api/now/table/$TableName"+"?sysparm_limit={1}&sysparm_offset={0}&sysparm_display_value=true" -f $offset, $limit if($NameValuePairs){$uri = $uri + '&' + $NameValuePairs} Write-Debug ("INFO: URI: {0}" -f $URI) try{ $pagedresponse = (Invoke-RestMethod -Headers $headers -Method $method -Uri $uri -ContentType 'application/json' -UseBasicParsing).result }catch{ Write-Debug ("ERROR: Service Now request failed") #Write-Debug ("ERROR: StatusCode: {0}" -f $_.Exception.Response.StatusCode.value__) #Write-Debug ("ERROR: StatusDescription: {0}" -f $_.Exception.Response.StatusDescription) Write-Debug ("ERROR: Message: {0}" -f $_.Exception.Message) break; } $response += $pagedresponse $count = $pagedresponse.count $offset = $offset + $limit Write-Debug ("INFO: Read: {0} rows from: {1}. This batch took {2}ms" -f $response.Count, $TableName, $stopwatch2.ElapsedMilliseconds) $stopwatch2.Restart() } Write-Debug ("INFO: Time to Pull from ServiceNow: {0}ms" -f $stopwatch.ElapsedMilliseconds) $stopwatch.Restart() $dtResults = New-Object System.Data.DataTable $ScriptBlock=$null $ScriptBlock += '$entryColumnList = ($entry | Get-Member -MemberType NoteProperty).Name'+"`n" if ($response.count -gt 0) { $DataColumnList = @{} $response | foreach-Object {$_ | get-member -MemberType NoteProperty} | Where-Object {$null -eq $DataColumnList[$($_.Name)]} | foreach-Object {$DataColumnList.Add($_.Name,$_.Name) | Out-Null} foreach($DataColumnName in ($DataColumnList.GetEnumerator()).Name) { if (!$dtResults.Columns.Contains($DataColumnName)) { $stopwatch2.Restart() $GetPopulatedEntryBlock='if($response | where-object{$_.' + $DataColumnName + ' -ne [DBNULL]::Value} | select-object -First 1) {$response | where-object{$_.' + $DataColumnName + ' -ne [DBNULL]::Value} | select-object -First 1 | Get-Member | where-object{$_.MemberType -eq "NoteProperty"} | where-object{$_.Name -eq ''' + $DataColumnName + '''}}' $GetPopulatedEntryBlock = $ExecutionContext.InvokeCommand.NewScriptBlock($GetPopulatedEntryBlock) $PopulatedOutput = & $GetPopulatedEntryBlock if ($PopulatedOutput){ $DataColumn = $PopulatedOutput } else{ $DataColumn = $response | select-object -First 1 | Get-Member | where-object{$_.MemberType -eq "NoteProperty"} | where-object{$_.Name -eq $DataColumnName} } if ($DataColumn.Definition.substring(0,$DataColumn.Definition.IndexOf(' ')) -eq 'System.Management.Automation.PSCustomObject') { $datatype = 'string' $dtResults.Columns.Add($DataColumn.Name,$datatype) | Out-Null $dtResults.Columns.Add($DataColumn.Name + "_link",$datatype) | Out-Null $ScriptBlock += 'if ($entryColumnList.Contains(''' + $DataColumn.Name + ''') -and $entry.' + $DataColumn.Name + '.getType().Name -eq "PSCustomObject") {$DataRow.' + $DataColumn.Name + ' = $entry.' + $DataColumn.Name + '.display_value} else {$DataRow.' + $DataColumn.Name + " = [DBNULL]::Value};`n" $ScriptBlock += 'if ($entryColumnList.Contains(''' + $DataColumn.Name + ''') -and $entry.' + $DataColumn.Name + '.getType().Name -eq "PSCustomObject") {$DataRow.' + $DataColumn.Name + '_link = $entry.' + $DataColumn.Name + '.link.substring($entry.' + $DataColumn.Name + '.link.LastIndexOf(''/'')+1) } else {$DataRow.' + $DataColumn.Name + " = [DBNULL]::Value};`n" } else { $DataType = switch ($DataColumn.Definition.substring(0,$DataColumn.Definition.IndexOf(' '))) { 'datetime' {'datetime'} 'bool' {'boolean'} 'long' {'int64'} 'string' {'string'} 'object' {'string'} default {'string'} } $dtResults.Columns.Add($DataColumn.Name,$datatype) | Out-Null $ScriptBlock += 'if ($entryColumnList.Contains(''' + $DataColumn.Name + ''')) {$DataRow.' + $DataColumn.Name + ' = $entry.' + $DataColumn.Name + ' } else {$DataRow.' + $DataColumn.Name + " = [DBNULL]::Value};`n" } } } Write-Debug ("INFO: Time to Process Columns: {0}ms" -f $stopwatch.ElapsedMilliseconds) $ScriptBlockToRun = $ExecutionContext.InvokeCommand.NewScriptBlock($ScriptBlock) $stopwatch.Restart() foreach($entry in $response) { $DataRow = $dtResults.NewRow() . $ScriptBlockToRun $dtResults.Rows.Add($DataRow) } Write-Debug ("INFO: Time to Process Rows: {0}ms" -f $stopwatch.ElapsedMilliseconds) $stopwatch = $null } return @(,($dtResults)) } |