Public/Invoke-FoxProQuery.ps1
function Invoke-FoxProQuery { <# .SYNOPSIS Runs a query against FoxPro tables using the last official Visual Fox Pro OLEDB driver from Microsoft. .DESCRIPTION Runs a query against FoxPro tables using the last official Visual Fox Pro OLEDB driver from Microsoft. .PARAMETER Connection An OleDb connection to a FoxPro database. This can be useful (read: more efficient) if you need to execute many statements against a single data source. See the example. .PARAMETER Query What query should be executed? .PARAMETER DataSource Where is the FoxPro data? .PARAMETER ExtendedProperties Extended property settings for FoxPro databases go here. .PARAMETER As This determines the type of object returned to the caller or passed down the pipeline. Currently, the following object types are valid: "DataSet", "DataTable", "DataRow","SingleValue" or "NonQuery". Detail is "DataRow" .PARAMETER SqlParameters Specifies a hashtable of parameters for parameterized SQL queries. http://blog.codinghorror.com/give-me-parameterized-sql-or-give-me-death/ The values should be in a hash, which is easily/invisibly cast to an IDictionary by PowerShell. See the example. .NOTES The last Visual Fox Pro driver released by Microsoft was 32 bit only. Microsoft did not relase 64 bit version of this driver. If you need 64 bit support, you may have successs using the "AWE" drivers available via Microsoft Office. (These used to be called "Jet", up until about office 2003 or 2007). Install the 64 bit drivers can be a problem if you are using 32 bit versions of the Office apps, which may people still do as Microsoft offered (and might still continue to offer) 32 bit as a default. The VFP driver uses Datasource as the "root" of the database. You can specify tables in subdirectories. This means queries like these two, which point to the same tables, will work fine: SELECT * FROM emp ## Datasource is "c:\foo\subdir" SELECT * FROM .\subdir\emp ## Datasource is "c:\foo" This will not work on the ACE drivers, which will not let you traverse subdirectories. .EXAMPLE Invoke-FoxProQuery -Query "Select count(*) countOf From dept" -datasource "c:\fpdata" .EXAMPLE Invoke-FoxProQuery -Query "Select top (1) * From dept order by deptid" -datasource "c:\fpdata" .EXAMPLE Invoke-FoxProQuery -Query "Select * From dept where deptid = '1234'" -datasource "c:\fpdata" .EXAMPLE Invoke-FoxProQuery -Query "create table dept (deptid int) " -datasource "c:\temp" -As 'NonQuery' .EXAMPLE try { $cn = Get-FoxProConnection -DataSource 'c:\fpdata' Invoke-FoxProQuery -Connection $cn -Query $Query1 -SqlP $Param1 Invoke-FoxProQuery -Connection $cn -Query $Query2 -SqlP $Param2 Invoke-FoxProQuery -Connection $cn -Query $Query3 -SqlP $Param3 } catch { # re-throw Throw } finally { # clean up. This step is key or you risk leaking resources $cn.Close() $cn.Dispose() } #> param ( [Parameter( ParameterSetName = 'WithConnection', Mandatory = $true )] [System.Data.OleDb.OleDbConnection] $Connection, [Parameter( ParameterSetName = 'WithDataSource', Mandatory = $true )] [string] $DataSource, [Parameter( ParameterSetName = 'WithDataSource' )] [string] $ExtendedProperties, [Parameter(Mandatory = $true)] [string] $Query, [ValidateSet("DataSet", "DataTable", "DataRow", "SingleValue", "NonQuery")] [string] $As = "DataRow", [System.Collections.IDictionary] $SqlParameters ) try { switch ($PSCmdlet.ParameterSetName) { 'WithDataSource' { $cn = Get-FoxProConnection -DataSource $DataSource } 'WithConnection' { $cn = $Connection } } Invoke-OleDbQuery -As $As -Query $Query -SqlParameters $SqlParameters -Connection $cn } Catch { Throw } finally { if ($PSCmdlet.ParameterSetName -ne 'WithConnection') { <# If Get-FoxProConnection failed, trying to close the connection here will generate a runtime error ("You cannot call a method on a null-valued expression."). Since we are in finally{}, this error will not be caught. Fix: test that $cn is a thing before trying to close the connection. #> if ($cn) { $cn.Close() $cn.Dispose() } } } } |