#At file:///C:/work/wex/absv2/ based on revid:reggie.burnett@stripped
20 Reggie Burnett 2012-09-11
started build verifier code along with msi interop code
added:
AbsUtility/BuildVerifier.cs
AbsUtility/MSIDatabase.cs
AbsUtility/MSIInterop.cs
AbsUtility/MSIRecord.cs
AbsUtility/MSIView.cs
modified:
AbsJobProcessor/AbsJobProcessor.csproj
AbsJobProcessor/Program.cs
AbsUtility/AbsUtility.csproj
AbsUtility/Job.cs
=== modified file 'AbsJobProcessor/AbsJobProcessor.csproj'
=== modified file 'AbsJobProcessor/AbsJobProcessor.csproj'
--- a/AbsJobProcessor/AbsJobProcessor.csproj 2012-08-22 17:36:55 +0000
+++ b/AbsJobProcessor/AbsJobProcessor.csproj 2012-09-11 18:56:18 +0000
@@ -15,7 +15,7 @@
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
- <PlatformTarget>x86</PlatformTarget>
+ <PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
=== modified file 'AbsJobProcessor/Program.cs'
--- a/AbsJobProcessor/Program.cs 2012-09-04 21:25:29 +0000
+++ b/AbsJobProcessor/Program.cs 2012-09-11 18:56:18 +0000
@@ -16,6 +16,20 @@
try
{
+ MSIDatabase m = new MSIDatabase(@"c:\\test.msi");
+ m.Open();
+ DataTable dt2 = m.GetTable("File");
+ m.Close();
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message + ex.StackTrace);
+ Console.ReadLine();
+ }
+ return;
+
+ try
+ {
if (!Settings.ResolveFolders()) return;
if (!Utility.ShouldRun()) return;
=== modified file 'AbsUtility/AbsUtility.csproj'
--- a/AbsUtility/AbsUtility.csproj 2012-08-28 19:10:02 +0000
+++ b/AbsUtility/AbsUtility.csproj 2012-09-11 18:56:18 +0000
@@ -44,8 +44,13 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="BuildVerifier.cs" />
<Compile Include="Job.cs" />
<Compile Include="JobBuild.cs" />
+ <Compile Include="MSIDatabase.cs" />
+ <Compile Include="MSIInterop.cs" />
+ <Compile Include="MSIRecord.cs" />
+ <Compile Include="MSIView.cs" />
<Compile Include="Product.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Settings.cs" />
=== added file 'AbsUtility/BuildVerifier.cs'
--- a/AbsUtility/BuildVerifier.cs 1970-01-01 00:00:00 +0000
+++ b/AbsUtility/BuildVerifier.cs 2012-09-11 18:56:18 +0000
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Abs
+{
+ internal class BuildVerifier
+ {
+ public BuildVerifier(string series, string license, string file)
+ {
+ BuildFile = file;
+ Series = series;
+ License = license;
+ }
+
+ public string BuildFile { get; private set; }
+ public string Series { get; private set; }
+ public string License { get; private set; }
+
+ public void Verify()
+ {
+ VerifyFileExistsAndSize();
+ VerifyProperFileName();
+ MSIDatabase m = new MSIDatabase(BuildFile);
+ using (m)
+ {
+ m.Open();
+ VerifyProperFilesIncluded(m);
+ VerifyManifest(m);
+ }
+ }
+
+ private void VerifyFileExistsAndSize()
+ {
+ if (!File.Exists(BuildFile))
+ throw new Exception("Installer file does not exist");
+ FileInfo fi = new FileInfo(BuildFile);
+ if (fi.Length < 200 * 1024 * 1024)
+ throw new Exception("Installer is not large enough");
+ }
+
+ private void VerifyProperFileName()
+ {
+
+ }
+
+ private void VerifyProperFilesIncluded(MSIDatabase m)
+ {
+ }
+
+ private void VerifyManifest(MSIDatabase m)
+ {
+ }
+ }
+}
=== modified file 'AbsUtility/Job.cs'
--- a/AbsUtility/Job.cs 2012-09-04 20:04:05 +0000
+++ b/AbsUtility/Job.cs 2012-09-11 18:56:18 +0000
@@ -151,10 +151,19 @@
// use msbuild to build setup msi
BuildInstaller(series, license);
+ // now verify that the installer is likely valid
+ VerifyInstaller(series, license);
+
// mark job as done
RegisterBuild(series, license);
}
+ private void VerifyInstaller(string series, string license)
+ {
+ BuildVerifier v = new BuildVerifier(series, license, outputFileName);
+ v.Verify();
+ }
+
private void RegisterBuild(string series, string license)
{
MySqlHelper.ExecuteNonQuery(Settings.ConnectionString,
=== added file 'AbsUtility/MSIDatabase.cs'
--- a/AbsUtility/MSIDatabase.cs 1970-01-01 00:00:00 +0000
+++ b/AbsUtility/MSIDatabase.cs 2012-09-11 18:56:18 +0000
@@ -0,0 +1,57 @@
+ï»g System.Data;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Abs
+{
+ public class MSIDatabase : IDisposable
+ {
+ public MSIDatabase(string file)
+ {
+ Filename = file;
+ }
+
+ public string Filename { get; private set; }
+ public IntPtr Handle { get; private set; }
+
+ public void Open()
+ {
+ IntPtr handle = IntPtr.Zero;
+ WindowsErrorCode result = MSIInterop.MsiOpenDatabase(Filename, new IntPtr(MSIInterop.MSIDBOPEN_READONLY), out handle);
+ if (result != WindowsErrorCode.ERROR_SUCCESS)
+ throw new Exception("Unable to open msi database. Return value was: " + result);
+ Handle = handle;
+ }
+
+ public void Close()
+ {
+ if (Handle != IntPtr.Zero)
+ MSIInterop.MsiCloseHandle(Handle);
+ Handle = IntPtr.Zero;
+ }
+
+ public DataTable GetTable(string tableName)
+ {
+ MSIView view = new MSIView(this);
+ using (view)
+ {
+ view.Open("SELECT * FROM " + tableName);
+ return view.GetDataTable();
+ }
+ }
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ #endregion
+
+ }
+
+}
=== added file 'AbsUtility/MSIInterop.cs'
--- a/AbsUtility/MSIInterop.cs 1970-01-01 00:00:00 +0000
+++ b/AbsUtility/MSIInterop.cs 2012-09-11 18:56:18 +0000
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Abs
+{
+ public class MSIInterop
+ {
+ //***********************************
+ // DllImports for the MSI API's used.
+ //***********************************
+ [DllImport("msi.dll", SetLastError = true)]
+ public static extern WindowsErrorCode MsiOpenDatabase(string szDatabasePath, IntPtr phPersist, out IntPtr phDatabase);
+
+ [DllImport("msi.dll", ExactSpelling = true)]
+ public static extern WindowsErrorCode MsiCloseHandle(IntPtr hAny);
+
+ [DllImport("msi.dll", CharSet = CharSet.Unicode)]
+ public static extern WindowsErrorCode MsiDatabaseOpenViewW(IntPtr hDatabase, [MarshalAs(UnmanagedType.LPWStr)] string szQuery, out IntPtr phView);
+
+ [DllImport("msi.dll", CharSet = CharSet.Unicode)]
+ public static extern WindowsErrorCode MsiViewExecute(IntPtr hView, IntPtr hRecord);
+
+ [DllImport("msi.dll", CharSet = CharSet.Unicode)]
+ public static extern WindowsErrorCode MsiViewFetch(IntPtr hView, out IntPtr hRecord);
+
+ [DllImport("msi.dll", CharSet = CharSet.Unicode)]
+ public static extern WindowsErrorCode MsiDatabaseCommit(IntPtr hDatabase);
+
+ public const int MSICOLINFO_NAMES = 0; // return column names
+ public const int MSICOLINFO_TYPES = 1; // return column definitions, datatype code followed by width
+ [DllImport("msi.dll", ExactSpelling = true)]
+ public static extern WindowsErrorCode MsiViewGetColumnInfo(IntPtr hView, int eColumnInfo, out IntPtr hRecord);
+
+ [DllImport("msi.dll", CharSet = CharSet.Unicode)]
+ public static extern WindowsErrorCode MsiRecordGetString(IntPtr hRecord, int iField, StringBuilder szValueBuf, ref int pcchValueBuf);
+
+ [DllImport("msi.dll", CharSet = CharSet.Unicode)]
+ public static extern uint MsiRecordGetFieldCount(IntPtr record);
+
+ [DllImport("msi.dll")]
+ public static extern WindowsErrorCode MsiViewClose(IntPtr viewhandle);
+
+ //*****************************************
+ // Open mode constants for MsiOpenDatabase.
+ //*****************************************
+ public const int MSIDBOPEN_READONLY = 0; // database open read-only, no persistent changes
+ public const int MSIDBOPEN_TRANSACT = 1; // database read/write in transaction mode
+ public const int MSIDBOPEN_DIRECT = 2; // database direct read/write without transaction
+ public const int MSIDBOPEN_CREATE = 3; // create new database, transact mode read/write
+ public const int MSIDBOPEN_CREATEDIRECT = 4; // create new database, direct mode read/write
+ }
+
+ public enum WindowsErrorCode : int
+ {
+ ERROR_SUCCESS = 0,
+ ERROR_INVALID_PARAMETER = 87,
+ ERROR_NO_MORE_ITEMS = 259,
+ ERROR_INSTALL_USEREXIT = 1602,
+ ERROR_INSTALL_FAILURE = 1603,
+ ERROR_BAD_CONFIGURATION = 1610,
+ ERROR_INSTALL_IN_PROGRESS = 1618,
+ ERROR_INSTALL_SOURCE_ABSENT = 1612,
+ ERROR_UNKNOWN_PRODUCT = 1605,
+ ERROR_FUNCTION_FAILED = 1627,
+ ERROR_INVALID_HANDLE_STATE = 1609,
+ ERROR_MORE_DATA = 234,
+ ERROR_UNKNOWN_PROPERTY = 1608,
+ ERROR_CREATE_FAILED = 1631,
+ ERROR_OPEN_FAILED = 110,
+ ERROR_BAD_QUERY_SYNTAX = 1615
+ }
+
+}
=== added file 'AbsUtility/MSIRecord.cs'
--- a/AbsUtility/MSIRecord.cs 1970-01-01 00:00:00 +0000
+++ b/AbsUtility/MSIRecord.cs 2012-09-11 18:56:18 +0000
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Abs
+{
+ public class MSIRecord : IDisposable
+ {
+ public MSIRecord()
+ {
+ }
+
+ public MSIRecord(IntPtr record)
+ {
+ Handle = record;
+ }
+
+ public IntPtr Handle { get; private set; }
+
+ public void Close()
+ {
+ if (Handle != IntPtr.Zero)
+ MSIInterop.MsiCloseHandle(Handle);
+ Handle = IntPtr.Zero;
+ }
+
+ public uint NumberOfFields()
+ {
+ return MSIInterop.MsiRecordGetFieldCount(Handle);
+ }
+
+ public string GetString(int index, int maxSize = 1024)
+ {
+ var builder = new StringBuilder(maxSize);
+ var count = builder.Capacity;
+
+ WindowsErrorCode result = MSIInterop.MsiRecordGetString(Handle, index, builder, ref count);
+ if (result == WindowsErrorCode.ERROR_SUCCESS)
+ return builder.ToString();
+ throw new Exception(String.Format("Error retrieving string value for index {0}", index));
+ }
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ #endregion
+ }
+}
=== added file 'AbsUtility/MSIView.cs'
--- a/AbsUtility/MSIView.cs 1970-01-01 00:00:00 +0000
+++ b/AbsUtility/MSIView.cs 2012-09-11 18:56:18 +0000
@@ -0,0 +1,115 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Text;
+
+namespace Abs
+{
+ public class MSIView : IDisposable
+ {
+ public MSIView(MSIDatabase db)
+ {
+ Database = db;
+ }
+
+ public MSIDatabase Database { get; private set; }
+ public string ViewSQL { get; private set; }
+ public IntPtr Handle { get; private set; }
+ public List<string> ColumnNames { get; private set; }
+ public List<string> ColumnTypes { get; private set; }
+
+ public void Open(string sql)
+ {
+ ViewSQL = sql;
+
+ IntPtr view = IntPtr.Zero;
+ WindowsErrorCode result = MSIInterop.MsiDatabaseOpenViewW(Database.Handle, ViewSQL, out view);
+ if (result != WindowsErrorCode.ERROR_SUCCESS)
+ throw new Exception(String.Format("Unable to open view for {0} with error {1}", sql, result));
+ Handle = view;
+ ColumnNames = GetColumnInfo(MSIInterop.MSICOLINFO_NAMES);
+ ColumnTypes = GetColumnInfo(MSIInterop.MSICOLINFO_TYPES);
+ }
+
+ public void Close()
+ {
+ if (Handle != IntPtr.Zero)
+ MSIInterop.MsiCloseHandle(Handle);
+ Handle = IntPtr.Zero;
+ }
+
+ public MSIRecord FetchRecord()
+ {
+ IntPtr recordHandle = IntPtr.Zero;
+
+ WindowsErrorCode result = MSIInterop.MsiViewFetch(Handle, out recordHandle);
+ if (result == WindowsErrorCode.ERROR_NO_MORE_ITEMS) return null;
+ if (result != WindowsErrorCode.ERROR_SUCCESS)
+ throw new Exception(String.Format("Error fetching records for view {0} with error {1}", ViewSQL, result));
+ return new MSIRecord(recordHandle);
+ }
+
+ public DataTable GetDataTable()
+ {
+ DataTable dt = new DataTable();
+ for (int x = 0; x < ColumnNames.Count; x++)
+ dt.Columns.Add(GetColumn(ColumnNames[x], ColumnTypes[x]));
+
+ WindowsErrorCode result = MSIInterop.MsiViewExecute(Handle, IntPtr.Zero);
+ if (result != WindowsErrorCode.ERROR_SUCCESS)
+ throw new Exception(String.Format("Error executing table view for sql {0} with error {1}", ViewSQL, result));
+
+ while (true)
+ {
+ MSIRecord r = FetchRecord();
+ if (r == null) break;
+ DataRow row = dt.NewRow();
+ for (int x = 0; x < dt.Columns.Count; x++)
+ row[x] = r.GetString(x+1);
+ r.Close();
+ dt.Rows.Add(row);
+ }
+ return dt;
+ }
+
+ private List<string> GetColumnInfo(int type)
+ {
+ IntPtr record = IntPtr.Zero;
+ WindowsErrorCode result = MSIInterop.MsiViewGetColumnInfo(Handle, type, out record);
+ MSIRecord r = new MSIRecord(record);
+ uint numFields = r.NumberOfFields();
+
+ List<string> collection = new List<string>();
+ for (int x = 1; x <= numFields; x++)
+ collection.Add(r.GetString(x));
+ return collection;
+ }
+
+ private DataColumn GetColumn(string name, string typeName)
+ {
+ DataColumn c = new DataColumn();
+ c.ColumnName = name;
+ if (typeName.StartsWith("s") || typeName.StartsWith("g"))
+ c.DataType = Type.GetType("System.String");
+ else if (typeName == "i4" || typeName == "j4")
+ c.DataType = Type.GetType("System.Int64");
+ else if (typeName == "i2" || typeName.StartsWith("j"))
+ c.DataType = Type.GetType("System.Int32");
+ else if (typeName == "v0")
+ c.DataType = Type.GetType("byte[]");
+ else if (typeName == "O0")
+ c.DataType = Type.GetType("System.Object");
+ return c;
+ }
+
+ #region IDisposable Members
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ #endregion
+ }
+}
Attachment: [text/bzr-bundle] bzr/reggie.burnett@oracle.com-20120911185618-86jw1hc9yc9k27kc.bundle
| Thread |
|---|
| • bzr commit into ABSv2 branch (reggie.burnett:20) | Reggie Burnett | 11 Sep |