public bool MsiAddInternalBinaryStream(IntPtr hDatabase, string cabname, string cabId, string cabfullpath) { //for info on the _Streams table, see MSDN: // http://msdn.microsoft.com/en-us/library/aa372919(VS.85).aspx Dictionary <int, Dictionary <string, string> > tableRecords = new Dictionary <int, Dictionary <string, string> >(); Dictionary <string, string> record = new Dictionary <string, string>(); uint retVal = CwMsiWin32.ERROR_SUCCESS; string selectQuery = "SELECT * FROM `_Streams`"; IntPtr hView = IntPtr.Zero; IntPtr hRecord = IntPtr.Zero; //open the database view retVal = CwMsiWin32.MsiDatabaseOpenViewW(hDatabase, selectQuery, out hView); MsiThrowOnFailure(hDatabase, retVal, "MsiDatabaseOpenViewW()"); //create a new record hRecord = CwMsiWin32.MsiCreateRecord(2); //2 fields: Name and Data //set the Name column of the _Streams table to the Cabinet name (file name on disk) retVal = CwMsiWin32.MsiRecordSetStringW(hRecord, 1, cabId); MsiThrowOnFailure(hDatabase, retVal, "MsiRecordSetStringW: Failed to set the Name column in the _Streams table to '" + cabname + "'"); //set the Data column of the _Streams table to the Cabinet name (full file path location on disk) retVal = CwMsiWin32.MsiRecordSetStreamW(hRecord, 2, cabfullpath); MsiThrowOnFailure(hDatabase, retVal, "MsiRecordSetStream: Failed to set the Data column in the _Streams table to '" + cabfullpath + "'"); //apply the update retVal = CwMsiWin32.MsiViewModify(hView, CwMsiWin32.MSIMODIFY_INSERT, hRecord); MsiThrowOnFailure(hDatabase, retVal, "MsiViewModify: Failed to apply update to CAB '" + cabId + "'"); //commit database retVal = CwMsiWin32.MsiDatabaseCommit(hDatabase); MsiThrowOnFailure(hDatabase, retVal, "MsiDatabaseCommit: Could not commit msi db."); CwMsiWin32.MsiCloseHandle(hView); CwMsiWin32.MsiCloseHandle(hRecord); return(true); }
public void MsiCreateEditRecordInTable(IntPtr hDatabase, string tableName, string action, int recordnumber, int[] fieldnumbers, ArrayList fieldvalues) { uint retVal = CwMsiWin32.ERROR_SUCCESS; int numfields = fieldvalues.Count; int msiAction = -1; //create a view to be used later for the operation IntPtr hView = IntPtr.Zero; string q = "SELECT * FROM `" + tableName + "`"; retVal = CwMsiWin32.MsiDatabaseOpenViewW(hDatabase, q, out hView); MsiThrowOnFailure(hDatabase, retVal, "MsiDatabaseOpenViewW('" + q + "')"); //execute the view retVal = CwMsiWin32.MsiViewExecute(hView, IntPtr.Zero); MsiThrowOnFailure(hDatabase, retVal, "MsiViewExecute()"); IntPtr hRecord = (IntPtr)(0); //create a record ptr with numfields if (action == "CreateRecord") { hRecord = CwMsiWin32.MsiCreateRecord((uint)numfields); msiAction = CwMsiWin32.MSIMODIFY_INSERT; if (hRecord == IntPtr.Zero) { throw new Exception("MsiCreateRecord"); } int fieldnum = 1; //note: not a zero-based index! //loop through each field in this record and set it foreach (object val in fieldvalues) { if (val.GetType() == typeof(string)) { retVal = CwMsiWin32.MsiRecordSetStringW(hRecord, (uint)fieldnum, (string)val); } else if (val.GetType() == typeof(Int32)) { retVal = CwMsiWin32.MsiRecordSetInteger(hRecord, (uint)fieldnum, (Int32)val); } else if (val.GetType() == typeof(Int16)) { retVal = CwMsiWin32.MsiRecordSetInteger(hRecord, (uint)fieldnum, (Int16)val); } MsiThrowOnFailure(hDatabase, retVal, "MsiRecordSetStringW(" + fieldnum.ToString() + ", '" + val + "')"); fieldnum++; } } else if (action == "ChangeFieldsInRecord") { //make sure the fieldnumbers size and fieldvalues size match if (fieldnumbers.Length != fieldvalues.Count) { retVal = CwMsiWin32.MsiCloseHandle(hView); MsiThrowOnFailure(hDatabase, retVal, "MsiCloseHandle(hView)"); throw new Exception("fieldnumbers and fieldvalues are not equal."); } hRecord = MsiGetRecordHandle(hDatabase, hView, recordnumber); int i = 0; //loop through all field numbers we want to change in this record //and alter those fields in the record we just retrieved foreach (int fieldnum in fieldnumbers) { retVal = CwMsiWin32.MsiRecordSetStringW(hRecord, (uint)fieldnum, fieldvalues[i].ToString()); MsiThrowOnFailure(hDatabase, retVal, "MsiRecordSetStringW(hRecord," + fieldnum.ToString() + "," + fieldvalues[i] + ")"); i++; } msiAction = CwMsiWin32.MSIMODIFY_UPDATE; } else { retVal = CwMsiWin32.MsiCloseHandle(hView); MsiThrowOnFailure(hDatabase, retVal, "MsiCloseHandle(hView)"); throw new Exception("Error: Invalid action specified '" + msiAction + "'!"); } if (hRecord == (IntPtr)(-1)) { throw new Exception("Failed to retrieve hRecord!"); } //perform the operation on the MSI database retVal = CwMsiWin32.MsiViewModify(hView, msiAction, hRecord); MsiThrowOnFailure(hDatabase, retVal, "MsiViewModify - failed to alter/create record"); //cleanup retVal = CwMsiWin32.MsiCloseHandle(hRecord); MsiThrowOnFailure(hDatabase, retVal, "MsiCloseHandle(hRecord)"); retVal = CwMsiWin32.MsiCloseHandle(hView); MsiThrowOnFailure(hDatabase, retVal, "MsiCloseHandle(hView)"); retVal = CwMsiWin32.MsiDatabaseCommit(hDatabase); MsiThrowOnFailure(hDatabase, retVal, "MsiDatabaseCommit(hDatabase)"); }
public void MsiCreateRecordFromMsiTable(IntPtr hDatabase, string tableName, object tableStruct, int numfields) { uint retVal = CwMsiWin32.ERROR_SUCCESS; IntPtr hView = IntPtr.Zero; string q = "SELECT * FROM `" + tableName + "`"; IntPtr hRecord = (IntPtr)(0); int fieldnum = 1; //create a view to be used later for the operation retVal = CwMsiWin32.MsiDatabaseOpenViewW(hDatabase, q, out hView); MsiThrowOnFailure(hDatabase, retVal, "MsiDatabaseOpenViewW('" + q + "')"); //execute the view retVal = CwMsiWin32.MsiViewExecute(hView, IntPtr.Zero); MsiThrowOnFailure(hDatabase, retVal, "MsiViewExecute()"); //create the record hRecord = CwMsiWin32.MsiCreateRecord((uint)numfields); if (hRecord == IntPtr.Zero) { throw new Exception("MsiCreateRecord"); } //get the fields for this table - note we can't use [type].GetType().GetFields() //because this function returns the fields in an unpredictable order! string[] fields = MsiTableGetFieldNames(tableName); if (fields == null) { throw new Exception("No fields for table '" + tableName + "'."); } if (fields.Length != numfields) { throw new Exception("Field count mismatch: fields.Length=" + fields.Length.ToString() + " / numfields=" + numfields.ToString()); } foreach (string thisfield in fields) { FieldInfo fi = tableStruct.GetType().GetField(thisfield); object value = fi.GetValue(tableStruct); if (value.GetType() == typeof(string)) { retVal = CwMsiWin32.MsiRecordSetStringW(hRecord, (uint)fieldnum, (string)value); } else if (value.GetType() == typeof(int)) { retVal = CwMsiWin32.MsiRecordSetInteger(hRecord, (uint)fieldnum, (int)value); } else if (value.GetType() == typeof(Int16)) { retVal = CwMsiWin32.MsiRecordSetInteger(hRecord, (uint)fieldnum, (Int16)value); } MsiThrowOnFailure(hDatabase, retVal, "MsiRecordSetStringW(" + fieldnum.ToString() + ", '" + value.ToString() + "')"); fieldnum++; } //perform the operation on the MSI database retVal = CwMsiWin32.MsiViewModify(hView, CwMsiWin32.MSIMODIFY_INSERT, hRecord); MsiThrowOnFailure(hDatabase, retVal, "MsiViewModify - failed to alter/create record"); //cleanup retVal = CwMsiWin32.MsiCloseHandle(hRecord); MsiThrowOnFailure(hDatabase, retVal, "MsiCloseHandle(hRecord)"); retVal = CwMsiWin32.MsiCloseHandle(hView); MsiThrowOnFailure(hDatabase, retVal, "MsiCloseHandle(hView)"); retVal = CwMsiWin32.MsiDatabaseCommit(hDatabase); MsiThrowOnFailure(hDatabase, retVal, "MsiDatabaseCommit(hDatabase)"); }