Created
March 3, 2011 15:47
-
-
Save kitroed/852965 to your computer and use it in GitHub Desktop.
Use OleDb to parse the conents of certain FoxPro files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.IO; | |
using System.Data; | |
using System.Data.OleDb; | |
using System.Text.RegularExpressions; | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
foreach (string vfpFilePath in args) | |
{ | |
if (vfpFilePath != null && File.Exists(vfpFilePath)) | |
{ | |
Console.WriteLine(Reader.ProcessFoxProFile(vfpFilePath)); | |
} | |
} | |
} | |
} | |
/// <summary> | |
/// Requires the VFP OLE DB driver to be installed on the machine running this: | |
/// http://www.microsoft.com/downloads/en/details.aspx?FamilyID=e1a87d8f-2d58-491f-a0fa-95a3289c5fd4 | |
/// </summary> | |
public class Reader | |
{ | |
//private string[] _scxFields = { "objname", "properties", "protected", "methods", "reserved3" }; | |
public static string ProcessFoxProFile(string p) | |
{ | |
string vfpFilePath = Path.GetFullPath(p); | |
string vfpFileName = Path.GetFileName(p); | |
string vfpFileExtension = Path.GetExtension(p).ToLower(); | |
int numberOfErrors = 0; | |
DataTable dt = new DataTable(); | |
OleDbConnectionStringBuilder cb = new OleDbConnectionStringBuilder(); | |
cb.Provider = "VFPOLEDB.1"; | |
cb.DataSource = vfpFilePath; | |
OleDbConnection conn = new OleDbConnection(cb.ConnectionString); | |
conn.Open(); | |
dt.Clear(); | |
dt.Columns.Clear(); | |
string queryString = "select * from ?"; | |
OleDbCommand command = new OleDbCommand(queryString, conn); | |
command.Parameters.Add("@p1", OleDbType.VarChar).Value = vfpFileName; | |
OleDbDataAdapter da = new OleDbDataAdapter(command); | |
try | |
{ | |
da.Fill(dt); | |
} | |
catch (OleDbException) | |
{ | |
numberOfErrors++; | |
} | |
catch (InvalidOperationException) | |
{ | |
numberOfErrors++; | |
} | |
var contents = new StringBuilder(); | |
if (vfpFileExtension == ".vcx" || vfpFileExtension == ".scx" || vfpFileExtension == ".frx") | |
{ | |
string[] scxFields = { | |
"class", "baseclass", "objname", "properties", "protected", "methods", "reserved1", "reserved2", "reserved3", | |
"name", "expr", "picture", "comment", "tag", "tag2", "rangelo", "when", "valid", "error", "message", "show", "activate", "deactivate", "proccode", "setupcode", "initalval", | |
"supexpr" | |
}; | |
contents.Append(ExtractVfpFields(dt, scxFields)); | |
} | |
else if (vfpFileExtension == ".mnx") | |
{ | |
string[] mnxFields = { "name", "prompt", "command", "message", "procedure", "keyname", "keylabel", "skipfor", "levelname", "comment" }; | |
contents.Append(ExtractVfpFields(dt, mnxFields)); | |
} | |
else if (vfpFileExtension == ".dbc") | |
{ | |
foreach (DataRow r in dt.Rows) | |
{ | |
contents.Append(r["objecttype"].ToString().Trim()); | |
contents.Append(" "); | |
contents.Append(r["objectname"].ToString().Trim()); | |
contents.AppendLine(); | |
if (r["objectname"].ToString().Contains("StoredProceduresSource")) | |
{ | |
// Stored Procedure code is stored in a Memo(Binary) VFP field. | |
byte[] codeField = r["code"] as byte[]; | |
if (codeField != null) | |
{ | |
contents.AppendLine(GetFromByteArray(codeField)); | |
} | |
} | |
if (r["objecttype"].ToString().Contains("View")) | |
{ | |
byte[] propertyField = r["property"] as byte[]; | |
if (propertyField != null) | |
{ | |
contents.AppendLine(GetFromByteArray(propertyField)); | |
} | |
} | |
} | |
} | |
else if (vfpFileExtension == ".pjx") | |
{ | |
foreach (DataRow r in dt.Rows) | |
{ | |
contents.Append(r["name"].ToString()); | |
contents.Append(" "); | |
contents.Append(r["type"].ToString()); | |
if (r["type"].ToString().Contains("H")) | |
{ | |
contents.Append(" "); | |
contents.Append(r["devinfo"].ToString()); | |
} | |
contents.AppendLine(); | |
} | |
} | |
return contents.ToString(); | |
} | |
static private string ExtractVfpFields(DataTable vfpFile, string[] fieldsToExtract) | |
{ | |
var contents = new StringBuilder(); | |
contents.AppendLine(); | |
foreach (DataRow r in vfpFile.Rows) | |
{ | |
foreach (string f in fieldsToExtract) | |
{ | |
try | |
{ | |
if (r.Table.Columns.Contains(f) && r[f].ToString().Length > 0) | |
{ | |
// add extracted field name in square brackets | |
contents.AppendLine("\n[" + f + "]"); | |
// Since FoxPro has some funky binary data fields, let's try to get some useful info out of them: | |
if (r[f].GetType() == typeof(System.Byte[])) | |
{ | |
byte[] binaryField = r[f] as byte[]; | |
if (binaryField != null) | |
{ | |
contents.AppendLine(GetFromByteArray(binaryField)); | |
} | |
} | |
else | |
{ | |
// contents of the field straight to string. | |
contents.AppendLine(r[f].ToString().Trim()); | |
} | |
contents.AppendLine("[/" + f + "]\n"); | |
} | |
} | |
catch (ArgumentException) | |
{ | |
} | |
} | |
} | |
contents.AppendLine(); | |
return contents.ToString(); | |
} | |
static private string GetFromByteArray(byte[] incomingByte) | |
{ | |
// Convert the property field on a View to ASCII then append only ASCII *printable* characters | |
// (Regex reads: replace all not character [' ' (32)] to ['~' (126)] and [tab (9)] and [LF (10)] and [CR (13)] with a space) | |
return Regex.Replace(System.Text.Encoding.ASCII.GetString(incomingByte), @"[^\u0020-\u007E\u0009\u000A\u000D]", " ").Trim(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment