cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Marsyas
Level 3

Need Help: How to set Component's Destination Folder programmatically?

Hi!

I'm trying to install a local printer during a Basic MSI Setup. I have written some C++ Code doing this for me and this code will be called during setup through a Custom Action.

Before I can call this code I need to copy the printer drivers to the System's printer driver directory (usually 'c:\Windows\System32\spool\drivers\w32x86'). The actual printer driver directory can be detected with the GetPrinterDriverDirectory() call.

Now is the question, how can I set the destination directory of the components containing my printer driver files to the directory pointed by GetPrinterDriverDirectory()?

I tried to write a Msi-DLL, which sets me a property with MsiSetProperty() and afterwards a second CA changes the Custom Path of the components to the dir pointed by the property.

Sample:
[CODE]
UINT __stdcall SetPrnDriverDirProp2(MSIHANDLE hMsi)
{
TCHAR szPrinterDriverDir[MAX_PATH];
DWORD cbPrinterDriverDir = sizeof(szPrinterDriverDir);

ZeroMemory(&szPrinterDriverDir, cbPrinterDriverDir);
if (!GetPrinterDriverDirectory(NULL, NULL, 1, (LPBYTE)szPrinterDriverDir, MAX_PATH, &cbPrinterDriverDir))
{
/* some error handling */
}

TCHAR szTmp[MAX_PATH] = {0};
DWORD nLen = MAX_PATH;

ZeroMemory(szTmp, MAX_PATH);
UINT nRet1 = MsiGetProperty(hMsi, _T("SYSPRINTERDIRPROP"), szTmp, &nLen);
UINT nRet2 = MsiSetProperty(hMsi, _T("SYSPRINTERDIRPROP"), szPrinterDriverDir);

return ERROR_SUCCESS;
}
[/CODE]

For some reason I'm not able to find out I always get a ERROR_INVALID_HANDLE as return code in nRet2. This makes no sense to me, because MsiGetProperty works fine, so the handle cannot be invalid :confused:.

Any suggestions?

Is there a more convenient way to set the target dir of the printer driver files?

Thank for your help

Marsyas
Labels (1)
0 Kudos
(1) Reply
Christopher_Pai
Level 16

If your CA is that simple, you might get away without having a Type 1 CA at all. Take a look at `Standard DLL` Custom actions where you declare the GetPrinterDriverDirectory API to InstallShield and map the pDriverDirectory argument to the property of your choice.

Also keep in mind Type 51 and Type 35 CA's for setting directory properties and understand the importance of sequencing. Personally I reccomend 51 ( SetProperty as you are doing ) scheduled prior to CostFinalize.

As for `more convienent`, it's possible that this API just reads from a registry value and an AppSearch/Reglocator could do the job... but that's a bad practice since the API is public and the registry data location is private.
0 Kudos