Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Instance Transforms and MsiOpenProduct

74 views
Skip to first unread message

kis...@gmail.com

unread,
Apr 25, 2008, 2:48:45 PM4/25/08
to
I installed a product using the instance transform. For example
msiexec /I mypackage.msi TRANSFORMS=instance.mst MSINEWINSTANCE=1. The
instance transforms contains a custom property (lets say [CUSTOM] =
XXX)


Now, using MsiOpenProduct I want to obtain the value of [CUSTOM], but
I am unable to get the value. For example:

UINT uRet = ::MsiOpenProduct(InstanceTransformProductCode, &hMsi);

CString sCustom;
bufLen = 2048;
uRet = MsiGetProperty(hMsi, _T("CUSTOM"),
sCustom.GetBuffer(bufLen), &bufLen);
sCustom.ReleaseBuffer();

sCustom is empty. I then looked into the msi log created immediately
after MsiOpenProduct is called, I see:

MSI (c) (4C:B0) [17:58:51:097]: PROPERTY CHANGE: Adding PackageCode
property. Its value is '{EF9201EA-EA4D-4127-ADA0-70E3C24F5402}'.
MSI (c) (4C:B0) [17:58:51:097]: Product Code passed to
Engine.Initialize: '(none)'
MSI (c) (4C:B0) [17:58:51:097]: Product Code from property table
before transforms: '{B655E81D-AB84-48FF-8654-202971D90876}'
MSI (c) (4C:B0) [17:58:51:097]: Product Code from property table after
transforms: '{B655E81D-AB84-48FF-8654-202971D90876}'
MSI (c) (4C:B0) [17:58:51:097]: Product not registered: beginning
first-time install
MSI (c) (4C:B0) [17:58:51:097]: PROPERTY CHANGE: Adding ProductState
property. Its value is '-1'.
MSI (c) (4C:B0) [17:58:51:097]: Entering
CMsiConfigurationManager::SetLastUsedSource.

Why isn't api resolving the instance transforms? The log indicates it
is initiating a first time install because the product wasn't
registered? I tried unstalling the product - that worked without
problems. It is the API I am having problems with.

Can someone please shed light on what is happening and if there is a
way to get the Custom property?

kis...@gmail.com

unread,
Apr 25, 2008, 5:00:19 PM4/25/08
to
Sorry, I read the documentation again. It says MsiOpenProduct "opens a
product for use with the functions that access the product database".
I missed the part that this is a handle to the database, so I will
need to apply the transforms myself. I tried the code below. It works
now:

