Automatically create the ProfileCatalog XML File

Topics: CAB & Smart Client Software Factory
Mar 30, 2006 at 12:44 PM
originally posted by: jswander

I am currently working on coming up with a Composit UI solution for the company I work for. I created a small extension that automatically creates the ProfileCatalog.xml file based on existing Module DLLs on the users machine. I am posting this in case it helps anyone else.

CODE:
Imports System.IO
Namespace CAB.Profile
Public Module ProfileCreator
Private Const CATALOGNAME As String = "ProfileCatalog.xml"
Public Sub CreateProfileCatalog()
Dim _contentArray As New ArrayList
Dim _moduleFiles() As String = Directory.GetFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules"))
Dim _moduleFile As String
Dim _fileArray As New ArrayList
Dim _fileEntry As New ProfileEntry
Dim _moduleInfo As String
If File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, CATALOGNAME)) Then
File.Delete(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, CATALOGNAME))
End If
If _moduleFiles.Length > 0 Then
For Each _moduleFile In _moduleFiles
If _moduleFile.Contains("CABModule.dll") Then
_fileEntry = New ProfileEntry
fileEntry.AssemblyFile = Split(moduleFile, "\")(Split(_moduleFile, "\").Length - 1)
If File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules/" & Replace(_fileEntry.AssemblyFile, ".dll", "") & ".update")) Then
fileEntry.UpdateURL = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules/" & Replace(fileEntry.AssemblyFile, ".dll", "") & ".update"))(0)
Else
_fileEntry.UpdateURL = ""
End If
fileArray.Add(fileEntry)
End If
Next
End If
If Not _fileArray.Count = 0 Then
_contentArray.Add("<?xml version=""1.0"" encoding=""utf-8"" ?>")
_contentArray.Add("<!-- Created by system -->")
_contentArray.Add("<SolutionProfile xmlns=""http://schemas.microsoft.com/pag/cab-profile"">")
_contentArray.Add("<Modules>")
For Each _fileEntry In _fileArray
_moduleInfo = ""
_moduleInfo = "<ModuleInfo AssemblyFile=""Modules/" & _fileEntry.AssemblyFile & """"
If Not _fileEntry.UpdateURL = "" Then
_moduleInfo &= " UpdateLocation=""" & _fileEntry.UpdateURL & """"
End If
_moduleInfo &= " />"
contentArray.Add(moduleInfo)
Next
_contentArray.Add("</Modules>")
_contentArray.Add("</SolutionProfile>")
File.WriteAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, CATALOGNAME), split(Join(_contentArray.ToArray, "^"), "^"))
End If
End Sub

Private Class ProfileEntry
Private _assemblyFile As String
Private _updateURL As String
Public Sub New()
End Sub
Public Property AssemblyFile() As String
Get
Return _assemblyFile
End Get
Set(ByVal value As String)
_assemblyFile = value
End Set
End Property
Public Property UpdateURL() As String
Get
Return _updateURL
End Get
Set(ByVal value As String)
_updateURL = value
End Set
End Property
End Class
End Module
End Namespace
Mar 30, 2006 at 12:45 PM
originally posted by: jswander

Adding to my Previous post:

In order for this to work, your Module Assembly files must end with "CABModule.dll". EX: "TestCabModule.dll"
If you wish to add an UpdateLocation value to the "ModuleInfo", include a one line file with the url in it and name the file the same as your DLL except with a ".update" extension.
EX: "TestCABModule.update"
To have your system automatically create this file, modify your ShellApplication.vb file as follows:

Public Class ShellApplication : Inherits FormShellApplication(Of ShellWorkItem, ShellForm)
<STAThread()> _
Shared Sub Main()
CreateProfileCatalog()
Dim objShell As New ShellApplication : objShell.Run()
End Sub

If anyone finds this useful, please let me know.
Mar 30, 2006 at 1:09 PM
originally posted by: matiaswoloski

Hi,

Have you checked the builtin ReflectionModuleEnumerator service? This enumerator will go through your AppDomain private path and will load the modules that it will find.

In the AddServices method you should
RootWorkItem.Services.RemoveFileCatalogEnumerator();
RootWorkItem.Services.RemoveReflectionModuleEnumerator();

Replace brackets with less-than and greater-than.

Thanks,
Matias
http://staff.southworks.net/blogs/matiaswoloski
Mar 31, 2006 at 4:31 AM
originally posted by: jswander

I tried using it, but it wanted to register every dll in the application. I have created several extensions to control business logic which I dont want the system to register. I just started teaching myself this system a week ago, so if anyone has any sugestions, please pass them on.

One item I cannot figure out though is where you assign allowed roles to a module.
Nov 3, 2006 at 6:59 AM
originally posted by: cjc9

I am also not able to figure out where allowable roles get assigned to the various modules that your CAB solution should load. I can find a reference to an array of allowable roles, but I can't figure out where that array is loaded from - I would expect it to be an element in the ProfileCatalog, but can't find any valid examples...
Nov 4, 2006 at 8:36 AM
originally posted by: cjc9

If I was more careful when trying to read my XML files, I probably would have saved myself a bunch of time...but anyways, here's what the ProfileCatalog.xml file should look like to enable the "Roles" functionality. This assumes that you've executed an "Authenticate" module, and that you've properly assigned valid roles to the PrincipalIdentity thread.

<SolutionProfile xmlns="http://schemas.microsoft.com/pag/cab-profile/2.0">
<Section Name="Layout">
<Modules>
<ModuleInfo AssemblyFile="Infrastructure.Layout.dll" />
</Modules>
</Section>
<Section Name="Services">
<Dependencies>
<Dependency Name="Layout" />
</Dependencies>
<Modules>
<ModuleInfo AssemblyFile="Infrastructure.Module.dll" />
</Modules>
</Section>
<Section Name="Apps">
<Dependencies>
<Dependency Name="Layout" />
<Dependency Name="Services" />
</Dependencies>
<Modules>
<ModuleInfo AssemblyFile="ModuleA.dll" Name="BMW" >
<Roles>
<Role Allow="Users"/>
</Roles>
</ModuleInfo>

<ModuleInfo AssemblyFile="ModuleB.dll" >
<Roles>
<Role Allow="MyDefinedRoleB"/>
</Roles>
</ModuleInfo>

<ModuleInfo AssemblyFile="ModuleC.dll" >
<Roles>
<Role Allow="MyDefinedRoleC"/>
</Roles>
</ModuleInfo>
</Modules>
</Section>
</SolutionProfile>

Hope this helps.
Thanks,
cjc9