Skip to content

Instantly share code, notes, and snippets.

@kitroed
Created March 3, 2011 15:47
Show Gist options
  • Save kitroed/852965 to your computer and use it in GitHub Desktop.
Save kitroed/852965 to your computer and use it in GitHub Desktop.
Use OleDb to parse the conents of certain FoxPro files
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