Python + CX_Freeze + COM Interface = Pain
Continued fun with win32com and cx_freeze, sigh. But I'm getting forward, step by step. Situation is as usual, you don't know what you're doing and you've got multiple overlapping problems. I'm getting pretty close, but alas, not working yet. I hoped that the execution of localserver.main() would help after from win32com.server.localserver import localserver and checking if commandline got arguments /Automate -Embedding but nope, still not working. As usual, no error messages, no exceptions, no logs, nothing to grab on to get forward. Well, things shouldn't be too easy. Sigh. Of course I've got my own logging, but it won't help enough. I can see that everything is working but after calling main everything hangs until the timeout happens. As stated, the code runs perfectly without cx_freeze. Without cx_freeze this article was totally awesome way to get started. Everything you'll need to know in very compact form. I loved it.
Another interesting fail is that if the --register is called from cx_frozen code and the rights elevation prompt is triggered the registration fails. Because when the process is launched as admin, the command line parameters aren't passed with it. Duh! Of course this can be easily fixed, by making the register as default, without any parameters. But it's still kind of annoying finding. I'm sure someone will get stuck with that and curse for quite a while. Before realizing that the parameters / options / switches / arguments are lost. Another way to deal with this is to run the application with adequate rights, so that the rights elevation prompt isn't needed.
I'm sure someone is going to ask if I'm using win32traceutil, yes. I'm using it, and it works perfectly and trivially without cx_freeze. When cx_freeze is being used, there's no output what so ever. So something goes wrong with the localserver.main() call, it seems that's not the right way after all to start the local server, which would then handle the routing of the method calls to the class in the module. - Well, I've learned many things while doing this, about win32com module and debugging it etc, but unfortunately the results are still bit slim. - This is the classic case where you can ask, how many conflicting guides you can find which tells you how to solve the problem in totally contradicting ways. And of course none of those work.
It seems that I'm getting close to the goal, but still com server startup is failing for some unknown reason. Maybe I should start it differently or something. The localserver.main() is clearly wrong. It also seems that this is not a new problem.
For some unknown reason, calling the localserver.main() doesn't work, but using localserver.serve([clsid]) works. I really don't know why it's so broken. But doesn't matter. Also the win32com.server.policy was missing from includes list. After this, it's all good. Still making some extra tests, outside the development environment to confirm that all dependencies are met, etc. But in general, the key problem has been solved.
Now it's working, phew. So much pain... And no joy, when it's working. It's just like, meh. And as you can see from my posts, yes. It's unfortunately very possible to have multiple serious overlapping fails when creating something new which you don't know too much about. None of the posts I found provided right information how to actually get it working.
After doing some cleanup, I removed most of the attempts to make it to work, so much of the tips how to make it work were incorrect and utterly useless. Sigh, so all that was needed, was calling the serve with clsid(s), if the binary is called with specific parameters.
And after knowing what to exactly look for, this seems to be the almost right answer. Consuming Python COM Server from .NET. But it's headline is misleading, because it talks about Consuming using .NET and not about Creating Python COM Server. Only mistake in the sample code is the lack of list usage with the clsid registration. So simple, if you just know exactly what and how should be done.
Why no bullet points? Well, this kis kind of single topic post.