PageBox: presentation deployment using .NET PageBox

for
FAQ Dev site .NET version Customization Install Grid Active Naming Grid API

PageBox for .NET customization

Deliveries

You can download PageBox and its repository for .NET in Zip format:

The repository of PageBox for .NET is made of the following files:

Name

Purpose

Repository/publisher.aspx

Publisher page

Repository/publisher.aspx.cs

Server code of the publisher page

Repository/subscriber.aspx

Subscriber page

Repository/subscriber.aspx.cs

Server code of the subscriber page

Repository/Global.asax.cs

Server code of global.asax

Repository/login-form.aspx

Login form

Repository/login-form.aspx.cs

Server code of login-form.aspx

Repository/Subscriber.cs

Class describing a subscribed PageBox

Repository/RepoSubs.cs

Class describing the subscribed PageBoxes of a Repository

Repository/RepoArchs.cs

Class describing the publications of a Repository

Repository/Deployer.cs

Class responsible of the presentation deployment

Repository/Deploy.cs

Web service proxy

Repository/pagebox.css

CSS used to display repository pages

Repository/logo.gif

PageBox logo

Repository/mail.gif

PageBox mail icon

Repository/Web.config

Example of configuration file

Repository/authorization.xml

Example of authorization file (users allowed to publish archives)

Repository/asubscriber.aspx

Archive subscriber page

Repository/asubscriber.aspx.cs

Code of archive subscriber page

Repository/aselect.aspx

Page of archive selection (for archive subscriber)

Repository/aselect.aspx.cs

Code of archive selection page (for archive subscriber)

Repository/download.aspx

Download page

Repository/download.aspx.cs

Code of download page

Repository/audit.aspx

Log display page

Repository/audit.aspx.cs

Code of log display page

Repository/Log.cs

Log writer

Repository/WebServices/Retry.asmx.cs

Code of Retry.asmx Web service

Repository/WebServices/RepoQuery.asmx.cs

Code of Query.asmx Web service of the Repository

RepositoryMG/MultiGrid.cs

Datagrid for aselect (multiselection)

RepoCleanup/Cleanup.cs

Main class of Cleanup Windows service

RepoCleanup/CleanupThread.cs

Worker thread invoking the Retry Web service

RepoCleanup/Retry.cs

Web service proxy

RepoCleanup/ProjectInstaller.cs

Generated by Visual Studio for the installation of the Windows service

RepoCleanup/cleanup.xml

Example of configuration file for retries

The Repository archive also includes a TestRepoCleanup directory that you can use

  1. To modify the Windows service (even with .NET it is still not easy to test the former NT services)

  2. To set the service cleanup.xml path and logging mode

TestRepoCleanup contains the following files:

Name

Purpose

TestCleanup.cs

Window form application

CleanupThread.cs

Worker thread invoking the Retry Web service

Retry.cs

Web service proxy

cleanup.xml

Example of configuration file for retries

PageBox for .NET is made of the following files:

Name

Purpose

update.aspx

PageBox page

update.aspx.cs

Code of PageBox page

Deploy.asmx.cs

Code of Deploy.asmx Web service

Query.asmx.cs

Code of Query.asmx Web service

RepoQuery.cs

Proxy of the RepoQuery Web service

Global.asax.cs

Server code of Global.asax

unzip.exe

From Infozip. Example of archive installation

inflate.bat

Example of archive installation script (DOS)

inflate.js

Example of JavaScript installation and de-installation script (WSH)

remove.bat

Example of archive de-installation script (DOS)

pagebox.css

CSS used to display repository pages

logo.gif

PageBox logo

mail.gif

PageBox mail icon

PbCmd.xml

Example of configuration for archive installation/de-installation

audit.aspx

Log display page

audit.aspx.cs

Code of log display page

Log.cs

Log writer

ActiveNaming.asmx.cs

ActiveNaming Web service

ActiveProxy.cs

Proxy of the ActiveNaming Web service

