diff --git a/administrator/modules/mod_post_installation_messages/mod_post_installation_messages.php b/administrator/modules/mod_post_installation_messages/mod_post_installation_messages.php
deleted file mode 100644
index 802c1bba90cc4..0000000000000
--- a/administrator/modules/mod_post_installation_messages/mod_post_installation_messages.php
+++ /dev/null
@@ -1,34 +0,0 @@
-
- * @license GNU General Public License version 2 or later; see LICENSE.txt
- */
-
-\defined('_JEXEC') or die;
-
-use Joomla\CMS\Extension\ExtensionHelper;
-use Joomla\CMS\Helper\ModuleHelper;
-
-// Try to get the items from the post-installation model
-try {
- /** @var \Joomla\Component\Postinstall\Administrator\Model\MessagesModel $messagesModel */
- $messagesModel = $app->bootComponent('com_postinstall')->getMVCFactory()
- ->createModel('Messages', 'Administrator', ['ignore_request' => true]);
- $messagesCount = $messagesModel->getItemsCount();
-} catch (RuntimeException $e) {
- $messagesCount = 0;
-
- // Still render the error message from the Exception object
- $app->enqueueMessage($e->getMessage(), 'error');
-}
-
-$joomlaFilesExtensionId = ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id;
-
-// Load the com_postinstall language file
-$app->getLanguage()->load('com_postinstall', JPATH_ADMINISTRATOR);
-
-require ModuleHelper::getLayoutPath('mod_post_installation_messages', $params->get('layout', 'default'));
diff --git a/administrator/modules/mod_post_installation_messages/mod_post_installation_messages.xml b/administrator/modules/mod_post_installation_messages/mod_post_installation_messages.xml
index 0d792264e2f33..488a7e61dd72e 100644
--- a/administrator/modules/mod_post_installation_messages/mod_post_installation_messages.xml
+++ b/administrator/modules/mod_post_installation_messages/mod_post_installation_messages.xml
@@ -9,8 +9,10 @@
www.joomla.org
4.0.0
MOD_POST_INSTALLATION_MESSAGES_XML_DESCRIPTION
+ Joomla\Module\PostInstallationMessages
- mod_post_installation_messages.php
+ services
+ src
tmpl
diff --git a/administrator/modules/mod_post_installation_messages/services/provider.php b/administrator/modules/mod_post_installation_messages/services/provider.php
new file mode 100644
index 0000000000000..cb394b030ca79
--- /dev/null
+++ b/administrator/modules/mod_post_installation_messages/services/provider.php
@@ -0,0 +1,39 @@
+
+ * @license GNU General Public License version 2 or later; see LICENSE.txt
+ */
+
+\defined('_JEXEC') or die;
+
+use Joomla\CMS\Extension\Service\Provider\Module;
+use Joomla\CMS\Extension\Service\Provider\ModuleDispatcherFactory;
+use Joomla\DI\Container;
+use Joomla\DI\ServiceProviderInterface;
+
+/**
+ * The post installation messages module service provider.
+ *
+ * @since __DEPLOY_VERSION__
+ */
+return new class () implements ServiceProviderInterface {
+ /**
+ * Registers the service provider with a DI container.
+ *
+ * @param Container $container The DI container.
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function register(Container $container)
+ {
+ $container->registerServiceProvider(new ModuleDispatcherFactory('\\Joomla\\Module\\PostInstallationMessages'));
+
+ $container->registerServiceProvider(new Module());
+ }
+};
diff --git a/administrator/modules/mod_post_installation_messages/src/Dispatcher/Dispatcher.php b/administrator/modules/mod_post_installation_messages/src/Dispatcher/Dispatcher.php
new file mode 100644
index 0000000000000..2b7d60b2d2703
--- /dev/null
+++ b/administrator/modules/mod_post_installation_messages/src/Dispatcher/Dispatcher.php
@@ -0,0 +1,72 @@
+
+ * @license GNU General Public License version 2 or later; see LICENSE.txt
+ */
+
+namespace Joomla\Module\PostInstallationMessages\Administrator\Dispatcher;
+
+use Joomla\CMS\Dispatcher\AbstractModuleDispatcher;
+use Joomla\CMS\Extension\ExtensionHelper;
+
+// phpcs:disable PSR1.Files.SideEffects
+\defined('_JEXEC') or die;
+// phpcs:enable PSR1.Files.SideEffects
+
+/**
+ * Dispatcher class for mod_post_installation_messages
+ *
+ * @since __DEPLOY_VERSION__
+ */
+class Dispatcher extends AbstractModuleDispatcher
+{
+ /**
+ * Runs the dispatcher.
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function dispatch()
+ {
+ // Load the com_postinstall language file
+ $this->getApplication()->getLanguage()->load('com_postinstall', JPATH_ADMINISTRATOR);
+
+ parent::dispatch();
+ }
+
+ /**
+ * Returns the layout data.
+ *
+ * @return array
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function getLayoutData()
+ {
+ $data = parent::getLayoutData();
+
+ $app = $this->getApplication();
+
+ // Try to get the items from the post-installation model
+ try {
+ /** @var \Joomla\Component\Postinstall\Administrator\Model\MessagesModel $messagesModel */
+ $messagesModel = $app->bootComponent('com_postinstall')->getMVCFactory()
+ ->createModel('Messages', 'Administrator', ['ignore_request' => true]);
+ $data['messagesCount'] = $messagesModel->getItemsCount();
+ } catch (\RuntimeException $e) {
+ $data['messagesCount'] = 0;
+
+ // Still render the error message from the Exception object
+ $app->enqueueMessage($e->getMessage(), 'error');
+ }
+
+ $data['joomlaFilesExtensionId'] = ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id;
+
+ return $data;
+ }
+}