Hey Mike,
I just tested this out, and it does in fact work. Up until now I had just assumed it works and I hadn't actually put more than one module in an installation package.
You'll need to organize all modules into one package with two package nodes. This means you'll need to gather all of your relevant files into one single directory. This could impact file naming conventions depending on how you organize things. I suggest using the "Resources.zip" approach to help minimize file name conflicts between bundled modules.
I just installed a package that had two package elements. Each were of type module. Only the first package went through the installation "wizard" - the second package was just installed straight up. So if you have any release notes or license information or company information - make sure you include that with the first package.
In my example, the first module is Engage: Tell A Friend. The second module is Engage: To Do (a module we use in our training classes). The Tell A Friend module uses the "Resources.zip" approach, whereas the To Do module explicitly lists all of its files in the manifest. You can see that here:
<dotnetnuke type="Package" version="5.0">
<packages>
<package name="Engage: Tell A Friend" type="Module" version="01.01.00">
<friendlyName>Engage: Tell A Friend</friendlyName>
<description>A simple and flexible module for sharing DNN websites from Engage Software (http://www.engagesoftware.com/).</description>
<owner>
<name>Engage Software</name>
<organization>Engage Software</organization>
<url><![CDATA[<a href="http://www.engagesoftware.com/">http://www.engagesoftware.com/</a>]]></url>
<email><![CDATA[<a href="mailto:support@engagemodules.com">support@engagemodules.com</a>]]></email>
</owner>
<license src="TAFEULA-Free.htm"/>
<releaseNotes src="TAFReleaseNotes_1.1.0.htm" />
<components>
<component type="ResourceFile">
<resourceFiles>
<basePath>DesktopModules/EngageTellAFriend</basePath>
<resourceFile>
<name>TAFResources.zip</name>
</resourceFile>
</resourceFiles>
</component>
<component type="Module">
<desktopModule>
<moduleName>Engage.TellAFriend</moduleName>
<foldername>EngageTellAFriend</foldername>
<businessControllerClass>Engage.Dnn.TellAFriend.FeaturesController</businessControllerClass>
<moduleDefinitions>
<moduleDefinition>
<friendlyName>EngageTellAFriend</friendlyName>
<defaultCacheTime>0</defaultCacheTime>
<moduleControls>
<moduleControl>
<controlKey/>
<controlSrc>DesktopModules/EngageTellAFriend/ViewTellAFriend.ascx</controlSrc>
<controlType>View</controlType>
</moduleControl>
<moduleControl>
<controlKey>Settings</controlKey>
<controlSrc>DesktopModules/EngageTellAFriend/Settings.ascx</controlSrc>
<controlType>Edit</controlType>
</moduleControl>
</moduleControls>
</moduleDefinition>
</moduleDefinitions>
</desktopModule>
</component>
<component type="Assembly">
<assemblies>
<assembly>
<name>EngageTellAFriend.dll</name>
<version>01.01.00</version>
</assembly>
</assemblies>
</component>
<component type="Script">
<scripts>
<basePath>DesktopModules/EngageTellAFriend</basePath>
<script type="UnInstall">
<name>TAFUnInstall.SqlDataProvider</name>
<version>01.01.00</version>
</script>
</scripts>
</component>
</components>
</package>
<package name="EngageTellAFriend" type="SkinObject" version="1.0.0">
<friendlyName>Engage: Tell A Friend Skin Object</friendlyName>
<description>A simple and flexible skin object for sharing DNN websites from Engage Software (http://www.engagesoftware.com/).</description>
<owner>
<name>Engage Software</name>
<organization>Engage Software</organization>
<url><![CDATA[<a href="http://www.engagesoftware.com/">http://www.engagesoftware.com/</a>]]></url>
<email><![CDATA[<a href="mailto:support@engagemodules.com">support@engagemodules.com</a>]]></email>
</owner>
<components>
<component type="SkinObject">
<moduleControl>
<controlKey>EngageTellAFriend</controlKey>
<controlSrc>DesktopModules/EngageTellAFriend/ViewTellAFriend.ascx</controlSrc>
</moduleControl>
</component>
</components>
</package>
<package name="Engage: To Do" type="Module" version="1.0.0">
<friendlyName>Engage: To Do</friendlyName>
<description>A DotNetNuke Module from Engage Software</description>
<owner>
<name />
<organization />
<url />
<email />
</owner>
<license>The license for this package is not currently included within the installation file, please check with the vendor for full license details.</license>
<releaseNotes />
<components>
<component type="Module">
<desktopModule>
<moduleName>Engage: To Do</moduleName>
<foldername>EngageToDo</foldername>
<businessControllerClass>Engage.Dnn.ToDo.FeatureController</businessControllerClass>
<supportedFeatures />
<moduleDefinitions>
<moduleDefinition>
<friendlyName>ToDo</friendlyName>
<defaultCacheTime>0</defaultCacheTime>
<moduleControls>
<moduleControl>
<controlKey />
<controlSrc>DesktopModules/EngageToDo/ViewTasks.ascx</controlSrc>
<supportsPartialRendering>False</supportsPartialRendering>
<controlTitle />
<controlType>View</controlType>
<iconFile />
<helpUrl />
<viewOrder>0</viewOrder>
</moduleControl>
<moduleControl>
<controlKey>Edit</controlKey>
<controlSrc>DesktopModules/EngageToDo/AddTask.ascx</controlSrc>
<supportsPartialRendering>False</supportsPartialRendering>
<controlTitle>Add Task</controlTitle>
<controlType>Edit</controlType>
<iconFile />
<helpUrl />
<viewOrder>0</viewOrder>
</moduleControl>
<moduleControl>
<controlKey>Settings</controlKey>
<controlSrc>DesktopModules/EngageToDo/ToDoSettings.ascx</controlSrc>
<supportsPartialRendering>False</supportsPartialRendering>
<controlTitle>ToDo Settings</controlTitle>
<controlType>Edit</controlType>
<iconFile />
<helpUrl />
<viewOrder>0</viewOrder>
</moduleControl>
</moduleControls>
</moduleDefinition>
</moduleDefinitions>
</desktopModule>
</component>
<component type="Assembly">
<assemblies>
<basePath>bin</basePath>
<assembly>
<name>EngageToDo.dll</name>
</assembly>
</assemblies>
</component>
<component type="File">
<files>
<basePath>DesktopModules\EngageToDo</basePath>
<file>
<path>App_LocalResources</path>
<name>AddTask.ascx.resx</name>
</file>
<file>
<path>App_LocalResources</path>
<name>Settings.ascx.resx</name>
</file>
<file>
<path>App_LocalResources</path>
<name>ViewTasks.ascx.resx</name>
</file>
<file>
<name>AddTask.ascx</name>
</file>
<file>
<name>module.css</name>
</file>
<file>
<name>Settings.ascx</name>
</file>
<file>
<name>ViewTasks.ascx</name>
</file>
</files>
</component>
</components>
</package>
</packages>
</dotnetnuke>
The file structure in my zip was as follows:
- App_LocalResources (Used by the ToDo Module)
- AddTask.ascx.resx
- Settings.ascx.resx
- ViewTasks.ascx.resx
- bin (Used by both modules)
- EngageTellAFriend.dll
- EngageToDo.dll
- AddTask.ascx (Used by the ToDo module)
- EngageToDoAFriend.dnn (The combination manifest file. The initial naming was innocent. Leaving it as such may not have been ;)
- module.css (Used by the ToDo module)
- Settings.ascx (Used by the ToDo module)
- TAFEULA-Free.htm (Used by the TAF module)
- TAFReleaseNotes_1.1.0.htm (Used by the TAF module)
- TAFResources.zip (Used by the TAF module, holds all ascx, resx, images, css, etc.. and is just straight up unpacked in the desktopmodules\EngageTellAFriend directory)
- TAFUnInstall.SqlDataProvider (Used by the TAF module)
- ViewTasks.ascx (Used by the ToDo module)
There are certainly better ways to organize the files - this is kind of a messy hodgepodge - but it does work!
Also, based on the issues you were running in to - i'd suggest you make sure you use different friendly names for your modules. As you saw - that doesn't work out so well. :)
Hope that helps,
Ian