The Grid API of PageBox for .NET (pageboxgrid.zip) is made of the following files:

Name

Purpose

ActiveProxy.cs

Proxy of the ActiveNaming Web service

Grid.cs

Grid API class

Log.cs

Class responsible for error logging

MulticastListener.cs

Listener for multicast datagrams

POPListener.cs

Listener for mails

UDPAddressPort.cs

Used to implement Hashtable key on (UDP address, port)

UDPListener.cs

Listener for UDP datagrams

UDPQueue.cs

Classes used by MulticastListener and UDPListener

The ActiveNaming Web service is described in the Active Naming documentation and in the Grid presentation.

The Grid API is described in the Grid API documentation and in the Grid presentation.

Repository

Subscriber.cs

The Subscriber class contains archs, an associative array of the presentations deployed or pending for deployment.

Subscriber has three methods:

  • A constructor without parameter to create a new Subscriber

  • A constructor with an XmlReader to restore a Subscriber from subscribers.xml

  • WriteXml to serialize a Subscriber in subscribers.xml

RepoSubs.cs

The RepoSubs class contains subscribers, an associative array of the subscribing PageBoxes and asubscribers, an associative array of the archive subscribers.

RepoSubs has eleven methods:

  • A constructor with an XmlReader to restore a RepoSubs from subscribers.xml. To restore subscribers and asubscribers, it calls restoreSubs

  • restoreSubs restores a associative table from subscribers.xml

  • WriteXml serializes a RepoSubs in subscribers.xml

  • subscribe adds a subscriber to the repository

  • unsubscribe removes a subscriber from the repository

  • asubscribe adds an archive subscriber to the repository

  • unasubscribe removes a archive subscriber from the repository

  • add adds a presentation to an archive subscriber

  • delete removes a presentation from an archive subscriber

  • cleanup invokes cleanup2 for subscribers and archive subscribers. cleanup is invoked by the Retry Web Service

  • cleanup2 tries to remove pending state. If an archive is in "pending deploy" cleanup2 deploys the archive again. If an archive is in "pending undeploy" cleanup2 undeploys the archive again. If cleanup2 succeeded to undeploy all archives deployed on a subscribing PageBox and if this PageBox is in "pending unsubscribe" state cleanup2 removes the PageBox from the subscriber list.

When a new PageBox is subscribed, it receives all presentations defined in RepoArchs.

RepoSubs manages subscribers.xml. Here is an example:

<?xml version="1.0"?>

<RepoSubs>

<subscribers>

<entry>

<url>127.0.0.1/PageBox/PageBox/Deploy.asmx</url>

<Subscriber>

<arch>

<name>art030_UploadFile.zip</name>

<status>art030_UploadFile.zip installed</status>

</arch>

<arch>

<name>MasterDetailDPLCHK.zip</name>

<status>MasterDetailDPLCHK.zip installed</status>

</arch>

<state>active</state>

</Subscriber>

</entry>

<entry>

<url>127.0.0.1/PageBox/PageBox2/Deploy.asmx</url>

<Subscriber>

<arch>

<name>art030_UploadFile.zip</name>

<status>art030_UploadFile.zip installed</status>

</arch>

<arch>

<name>MasterDetailDPLCHK.zip</name>

<status>MasterDetailDPLCHK.zip installed</status>

</arch>

<state>active</state>

</Subscriber>

</entry>

</subscribers>

<asubscribers />

</RepoSubs>

RepoArch.cs

The RepoArchs class contains four associative arrays:

  • archives contains the archive names and owners

  • docs contains the archive names and documentation URLs

  • administrators contains the administrator user ids

  • publishers contains the publisher user ids

RepoArch has nine methods:

  • A constructor with an XmlReader to restore archives and docs from archives.xml. To restore subscribers and asubscribers, it calls restoreHash2

  • restoreAuth restores administrators and publishers from authorization.xml. It calls restoreHash to restore administrators and publishers

  • restoreHash restores a user array (administrators or publishers) from authorization.xml

  • restoreHash2 restores an associative table from archives.xml

  • WriteXml serializes associative tables in archives.xml

  • add adds an archive to the repository

  • delete removes an archive from the repository

  • isAdministrator returns true if a user is an administrator

  • isPublisher returns true if a user is a publisher

