Hello @bentraje,
I might have been unclear here. You can have the dialog at a different point of time, but you are bound to what PluginMessage
is able to convey. You can also do it like you and licensing_example_r21.py are doing it, and simply rely on the __main__
execution context, because when the file is being called with it, you are in the C4DPL_INIT
stage. But you can also launch your dialog when for example
C4DPL_STARTACTIVITY
is being emitted after all plugins have been loaded but before Cinema 4D is done loading. 
- or when
C4DPL_PROGRAM_STARTED
is being emitted, and the app is "ready to go"

You can also go earlier or later; I would recommend having a look at the plugin message IDs. And just in case you are planning to do some hot swapping, i.e., update an outdated plugin before Cinema 4D wants to load it, this can be quite complicated, and it is not supported by us.
Find a simple example below.
Cheers,
Ferdinand
import c4d
import typing
LICENSE_IS_VALID: bool = True
def PluginMessage(mid: int, data: typing.Any) -> bool:
"""Called by Cinema 4D to convey larger portions of the app state starting or ending.
"""
if mid == c4d.C4DPL_PROGRAM_STARTED and not LICENSE_IS_VALID:
c4d.gui.MessageDialog("BT Rendering Utilities. This beta version expired. "
"Please download another one from our website.")
return True
return False
def RegisterPlugin() -> bool:
"""Checks the license of the plugin and registers it.
Could also be done inside the __main__ context guard, but I like putting it in a function :)
"""
CheckLicense = lambda : False
# CHeck for a valid license and bail on registering when it is not given.
if not CheckLicense():
global LICENSE_IS_VALID
LICENSE_IS_VALID = False
return False
# Do the registering ...
# return c4d.plugins.Register...
return True
if __name__ == "__main__":
if not RegisterPlugin():
print ("Warning: Could not register ...")