MSI read support in msilib?

Floris Bruynooghe floris.bruynooghe at gmail.com
Thu Jan 17 13:31:06 CET 2008


On Jan 16, 7:03 pm, "Martin v. Löwis" <mar... at v.loewis.de> wrote:
> > The introduction from the msilib documentation in python 2.5 claims it
> > supports reading an msi.  However on the Record class there is only a
> > GetFieldCount() method and some Set*() methods.  I was expecting to
> > see GetString() and GetInteger() methods to be able to read the
> > values.
>
> > Maybe I'm missing something?
>
> I think you are right - there is indeed stuff missing; few people have
> noticed so far.

Ok, below is the patch I made and tested.  It is still missing a
wrapper for MsiRecordReadStream() but I didn't need that right
now ;-).  It is a patch against Python 2.5.1 (ignore revision numbers
as they're not from svn.python.org).

Let me know if this is any good or comments etc.  Would it be good to
include in python?  Maybe I should create the diff against the trunk
and file a patch report?

Regards
Floris


Index: _msi.c
===================================================================
--- _msi.c	(revision 2547)
+++ _msi.c	(working copy)
@@ -339,6 +339,53 @@
 }

 static PyObject*
+record_getinteger(msiobj* record, PyObject* args)
+{
+    unsigned int field;
+    int status;
+
+    if (!PyArg_ParseTuple(args, "I:GetInteger", &field))
+        return NULL;
+
+    status = MsiRecordGetInteger(record->h, field);
+    if (status == MSI_NULL_INTEGER){
+        PyErr_SetString(MSIError, "could not convert record field to
integer");
+        return NULL;
+    }
+    return PyInt_FromLong((long) status);
+}
+
+static PyObject*
+record_getstring(msiobj* record, PyObject* args)
+{
+    unsigned int field;
+    unsigned int status;
+    char buf[2000];
+    char *res = buf;
+    int malloc_flag = 0;
+    DWORD size = sizeof(buf);
+    PyObject* string;
+
+    if (!PyArg_ParseTuple(args, "I:GetString", &field))
+        return NULL;
+
+    status = MsiRecordGetString(record->h, field, res, &size);
+    if (status == ERROR_MORE_DATA) {
+        res = (char*) malloc(size + 1);
+        if (res == NULL)
+            return PyErr_NoMemory();
+        status = MsiRecordGetString(record->h, field, res, &size);
+    }
+
+    if (status != ERROR_SUCCESS)
+        return msierror((int) status);
+    string = PyString_FromString(res);
+    if (buf != res)
+        free(res);
+    return string;
+}
+
+static PyObject*
 record_cleardata(msiobj* record, PyObject *args)
 {
     int status = MsiRecordClearData(record->h);
@@ -405,6 +452,10 @@
 static PyMethodDef record_methods[] = {
     { "GetFieldCount", (PyCFunction)record_getfieldcount,
METH_NOARGS,
 	PyDoc_STR("GetFieldCount() -> int\nWraps MsiRecordGetFieldCount")},
+    { "GetInteger", (PyCFunction)record_getinteger, METH_VARARGS,
+    PyDoc_STR("GetInteger(field) -> int\nWraps
MsiRecordGetInteger")},
+    { "GetString", (PyCFunction)record_getstring, METH_VARARGS,
+    PyDoc_STR("GetString(field) -> string\nWraps
MsiRecordGetString")},
     { "SetString", (PyCFunction)record_setstring, METH_VARARGS,
 	PyDoc_STR("SetString(field,str) -> None\nWraps
MsiRecordSetString")},
     { "SetStream", (PyCFunction)record_setstream, METH_VARARGS,




More information about the Python-list mailing list