When a new presentation is added, it is deployed on every subscriber and added to the Subscriber objects. Presentations are not automatically added to archive subscribers but when an archive subscriber has subscribed a presentation, it receives presentation updates.

RepoArchs manages archives.xml. Here is an example:

<?xml version="1.0"?>

<RepoArchs>

<archives>

<entry>

<arch>art030_UploadFile.zip</arch>

<val>admin</val>

</entry>

<entry>

<arch>MasterDetailDPLCHK.zip</arch>

<val />

</entry>

</archives>

<docs>

<entry>

<arch>art030_UploadFile.zip</arch>

<val>http://localhost/home2/php/php-index.html</val>

</entry>

<entry>

<arch>MasterDetailDPLCHK.zip</arch>

<val>http://localhost/home2/php/php-index.html</val>

</entry>

</docs>

</RepoArchs>

Deployer.cs

The Deployer class has two static methods:

  • deploy deploys a presentation on a PageBox using the add method of the Deploy Web Service

  • undeploy undeploys a presentation on a PageBox using the delete method of the Deploy Web Service

RepoArchs and RepoSubs extend Deployer and invoke its methods.

Deploy.cs

Deploy.cs is a SOAP proxy. It has been generated from the Deploy Web service of PageBox using wsdl.exe. The constructor has been modified to set the Web service URL, which has to be the subscriber URL.

Global.asax.cs

Global class contains two static members, subRep, a RepoSubs singleton and archRep, a RepoArchs singleton. Global restores archRep and subRep at the first request performed on the Repository application in Application_BeginRequest.

Application_BeginRequest calls restore to restore subRep and archRep.

restore uses RepoArchs and RepoSubs’s constructors with an XmlReader to restore subRep and archRep from subscribers.xml and archives.xml.

Global class contains two methods, saveSubRep to save subRep on subscribers.xml and saveArchRep to save archRep on archives.xml. These methods call the WriteXml methods of RepoSubs and RepoArchs.

subcriber.aspx.cs

The SubscriberWF class manages a form that

  • Lists the Repository subscribers using a DataGrid

  • Allows adding and removing subscribers

The bind method binds an ArrayList to the Datagrid. This ArrayList contains SubscriberEntry objects.

bind populates the ArrayList from RepoSubs.subscribers.

bind is called by Page_Load, subscriberDB_unsubscribe, Form1_subscribe, Form1_unsubscribe, Form1_force, Form1_refresh.

subscriber.aspx provides two buttons to remove subscribers Unsubscribe and Force and a button to refresh the Datagrid, refresh. When the user clicks one of these buttons, Form1_subscribe, Form1_unsubscribe, Form1_force or Form1_refresh is invoked.

Form1_subscribe invokes RepoSubs.subscribe.

Form1_unsubscribe and Form1_force invoke RepoSubs.unsubscribe.

Force allows removing a PageBox that doesn’t exist (anymore) whereas Unsubscribe keeps the subscriber in "pending unsubscribe" state. In that state the subscriber doesn’t receive new archives.

The Datagrid rows have also two buttons, unsub and force.

In InitializeComponent we added subscriberDB_unsubscribe to the Datagrid’s ItemCommand as DataGridCommandEventHandler. When the user clicks either on unsub or force buttons, subscriberDB_unsubscribe is called. subscriberDB_unsubscribe calls RepoSubs.unsubscribe.

publisher.aspx.cs

The publisher class manages a form that

  • Lists the uploaded presentations and batchs using a Datagrid.

  • Allows uploading and removing presentations and batchs.

If you put authentication in place then only publishers and administrators can use that form and a publisher can only see the presentations and batchs that she or he has published.

A user is a publisher if its user id is defined in RepoArchs.publishers.