PMSIHANDLE hMsi, hMsiActiveDb;
CString strProductCode(_T("{B655E81D-
AB84-48FF-8654-202971D90876}"));

CString strTransforms, sProp;
bufLen = 2048;
MsiGetProductInfo(strProductCode, INSTALLPROPERTY_TRANSFORMS,
strTransforms.GetBuffer(2048), &bufLen);
strTransforms.ReleaseBuffer();

UINT uRet = ::MsiOpenProduct(strProductCode, &hMsi);
hMsiActiveDb = ::MsiGetActiveDatabase(hMsi);

int nErrorConditions = MSITRANSFORM_ERROR_ADDEXISTINGROW
| MSITRANSFORM_ERROR_DELMISSINGROW
| MSITRANSFORM_ERROR_ADDEXISTINGTABLE
| MSITRANSFORM_ERROR_DELMISSINGTABLE
| MSITRANSFORM_ERROR_UPDATEMISSINGROW
| MSITRANSFORM_ERROR_CHANGECODEPAGE;

bufLen = 2048;
uRet = MsiDatabaseApplyTransform(hMsiActiveDb, strTransforms,
nErrorConditions);
uRet = MsiGetProductProperty(hMsi, MSIPROPERTY_MYCUSTOMPROP,
sProp.GetBuffer(2048), &bufLen);
sProp.ReleaseBuffer();

kis...@gmail.com

unread,
Apr 28, 2008, 8:46:25 PM4/28/08
to
I am still unable to understand why I need to manually apply the
transforms on the database myself. I would think MsiOpenProduct would
pre-apply all the transforms (which is what it does but for the
instance transform I am using). Is there something else I should do to
get an instance-transformed product pre-apply all transforms and patch-
transforms when I call MsiOpenProduct?

On Apr 25, 2:00 pm, "kis...@gmail.com" <kis...@gmail.com> wrote:
> Sorry, I read the documentation again. It saysMsiOpenProduct"opens a

> > msiexec /I mypackage.msi TRANSFORMS=instance.mstMSINEWINSTANCE=1. The


> > instance transforms contains a custom property (lets say [CUSTOM] =
> > XXX)
>

> > Now, usingMsiOpenProductI want to obtain the value of [CUSTOM], but


> > I am unable to get the value. For example:
>
> >     UINT uRet = ::MsiOpenProduct(InstanceTransformProductCode, &hMsi);
>
> >     CString sCustom;
> >     bufLen = 2048;
> >     uRet = MsiGetProperty(hMsi, _T("CUSTOM"),
> > sCustom.GetBuffer(bufLen), &bufLen);
> >     sCustom.ReleaseBuffer();
>
> > sCustom is empty. I then looked into the msi log created immediately

> > afterMsiOpenProductis called, I see:


>
> > MSI (c) (4C:B0) [17:58:51:097]: PROPERTY CHANGE: Adding PackageCode
> > property. Its value is '{EF9201EA-EA4D-4127-ADA0-70E3C24F5402}'.
> > MSI (c) (4C:B0) [17:58:51:097]: Product Code passed to
> > Engine.Initialize:           '(none)'
> > MSI (c) (4C:B0) [17:58:51:097]: Product Code from property table
> > before transforms: '{B655E81D-AB84-48FF-8654-202971D90876}'
> > MSI (c) (4C:B0) [17:58:51:097]: Product Code from property table after
> > transforms:  '{B655E81D-AB84-48FF-8654-202971D90876}'
> > MSI (c) (4C:B0) [17:58:51:097]: Product not registered: beginning
> > first-time install
> > MSI (c) (4C:B0) [17:58:51:097]: PROPERTY CHANGE: Adding ProductState
> > property. Its value is '-1'.
> > MSI (c) (4C:B0) [17:58:51:097]: Entering
> > CMsiConfigurationManager::SetLastUsedSource.
>
> > Why isn't api resolving the instance transforms? The log indicates it
> > is initiating a first time install because the product wasn't
> > registered? I tried unstalling the product - that worked without
> > problems. It is the API I am having problems with.
>
> > Can someone please shed light on what is happening and if there is a

> > way to get the Custom property?- Hide quoted text -
>
> - Show quoted text -

kis...@gmail.com

unread,
Apr 30, 2008, 4:03:12 PM4/30/08
to
I ended up copying the cached msi to temp folder, changing its product
code to that of the instance transform, and then calling
MsiOpenDatabase and MsiOpenPackage. That works.

> > - Show quoted text -- Hide quoted text -

David Brooks

unread,
Jul 1, 2010, 10:45:16 AM7/1/10
to
Hi kishmu...

I been searching around for a solution to a very similar problem and this
thread is the closest I have come to finding one. I know this is an old
issue to you, but do you think you could help point me in the right
direction?

I am not sure I completely understand your final comment: "I ended up

copying the cached msi to temp folder, changing its product
code to that of the instance transform, and then calling
MsiOpenDatabase and MsiOpenPackage. That works."

MsiOpenPackage will open the cached database with the transform already
applied, right? I have that working, and I see why you do an
MsiOpenDatabase on the copy (so you have to handles to diff to generate a
new transform), but where do you change the value? When I try to apply a
change to the database opened in MsiOpenPackage I get a failure on the view.
The database opened with MsiOpenDatabase, of course, doesn't show me any of
the changes in the transform (even after calling MsiDatabaseApplyTransform.

So I am stuck. I would greatly appreciated it if you could help me out (and
if you are even monitoring this tread any more).

Thanks,

Dave

url:http://www.ureader.com/msg/16531736.aspx

Adrian Accinelli

unread,
Jul 12, 2010, 1:56:41 PM7/12/10
to
"David Brooks" <d...@iy.com> wrote in message
news:1699faad14814a65...@newspe.com...

To work with the Database's data you need to have a MSIHANDLE to the
Database itself. MsiOpenPackage/Ex and MsiOpenProduct give you an
Installation MSIHANDLE rather than a Database MSIHANDLE. That's why you
have the call MsiGetActiveDatabase from say a custom action because you are
given an Install handle in the MSIHANDLE provided to you. In addition the
active install database is read-only except for temporary rows/tables so
that's probably why you views are failing since you are likely trying to
modify them -- check the error are you getting to be sure.

To make a transform with all latest patches in place in the original
database I would:
1. Locate Cached MSI (or original msi) and copy it to temp -- call it
MSI_orig
2. Update MSI_a with instance ProductCode and close it. Then open with
MsiOpenPackage as hProduct.
3. Get the active Database from this Product Handle -- call it MSI_a. At
this point you should have read-only copy of patched/transformed MSI for the
product you want.
4. Create new empty database using MSIDBOPEN_CREATEDIRECT is fine -- call it
MSI_b
5. Enumerate contents of `_Tables` table from MSI_a, then
Export each table found to IDT file and import into MSI_b (using
MsiDatabaseExport/MsiDatabaseImport)
Export/Import _SummaryInformation table
6. Commit and close Handles

The up-to-date MSI_b file should now be available for copying/modification
and suitable for creating a transform.

Sincerely,
Adrian Accinelli


0 new messages