Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cx_freeze bdist_msi: create registry entries?

I used bdist_msi from cx_freeze in the past and it works nice.

Now I need to create registry entries

Is it possible to create registry entries with bdist_msi from cx_freeze?

With the wixtools these settings were done in the past:

<!-- File extension .foostarter -->
<RegistryValue Root='HKCR' Type='string' Key='.foostarter' Value='foostarter.File' />
<RegistryValue Root='HKCR' Type='string' Key='.foostarter' Name='Content Type' 
                           Value='application/vnd.foobar-modstarter' />
<RegistryValue Root='HKCR' Key='foostarter.File\Shell\Open' Type='string' Value='Ausfuehren' />
<RegistryValue Root='HKCR' Key='foostarter.File\Shell\Open\Command' Type='string'
               Value='"[#foostarter.exe]" file "%%1"' />

<!-- protocol foostarter://... -->
<RegistryValue Root='HKCR' Key='foostarter' Type='string' Value='URL: foostarter Protocol' />
<RegistryValue Root='HKCR' Key='foostarter' Type='string' Name='URL Protocol' Value=''/>
<RegistryValue Root='HKCR' Key='foostarter\shell\open\command' Type='string' 
               Value='"[#foostarter.exe]" url "%%1"' />

<!-- start without asking -->
<RegistryValue Root='HKLM' Key='Software\Microsoft\Internet Explorer\ProtocolExecute\foostarter' 
               Name='WarnOnOpen' Value='0' Type='integer' />
like image 281
guettli Avatar asked Aug 02 '18 14:08

guettli


3 Answers

To which purpose do you need to create registry entries?

The cx_Freeze documentation is not complete: the bdist_msi command has more options than the currently listed ones add_to_path and upgrade_code. It has an option (kwarg) data (see the source code of cx_Freeze) which can be used to add entries to the Windows Installer database tables. See here how to let the installer create desktop or program menu shortcuts by adding entries to the Shortcut Table (key Shortcut of data) and to the Directory Table (key Directory). Similarly, you can use the key Registry to add information to the Registry Table and the key RemoveRegistry to add information to the RemoveRegistry Table, telling the installer to write information to the registry upon installing and to remove it upon uninstalling.

You can use Orca to see which entries the wixtools generate in the Registry Table and Component Table (and maybe further tables) with your settings and define exactly the same tables in your setup script and pass them to bdist_msi using data.

You can also add Properties through the Property Table (key Property), an User Interface through the InstallUISequence Table, Dialog Table, Control Table, and ControlEvent Table, and much more... See here for a list of the available keys with links to the documentation of the corresponding database tables.

For more complex purposes, you probably need to use additional tools to generate an installer after running the cx_Freeze setup script. See for example the script-based tool NSIS (Nullsoft Scriptable Install System) .

like image 134
jpeg Avatar answered Oct 16 '22 09:10

jpeg


I am answering my own question. I think this solution should work:

First use bdist_msi to create the msi-file.

Then alter the created msi file. You could use the python library msilib. Add an entry to the table Registry, documented here: https://learn.microsoft.com/en-us/windows/desktop/msi/registry-table

I could not use the undocumented "data" argument of cx_freeze since in setup.py, since it uses msilib.add_data() . And this methods needs the external key to a component.

I don't know this component-id during setup.py.

That's why I think you need to do this in two steps.

Above is only theory. In practice I used bdist_exe and then wix to create the msi.

Since above is only vague guessing, feedback is very welcome.

like image 20
guettli Avatar answered Oct 16 '22 09:10

guettli


MSI - MS SQL

I am not familiar with bdist_msi. However, it is definitely possible to post-process an MSI file to add registry entries if you have the right tools to do so. I am not sure if you want this scripted and automated, or if any manual steps with an appropriate tool is OK?

As you have understood from using the python library msilib, an MSI file is really a primitive MS SQL database under the hood, and you can update it using automation and a primitive SQL dialect. See "Hotfixing MSI using WiRunSQL.vbs" below. The msilib is probably just a wrapper accessing the MSI COM API - or the down-to-the-metal Win32 C++ functions - you see how little I know about Python :-). Some context on COM vs Win32 (not important for you I think).

If you insert entries in the MSI database tables, you don't really need to know the component name generated by bdist_msi, you can insert new records in both the Component table and in the Registry table with whatever records you need (in addition to those created by bdist_msi). Then you need to also write to the FeatureComponents table to add the component to a feature. Not quite trivial, but not that bad either I guess. I don't have any sample Python code using msilib, but it sounds like you already have that? Maybe a sample using regular MSI API? Here goes:

Hotfixing MSI using WiRunSQL.vbs: There is a VBScript in the MSI SDK called WiRunSQL.vbs that can be used to insert data directly into an MSI file in a scripted fashion in a very simple fashion (just simplified SQL). I describe this briefly in this answer (bottom). If you have Visual Studio installed, just search for the VBScript file under Program Files (x86).

Easy Fix?: Could the above SQL hotfixing VBScript be all you need? It is very simple to use and to automate, and it is a Microsoft VBScript. Few other entanglements and layers of indirection.

Quick MSI Update Mockup

Sample changes to MSI (open links to MSDN to see what each column means):

Component Table: (rolling with standard Pope-Mo-GUID :-) )

MyComp, {77777777-7777-7777-7777-777777777777}, TARGETDIR, 4, MyValue

Registry Table:

MyValue, -1, Software\[Manufacturer]\[ProductName]\New_Key, Value, 1, MyComp

FeatureComponents Table:

MyFeature, MyComp


Manual Tweaks Using Tools:

I hope the above made some sort of sense. Let me spin through a few "manual" or non-scripted / non-automated alternatives:

Free Tools: There are several tools you can try. That link describes the free Orca (offical Microsoft SDK MSI viewer and editor - if you got Visual Studio installed try searching for Orca-x86_en-us.msi - under Program Files (x86) - then just install it), SuperOrca and InstEd. Those are free tools.

Commercial Tools With Free Features: There is also Advanced Installer - a commercial tool that allows some basic functionality for free. I think that includes adding a registry key entry. I just tested that it works in the full version. This tool has much better GUI than Orca or the other free tools - and updates all associated tables automagically. I am not aware of any free features in Installshield or PACE Suite - the other major commercial tools, but should you already have them available, then they can do the job easily. And a quick mention: List of major, established deployment tools.

WiX: Seeing as you appear somewhat familiar with WiX, one option would be to (re)-build the whole installer with WiX. Maybe you already do? You can decompile an existing MSI to WiX format using dark.exe. This dark.exe process is described here (section 4). You can then update the WiX XML and recompile - though this may require some black art and massage to work.


Some Links:

  • https://github.com/python/cpython/blob/master/Lib/distutils/command/bdist_msi.py (skimmed, I can't see any registry support from the quick look either, but I know very little about this)
  • http://www.pyinstaller.org/
  • Does an universal cross-platform installer exists?
  • How to create windows installer
  • https://docs.python.org/3/library/msilib.html?highlight=bdist_msi (for others)
like image 1
Stein Åsmul Avatar answered Oct 16 '22 07:10

Stein Åsmul