A user is an administrator if its user id is defined in RepoArchs.administrators.

RepoArchs restores publishers and administrators from authorization.xml. Here is an example of authorization.xml:

<authorization>

<administrators>

<user>admin</user>

</administrators>

<publishers>

<user>publisher1</user>

<user>publisher2</user>

</publishers>

</authorization>

authorization.xml handles role authorizations. Authentication is defined in web.config. By default we use Form based authentication with login-form.aspx:

<authentication mode="Forms">

<forms loginUrl="login-form.aspx">

<credentials passwordFormat="Clear">

<user name="admin" password="admin" />

<user name="subscriber1" password="subscriber" />

<user name="subscriber2" password="subscriber" />

<user name="publisher1" password="publisher" />

<user name="publisher2" password="publisher" />

</credentials>

</forms>

</authentication>

<authorization>

<deny users="?" />

</authorization>

It is very important to define the <authorization> element and to forbid unauthenticated access to the Repository application.

When authentication is in place:

  1. In case of publication, publisher registers the user id as the owner of the presentation

  2. A user B cannot publish a presentation with the same name as a presentation previously published by a user A

  3. update.aspx displays the owner of deployed archives

The bind method binds an ArrayList to the Datagrid. This ArrayList contains PublisherEntry objects.

bind populates the ArrayList from RepoArchs.archives and RepoArchs.docs.

bind is called by Page_Load, archUpload, refresh, archiveDB_delete.

publisher.aspx provides a button to upload archives Upload and a button to refresh the Datagrid, Refresh. When the user clicks one of these buttons, archUpload or refresh is invoked.

archUpload processes POST method upload as defined in RFC 1867. The upload code is quite simple:

string arch = archFile.PostedFile.FileName;

int pos = arch.LastIndexOf("\\");

arch = arch.Substring(pos + 1);

if (!Directory.Exists(Global.archRep.downloadPath))

Directory.CreateDirectory(Global.archRep.downloadPath);

archFile.PostedFile.SaveAs(Global.archRep.downloadPath + arch);

LabStatus.Text = Global.archRep.add(arch, owner, docURL.Value);

bind();

archUpload saves the uploaded file in downloadPath, which is Repository-Directory\..\download as defined in Global.asax.cs with a Repository name which is the same as the uploaded file (arch). Then it calls RepoArchs.add to add the archive to RepoArchs.archives and trigger the deployment of the presentation/batch on subscribers.

Beside the presentation location, publisher.aspx allows specifying the URL of the presentation documentation. archUpload retrieves it in docURL.value.

The Datagrid rows have also two buttons, Delete and Force.

In InitializeComponent we added archiveDB_delete to the Datagrid’s ItemCommand as DataGridCommandEventHandler. When the user clicks either on Delete or Force buttons, archiveDB_delete is called. archiveDB_delete calls RepoArchs.delete.

In both cases publisher send an undeploy(presentation) to all subscribers and removes the presentation file from the repository. If the undeploy succeeds, the presentation is removed from the archive list of the subscriber.

If the undeploy fails for one subscriber:

  • The presentation is removed from the archive list of the subscriber in case of Force

  • The presentation is kept in the archive list of the subscriber in case of Delete

asubscriber.aspx.cs

The asubscriber class is very similar to subscriber.aspx.cs. It manages a form that

  • Lists the Archive subscribers of the Repository using a DataGrid

  • Allows adding and removing Archive subscribers

The bind method binds an ArrayList to the Datagrid. This ArrayList contains SubscriberEntry objects.

bind populates the ArrayList from RepoSubs.subscribers.

bind is called by Page_Load, subscriberDB_handle, Form1_subscribe, Form1_unsubscribe, Form1_force, Form1_refresh.

asubscriber.aspx provides two buttons to remove subscribers Unsubscribe and Force and a button to refresh the Datagrid, refresh. When the user clicks one of these buttons, Form1_subscribe, Form1_unsubscribe, Form1_force or Form1_refresh is invoked.

Form1_subscribe invokes RepoSubs.asubscribe.

Form1_unsubscribe and Form1_force invoke RepoSubs.unasubscribe.

Force allows removing a PageBox that doesn’t exist (anymore) whereas Unsubscribe keeps the subscriber in "pending unsubscribe" state. In that state the subscriber doesn’t receive new archives.

The Datagrid rows have also two buttons, unsub and force.

In InitializeComponent we added subscriberDB_handle to the Datagrid’s ItemCommand as DataGridCommandEventHandler. When the user clicks either on unsub or force buttons, subscriberDB_handle is called. subscriberDB_handle calls RepoSubs.unasubscribe.

The Datagrid rows also contain a link to the aselect page. This link is created in asubscriber.aspx by

<asp:HyperLinkColumn HeaderText=" " ItemStyle-Width="7%" Text="Archives" DataNavigateUrlField="PageBox" DataNavigateUrlFormatString="aselect.aspx?subscriber={0}"/>

When you click on such a link, aselect is invoked in GET mode with a subscriber parameter containing the URL of the PageBox Web service.

aselect.aspx.cs

aselect.aspx.cs manages a form that:

  • Lists the repository archives with a checkbox checked when the archive is deployed on this Archive subscriber

  • Allows adding or removing archives on the subscription

The form operates by delta:

  • If you check a checkbox the corresponding archive is deployed

  • If you uncheck a checkbox the corresponding archive is undeployed

  • You can make multiple changes before submitting the changes

To support this feature we use a MultiGrid class that extends DataGrid.

MultiGrid is based on the article of Dino Esposito published in the MSDN issue of January 2002.

It includes two changes:

  1. The BindName method of SelectColumnTemplate sets the checkbox after the archive status (deployed/not deployed)

  2. The SelectedItems property of MultiGrid returns an array of SelectedEntry objects. A SelectedEntry object contains the checkbox status and the row number

The bind method binds an ArrayList to the MultiGrid. This ArrayList contains SelectorEntry objects.

bind populates the ArrayList from RepoArchs.archives and RepoArchs.docs.

bind is called by Page_Load and Form1_refresh.

Form1_refresh reads SelectedItems, enumerates the archives and adds or remove archives on the subscription list accordingly.

download.aspx.cs

download.aspx allows downloading presentations from Repositories without subscription:

When the presentation is updated, it is not deployed on the download site.

The download site doesn’t need a PageBox.

The download class manages a form that lists the uploaded presentations and batches using a Datagrid.

It implements one method, Page_Load that populates an ArrayList from RepoArchs.archives and RepoArchs.docs and binds it to the Datagrid. This ArrayList contains DownloadEntry objects.

A DownloadEntry contains both the presentation name (Archive) and download URL (ArchiveURL).

download.aspx provides a link to download presentations and batches, defined with:

<asp:HyperLinkColumn Target="_self" DataNavigateUrlField="ArchiveURL" DataTextField="Archive" ItemStyle-Width="28%" HeaderText="Archive"/>

Log.cs

Log.cs provides a write static method. write writes on log.rep entries that contain:

  1. The time when write was invoked

  2. The user and IP address that triggered the write invocation

  3. The invoked method name, parameter and response

audit.aspx.cs

audit.aspx manages a form that displays log.rep and allows removing log.rep.

If you put authentication in place then only administrators can use that form.

The audit class implements two methods, clear and include.

Both methods first check that the user is an administrator.

clear removes the log.rep file.

include calls Response.WriteFile("log.rep")

clear is invoked through the Clear button.

include is invoked by <% include(); %>.

Retry.asmx

If it is properly configured, RepoCleanup calls the Retry.asmx every 30 minutes to retry pending deploys and undeploys. With this mechanism PageBox for .NET can cope with transient conditions such as Pagebox server reboot.

Because Retry.asmx is implemented as a Web Service a single RepoCleanup can monitor a set of Repositories on different machines.

Retry.asmx invokes the cleanup method of RepoSubs.cs.

Form based authentication, which is the preferred authentication scheme for the Repository, is not suitable for Web services. Therefore Retry.asmx is installed on a WebServices subdirectory of the repository.

WebServices contains a specific web.config that disables form-based authentication:

<configuration>

<system.web>

<authorization>

<allow users="?" />

</authorization>

</system.web>

</configuration>

Retry.asmx implements a custom authentication and authorization mechanism consistent with the rest of the Repository: only Repository administrators are allowed to issue cleanup requests. This mechanism is quite simple.

public string Cleanup(string user, string password) {

if (!FormsAuthentication.Authenticate(user, password) ||

!Global.archRep.isAdministrator(user))

return "Retry.Cleanup failed: invalid credentials";

Global.subRep.cleanup();

return "Retry.Cleanup performed";

}

  1. Retry.asmx has a single method, Cleanup whose parameters are the user name and password to check

  2. Cleanup uses FormsAuthentication.Authenticate to check if the user is defined and if its password is correct

  3. Then Cleanup checks if the user is a Repository administrator

  4. If the user credentials are OK, Cleanup calls the RepoSub’s cleanup method

RepoQuery.asmx

RepoQuery has two methods:

  1. GetSubscribers, the single method of the RepoQuery Web service. GetSubscribers returns an array that contains the URL of all subscribers and archive subscribers to a presentation but the requesting subscriber. GetSubscriber is called by the Query Web service of PageBox. GetSubscribers invokes the populate method to retrieve subscribers or archive subscribers.

  2. populate enumerates the subscribers or archive subscribers and select the subscribers to the presentation

PageBox

PbArch.cs

The PbArch class describes presentations and batchs deployed on a PageBox.

PbArch contains three associative tables:

  • archives. archives contains Archive objects and describes deployed archives

  • inflate. inflate contains InstallCommand objects and describes supported extensions and how to install a presentation with a given extension

  • remove. remove also contains InstallCommand objects and describes how to uninstall a presentation with a given extension

The InstallCommand class has three fields:

  • cmd

  • paramPrefix

  • useShell

To process a command, PbArch uses a ProcessStartInfo object:

ProcessStartInfo psi = new ProcessStartInfo();

psi.FileName = ic.cmd;

psi.UseShellExecute = ic.useShell;

psi.Arguments = ic.paramPrefix + Global.path + "\\" + a;

Process p = Process.Start(psi);

A command has a mandatory parameter, which is the archive path.

The parameter string is built like this:

Parameter-prefix + archive-directory + "\\" + archive-name

You can put more than one parameter in Parameter-prefix but they must be followed by the archive full path.

restorePbCmd restores inflate and remove associative tables from pbCmd.xml. To restore inflate or remove, it invokes the restoreHash method.

Here is an example of pbCmd.xml file:

<commands>

<inflate>

<entry>

<extension>.zip</extension>

<command>inflate.js</command>

<param-prefix>/arch:</param-prefix>

<use-shell>true</use-shell>

</entry>

<entry>

<extension>.jar</extension>

<command>-</command>

<param-prefix>-</param-prefix>

<use-shell>true</use-shell>

</entry>

</inflate>

<remove>

<entry>

<extension>.zip</extension>

<command>inflate.js</command>

<param-prefix>/del /arch:</param-prefix>

<use-shell>true</use-shell>

</entry>

<entry>

<extension>.jar</extension>

<command>-</command>

<param-prefix>-</param-prefix>

<use-shell>true</use-shell>

</entry>

</remove>

</commands>

When the PageBox receives a deployment request for an archive xxxx.zip, it will call a WSH script

inflate.js /arch:archive-directory\\xxxx.zip

When the PageBox receives a undeployment request for an archive xxxx.zip, it will call a WSH script

inflate.js /del /arch;archive-directory\\xxxx.zip

When the PageBox receives a deployment request for an archive xxxx.jar, it won’t call a script because "-" stands for "Just copy this archive".

Here is an example of command (inflate.js):

var argsNamed = WScript.Arguments.Named;

if (argsNamed.Exists("arch")) {

var arch = argsNamed.Item("arch");

var pos = arch.lastIndexOf(".");

var dir = arch.substring(0, pos);

var sh = new ActiveXObject("WScript.Shell");

if (argsNamed.Exists("del")) {

var fso = new ActiveXObject("Scripting.FileSystemObject");

fso.DeleteFolder(dir);

// WScript.Echo("rmdir /S /Q " + dir);

} else {

sh.exec("unzip -o " + arch + " -d " + dir);

// WScript.Echo("unzip -o " + arch + " -d " + dir);

}

}

The archives associative table contains Archive objects.

The Archive class maintains the download location, the owner, size, upload time, documentation URL and state of the archive. Archive has a constructor to create a new Archive object, a constructor to restore an Archive object from PbArchives.xml (with a XmlReader parameter) and a method WriteXml to serialize onto PbArchives.xml.

The PbArchs constructor with a XMLReader parameter restores the archives associative table from PbArchive.xml whereas PbArchs’ WriteXml serializes the archive associative table onto PbArchives.xml.

PbArchive.xml looks like this:

<?xml version="1.0"?>

<PbArchs>

<archives>

<entry>

<arch>MasterDetailDPLCHK.zip</arch>

<Archive>

<downloadURL>127.0.0.1/download/</downloadURL>

<owner>publisher1</owner>

<size>16207</size>

<date>2002-02-16T18:04:34.0047628+01:00</date>

<docURL>http://agrandem/home2/cuckoo/cuckoo-pres.html</docURL>

</Archive>

</entry>

</archives>

</PbArchs>

PbArchs has two other methods:

  • add. add adds a presentation to the archives associative table, downloads and installs the presentation

  • delete. delete removes a presentation from the archives associative table, removes and uninstalls the presentation

Global.asax.cs

Global class contains a static member, pbArchives, a PbArchs singleton. Global restores pbArchives at the first request performed on the Repository application in Application_BeginRequest.

Application_BeginRequest calls restore to restore pbArchives.

restore uses PbArchs’ constructor with an XmlReader to restore pbArchives from pbArchives.xml.

Global class contains a savePbArchives method to save pbArchives on pbArchives.xml. This method call the WriteXml method of PbArchs.

Deploy.asmx.cs

Deploy.asmx is the deployment Web service.

Deploy.asmx.cs implements two Web methods, add that invokes the add method of the PbArchs singleton and delete that invokes the delete method of the PbArchs singleton.

update.aspx.cs

The update class manages a form that lists the deployed presentations

The Page_Load method binds an ArrayList to the Datagrid. This ArrayList contains UpdateEntry objects.

Page_Load populates the ArrayList from PbArchs.archives.

Log.cs

Log.cs provides a write static method. write writes on log.html entries that contain:

  1. The time when write was invoked

  2. The user and IP address that triggered the write invocation

  3. The invoked method name, parameter and response

audit.aspx.cs

audit.aspx manages a form that displays log.rep and allows removing log.html.

The audit class implements two methods, clear and include.

clear removes the log.html file.

include calls Response.WriteFile("log.html")

clear is invoked through the Clear button.

include is invoked by <% include(); %>.

Query.asmx

Query.asmx has a single method of the Query Web service, GetSubscribers.

GetSubscribers retrieves the URL of the Repository RepoQuery Web service, invokes this RepoQuery Web service to get the URLs of all other subscribers and archive subscribers to the presentation and returns this list to the requestor – typically a presentation or application installed by the PageBox.

RepoCleanup

RepoCleanup is a Windows service (what used to be called a NT service).

RepoCleanup manages a set of Repositories.

Every 30 minutes RepoCleanup calls the Retry.asmx of every Repository that it knows to retry pending deploys and undeploys. With this mechanism PageBox for .NET can cope with transient conditions such as Pagebox server reboot.

Cleanup.cs

Cleanup.cs is the core class of the Windows service. It implements two methods:

  • OnStart invoked when the Windows service is started

  • OnStop invoked when the Windows service is stopped

OnStart first retrieves the full path of the configuration file (cleanup.xml) and the logging mode.

It first looks in the registry.

As a regular Windows service, Cleanup is defined in the HKEY_LOCAL_MACHINE hive in SYSTEM\CurrentControlSet\Services\Cleanup.

OnStart expects to find the configuration path in SYSTEM\CurrentControlSet\Services\Cleanup\Parameters\ConfigFile and the logging mode in SYSTEM\CurrentControlSet\Services\Cleanup\Parameters\LogDebug.

Then OnStart looks at the startup parameters. It expects to find the path and optionally the logging mode.

If the path is not set either in the registry or as a startup parameter, OnStart writes an error on the Application event log with RepoCleanup as source:

Cleanup.OnStart service without startup parameter (cleanup.xml full path)

If the startup parameters are set, OnStart creates or updates the corresponding registry entries.

Then OnStart creates a CleanupThread and a worker thread where the ThreadRun method of CleanupThread will run.

ThreadRun waits 30 minutes or for a pulse. Then it checks a toStop Boolean. It toStop is true, it terminates. OnStop just sets toStop and issues the pulse to gracefully terminate the worker thread.

CleanupThread.cs

CleanupThread implements

  • A constructor that restores the configuration from cleanup.xml

  • Two logging methods, error and log

  • ThreadRun

Here is an example of cleanup.xml:

<cleanup>

<repository>

<url>http://localhost/PageBox/Repository/WebServices/Retry.asmx</url>

<user>admin</user>

<password>admin</password>

</repository>

<repository>

<url>http://localhost/PageBox/Repository2/WebServices/Retry.asmx</url>

<user>admin</user>

<password>admin</password>

</repository>

</cleanup>

For each Repository, cleanup.xml contains

  1. The URL of its Retry Web Service

  2. A user name and password of a valid administrator account on that Repository

The CleanupThread restores cleanup.xml on an ArrayList of RepositoryEntry.

At each loop, ThreadRun enumerates the ArrayList and calls for each Repository the Cleanup method of the Retry proxy.

error writes an error entry on the Application Event log with a RepoCleanup source.

log writes an information entry on the Application Event log with a RepoCleanup source if the logging mode, toLog is true.

Retry.cs

Retry.cs is a SOAP proxy. It has been generated from the Retry Web service of the Repository using wsdl.exe. The constructor has been modified to set the Web service URL, which has to be the Repository URL.

ProjectInstaller.cs

ProjectInstaller.cs is a generated class responsible for the installation and de-installation of the Windows service.

In .NET beta 2, we must set the service user and password. Even in Release version, because RepoCleanup can invoke Retry on other machines, we should use a network-enabled account with write access to the registry.

To avoid hard coding the user and password, during installation and de-installation, ProjectInstaller prompts for the user name and password.

TestRepoCleanup

TestRepoCleanup was designed to test RepoCleanup functions.

Therefore it includes the same classes as RepoCleanup:

  • CleanupThread.cs

  • Retry.cs

You can use it to test your modifications.

It is also user-friendlier than regedit and the Windows service startup parameters to set the registry entries.

TestRepoCleanup uses a Windows form, TestCleanup.

TestCleanup.cs

The TestCleanup form contains two buttons, Start and Stop.

The TestCleanup class contains three methods:

  • The constructor that retrieves the cleanup.xml path and the logging mode from the registry. It also sets a text box and a check box accordingly

  • OnStart called when you click on the Start button. It retrieves the content of the text box and the check box, updates the registry and creates a CleanupThread and a worker thread where the ThreadRun method of CleanupThread will run

  • OnStop called when you click on the Stop button. It sets toStop and issues a pulse to gracefully terminate the worker thread

Contact:support@pagebox.net
2001-2004 Alexis Grandemange. Last modified .