Thứ Năm, 13 tháng 9, 2007

Generate PDB files in C#

class PDBHeader
{
#region Declarations
char[] databaseName={'\0','\0','\0','\0','\0','\0','\0',
'\0','\0','\0','\0','\0','\0','\0','\0',
'\0','\0','\0','\0','\0','\0','\0','\0',
'\0','\0','\0','\0','\0','\0','\0',
'\0','\0'}; // 32 Bytes

UInt16 fileAttributes = 0X0008; // 2 Bytes
UInt16 version = 0X0000; // 2 Bytes
UInt32 creationDate; // 4 Bytes
UInt32 modificationDate; // 4 Bytes
UInt32 lastBackupDate; // 4 Bytes
UInt32 modification=0X0000; // 4 Bytes
UInt32 appInfoArea=0X0000; // 4 Bytes
UInt32 sortInfoArea=0X0000; // 4 Bytes
char[] type={'d','a','t','a'}; // 4 Bytes
char[] creatorID; // 4 Bytes
UInt32 uniqueID=0X0000; // 4 Bytes
UInt32 nextRecord=0X0000; // 4 Bytes
UInt16 numRecords; // 2 Bytes
#endregion

#region Properties
public UInt16 NumRecords
{
set
{
numRecords=value;
}
get
{
return numRecords;
}
}
public DateTime CreationDate
{
set
{
TimeSpan ts=DateTime.Now-value;
creationDate=(UInt32)ts.TotalSeconds;
}
}
public DateTime ModificationDate
{
set
{
TimeSpan ts=DateTime.Now-value;
modificationDate=(UInt32)ts.TotalSeconds;
}
}
public DateTime LastBackupDate
{
set
{
TimeSpan ts=DateTime.Now-value;
lastBackupDate=(UInt32)ts.TotalSeconds;
}
}

public string CreatorID
{
set
{
if (value.Length==4)
{
creatorID=value.ToCharArray();
}
else
{
throw new PDBException("Creator ID" +
" is invalid (must be 4 charactors)");;
}
}
get
{
return new String(creatorID);
}
}

public string DataBaseName
{
set
{
if (value.Length<=32)
{
databaseName=value.ToCharArray();
}
else
{

throw new PDBException("Database Name" +
" Exceeds 32 Charactors");;
}
}
get
{
return new String(databaseName);
}
}

#endregion

#region Functions

public PDBHeader()
{
// Palm databse store total number
// of seconds since 01-01-1904
TimeSpan ts=
DateTime.Now-DateTime.Parse("01-01-1904");
creationDate=(UInt32)ts.TotalSeconds;
modificationDate=(UInt32)ts.TotalSeconds;
lastBackupDate=(UInt32)ts.TotalSeconds;
numRecords=0;
}

public override string ToString()
{
string getAll="";
getAll+=HexEncoding.GetStringToChar(databaseName,32);
getAll+=fileAttributes.ToString("X4");
getAll+=version.ToString("X4");
getAll+=creationDate.ToString("X8");
getAll+=modificationDate.ToString("X8");


getAll+=lastBackupDate.ToString("X8");
getAll+=modification.ToString("X8");
getAll+=appInfoArea.ToString("X8");
getAll+=sortInfoArea.ToString("X8");
getAll+=HexEncoding.GetStringToChar(type,4);
getAll+=HexEncoding.GetStringToChar(creatorID,4);
getAll+=uniqueID.ToString("X8");
getAll+=nextRecord.ToString("X8");
getAll+=numRecords.ToString("X4");

return getAll;
}
ii. RecordList Section
The size of the recordlist section depends on the number of records. Each record uses 8 bits to store record information. The PDBRecordList class is used to represent a recordlist.

Collapse
class PDBRecordList
{
#region Declarations
UInt32 offset=0; // 4 Bytes (Offset of the record)
byte recordAttribute=0X40;
char[] uniqueID={'\0','\0','\0'}; // 3 Bytes (Unique ID for each record)
string dataRecord=""; // Record data for current record
#endregion

#region Properties
public string DataRecord
{
set
{
dataRecord=value;
}
get
{
return dataRecord;
}
}
public UInt32 RecordOffset
{
set
{
offset=value;
}
get
{
return offset;
}
}
#endregion

#region Functions
public PDBRecordList(string str)
{
dataRecord=str;
}
public override string ToString()
{

string getAll="";
getAll+=offset.ToString("X8");
getAll+=recordAttribute.ToString("X2");
getAll+=HexEncoding.GetStringToChar(uniqueID,3);
return getAll;
}

#endregion
}
iii. Data Section
It is the main section to store information related to the records. Each record is separated by a null terminated character ('\0'). The size of each record may vary but the number of columns should be the same.

Using the code
The PDBCreators class is used to create databases.

Collapse
class PDBCreators
{
PDBHeader header=new PDBHeader();
ArrayList pdbRecord=new ArrayList();
public PDBCreators()
{
}
public PDBHeader PDBHeaders
{
set
{
header=value;
}
get
{
return header;
}
}
public Object[] AddRecord
{
set
{
string row="";
for (int i=0; i {
if (value[i].GetType().ToString()=="System.Int32")
continue;
row+=value[i].ToString().Trim()+'\0';
}
pdbRecord.Add(new PDBRecordList(row));
}
}

public void GeneratePDB(string fileName)
{
try
{
FileStream fs=new FileStream(fileName,FileMode.Create);
BinaryWriter bw=new BinaryWriter(fs);
int discard=0;
UInt32 index=78; // Header length is 78 Bytes
header.NumRecords=(UInt16)pdbRecord.Count;

bw.Write(HexEncoding.GetBytes(header.ToString(),
out discard));

// start index of Data List Area
index+=(UInt32)(pdbRecord.Count*8)+2;
string result="";
for (int i=0; ipdbRecord.Count; i++)
{
PDBRecordList rec=(PDBRecordList)pdbRecord[i];
rec.RecordOffset=index;
bw.Write(HexEncoding.GetBytes(rec.ToString(),
out discard));
index+=(UInt32)rec.DataRecord.Length;
result+=rec.DataRecord;
}
char[] padding={'\0','\0'}; // Two bytes for backup bits
bw.Write(HexEncoding.GetBytes(
HexEncoding.GetStringToChar(padding,2),
out discard));
result=HexEncoding.GetStringToChar(
result.ToCharArray(),result.Length);
bw.Write(HexEncoding.GetBytes(result,out discard));
bw.Close();
fs.Close();
}
catch (Exception exc)
{
throw new PDBException("Error" +
" in writing pdb file "+exc.Message);
}

}
}
The PDBGenerator reads two file formats (CSV and XML) and displays data in table format in a DataGrid. This data can be changed. It reads all table data from the XML file and displays table names in a combo box.

Collapse
PDBCreators pdb=new PDBCreators();
pdb.PDBHeaders.DataBaseName=this.txtDBName.Text;
pdb.PDBHeaders.CreatorID=this.txtCreatorID.Text;

DataTable recordsTable;
if (recordsDataSet.Tables.Count>0 &&
this.cmbTableNames.Items.Count>0 &&
recordsDataSet.Tables.Contains(this.cmbTableNames.Text))
recordsTable=recordsDataSet.Tables[this.cmbTableNames.Text];
else
{
MessageBox.Show("There is no table to convert",
"PDB Generator",MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
for (int i=0; i pdb.AddRecord=recordsTable.Rows[i].ItemArray;
try
{
pdb.GeneratePDB(this.txtDestination.Text+"\\"+
this.txtDBName.Text+".pdb");
MessageBox.Show("PDB Generated Successfully",
"PDB Generator",MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
catch(Exception exc)
{
MessageBox.Show("Error in PDB Generation"+exc.ToString(),
"PDB Generator",MessageBoxButtons.OK,
MessageBoxIcon.Information);
}

Không có nhận xét nào: