Saturday, May 31, 2008

FreeMind manual installation in Ubuntu Hardy 8.04

So you like the mind mapping software FreeMind, but the distribution package for Ubuntu 8.04 is hideously out of date. Your solution awaits... simply by installing FreeMind from source. While this is fairly easy to follow, there is some complexity with getting full desktop integration. I am including the steps I followed, but if you scroll all the way to the bottom, you can find a compiled archive with 0.9.0 beta 17 included with a script to do all the work referenced in the article.

First, you need a few packages (if you are going to use the version of FreeMind I compiled below, you do not need sun-java6-jdk):

sudo aptitude install sun-java6-jre sun-java6-fonts sun-java6-jdk


Now download FreeMind. I recommend the latest beta version, found here. You will also need to download Apache Ant. There is an Ant package in the Hardy repositories, but it is broken, so you will need the binaries directly from Apache. I used 1.7.0, the latest version available at the time of this article.

Unpack Ant and copy it to its destination (execute the following in a terminal wherever you placed the downloaded Ant archive):

tar xf apache-ant-1.7.0-bin.tar.bz2
sudo mkdir /usr/local/ant
sudo mv apache-ant-1.7.0/* /usr/local/ant


Set up Ant's environment variables:

gksu gedit /etc/rc.local

# In gedit, append the following to this file before "exit 0":

export ANT_HOME=/usr/local/ant
export PATH=${PATH}:${ANT_HOME}/bin


Reboot for the above to take effect, or just execute the two export commands within your current terminal. Now you are ready to compile FreeMind. Unpack it and build it with Ant:

tar xf freemind-src-0.9.0_Beta_17.tar.gz
cd freemind
ant


Now copy the built contents of the dist folder into /opt/freemind, and set up the executable:

sudo mkdir /opt/freemind
sudo cp -R ../bin/dist/* /opt/freemind
sudo chmod +x /opt/freemind/freemind.sh
sudo ln -s /opt/freemind/freemind.sh /usr/local/bin/freemind


Congratulations, you can now run FreeMind by simply typing the command: freemind

The harder part was registering the x-freemind MIME type and getting Gnome to open .mm files with a double-click (and having an icon assigned to those files!). For the MIME type, there are two existing conflicting MIME types you will have to get rid of: x-troff-mm and x-matlab. As I have no use for these applications, this is not a problem for me. These are defined in /usr/share/mime/packages/freedesktop.org.xml, and you have to comment out the nodes as follows:

<!--
<mime-type type="text/x-matlab">
<sub-class-of type="text/plain"/>
<comment>MATLAB script/function</comment>
<comment xml:lang="bg">Скрипт/функци� — MATLAB</comment>
<comment xml:lang="ca">script/funció MATLAB</comment>
<comment xml:lang="cs">Skript/funkce MATLAB</comment>
<comment xml:lang="de">MATLAB-Skript/-Funktion</comment>
<comment xml:lang="en_GB">MATLAB script/function</comment>
<comment xml:lang="es">script/función de MATLAB</comment>
<comment xml:lang="eu">MATLAB script/funtzioa</comment>
<comment xml:lang="fi">MATLAB-skripti/funktio</comment>
<comment xml:lang="fr">script/fonction MATLAB</comment>
<comment xml:lang="hu">MATLAB parancsfájl/funkció</comment>
<comment xml:lang="it">Script/Funzione MATLAB</comment>
<comment xml:lang="ja">MATLAB スクリプト/関数</comment>
<comment xml:lang="ko">MATLAB 스�립트/함수</comment>
<comment xml:lang="nb">Skript/funksjon for MATLAB</comment>
<comment xml:lang="nl">MATLAB-script/functie</comment>
<comment xml:lang="nn">MATLAB-skript/funksjon</comment>
<comment xml:lang="pl">Skrypt/funkcja MATLABa</comment>
<comment xml:lang="pt_BR">Script/função do MATLAB</comment>
<comment xml:lang="sv">MATLAB-skript/funktion</comment>
<comment xml:lang="uk">Сценарій/функці� MATLAB</comment>
<comment xml:lang="vi">Văn lệnh/chức năng MATLAB</comment>
<magic priority="10">
<match value="%" type="string" offset="0"/>
</magic>
<magic priority="50">
<match value="function" type="string" offset="0"/>
</magic>
<glob pattern="*.m"/>
<alias type="text/x-octave"/>
</mime-type>
-->


...and....

<!--
<mime-type type="text/x-troff-mm">
<sub-class-of type="text/plain"/>
<comment>Troff MM input document</comment>
<comment xml:lang="bg">Изходен документ — Troff MM</comment>
<comment xml:lang="ca">document d'entrada Troff MM</comment>
<comment xml:lang="cs">Vstupní dokument Troff MM</comment>
<comment xml:lang="da">Troff MM inddata-dokument</comment>
<comment xml:lang="de">Troff-MM-Eingabedokument</comment>
<comment xml:lang="el">έγγ�αφο/π�όγ�αμμα εντολών troff MM</comment>
<comment xml:lang="en_GB">Troff MM input document</comment>
<comment xml:lang="eo">eniga dokumento de Troff MM</comment>
<comment xml:lang="es">documento de entrada Troff MM</comment>
<comment xml:lang="eu">Troff MM sarrerako dokumentua</comment>
<comment xml:lang="fi">Troff MM -syöteasiakirja</comment>
<comment xml:lang="fr">document d'entrée Troff MM</comment>
<comment xml:lang="hu">Troff MM bemeneti dokumentum</comment>
<comment xml:lang="it">Documento di input Troff MM</comment>
<comment xml:lang="ja">Troff MM 入力ドキュメント</comment>
<comment xml:lang="ko">Troff MM input 문서</comment>
<comment xml:lang="lt">Troff MM įvesties dokumentas</comment>
<comment xml:lang="ms">Dokumen input Troff MM</comment>
<comment xml:lang="nb">Troff MM-inndatadokument</comment>
<comment xml:lang="nl">Troff MM-invoerdocument</comment>
<comment xml:lang="nn">Troff MM inndata-dokument</comment>
<comment xml:lang="pl">Dokument wejściowy Troff MM</comment>
<comment xml:lang="pt">documento origem Troff MM</comment>
<comment xml:lang="pt_BR">Documento de entrada Troff MM</comment>
<comment xml:lang="sq">Dokument input-i Troff MM</comment>
<comment xml:lang="sr">Troff MM улазни документ</comment>
<comment xml:lang="sv">Troff MM-indatadokument</comment>
<comment xml:lang="uk">Вхідний документ Troff MM</comment>
<comment xml:lang="vi">Tà i liệu nhập MM Troff</comment>
<comment xml:lang="zh_CN">Troff MM 输入文档</comment>
<glob pattern="*.mm"/>
</mime-type>
-->


You then need to add a file at /usr/share/mime/packages/freemind.xml with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-freemind">
<comment>FreeMind Mind Map</comment>
<glob pattern="*.mm"/>
</mime-type>
</mime-info>


Once you have edited/created these files, you need to update the MIME database:

sudo update-mime-database /usr/share/mime


To assign icons to the FreeMind .mm files, It turns out you have to create 48x48, 32x32, and 24x24 icons (PNG files) for FreeMind, copy these to /usr/share/icons/gnome under the appropriate size-named folders, and then update the icon cache. I used GIMP to create the icons based on an svg icon that came with the FreeMind source package. Each icon PNG must be named gnome-mime-application-x-freemind.png. To update the icon cache once these are in place:

sudo gtk-update-icon-cache --force gnome


Once you are done, log out and back in, and enjoy your FreeMind goodness.

NOW, if that all seems a bit much... I have created an archive containing a script that does everything except set up the main menu item pointing to FreeMind. It contains a version of FreeMind 0.9.0 beta 17 I compiled (on 64-bit Ubuntu, so this may or may not work on 32-bit versions) along with the modifications to the MIME types and the icons I created.

Download it here: freemind-0.9.0_Beta_17.tar.bz2


Monday, May 05, 2008

Integrating Ubuntu Hardy Heron 8.04 with Active Directory

I have three primary goals with integrating Ubuntu Server with Active Directory:
  • Join the server to the domain
  • Allow domain admins to be Ubuntu Server administrators
  • Allow Windows clients in domain groups access to Samba shares
Goal #1: Join the Server to the Domain

Thanks to this post for helping with this portion. The steps are:
  1. sudo apt-get update
  2. sudo apt-get install likewise-open
  3. sudo domainjoin-cli join fqdn.of.your.domain Administrator
  4. sudo update-rc.d likewise-open defaults
  5. sudo /etc/init.d/likewise-open start
Goal #2: Allow Active Directory Domain Administrators to Administer Ubuntu

Ubuntu Forums to the rescue... thanks, gotee12. This will allow members of the Domain Admins AD group to issue sudo commands. From a command prompt:
  1. visudo
  2. Add this line to the resulting file:
%YOURDOMAINNAME\\domain^admins ALL=(ALL) ALL
Note the carat symbol to substitute for spaces.

Goal #3: Allow Windows Clients in Domain Groups to Access Samba Shares

*** UPDATE *** My friend Chris got the plumbing to wire up Likewise Open with Samba figured out. Good grief, this was opaque:
http://chrplunk.blogspot.com/2008/06/allow-windows-clients-in-active.html

Now you have to set up your shares. The shares are defined as individual text files under /var/lib/samba/usershares. Create a file in this folder named with the name of the share (e.g. "test") and contents like the following, but be careful--match the spaces and casing with nothing extra, and **make sure the file name is in all lowercase regardless of the casing of the share name**:
#VERSION 2
path=/path/to/shared/folder
comment=
usershare_acl=<Group SID>:<access modifier>
guest_ok=y
For example:
#VERSION 2
path=/testShare
comment=
usershare_acl=S-1-1-0:F
guest_ok=y
To get the SID of the group that will have access to enter in the usershare_acl row, execute:
wbinfo -n "DOMAIN\group"
(S-1-1-0 is Everyone.)

The access modifiers after the group SID are as follows:
  • R - read-only
  • F - full access
  • D - deny access
The last thing you need do is to set the permissions on the shared folder itself. I found it easiest to give world-writable permissions to the folder, as it seemed not to dereference my group memberships at the folder permission level (unlike Samba at the share level). So:
chmod -R 0777 /path/to/shared/folder
If anyone knows how to get the group security to work at the folder level so it need not be world-writable, I'd appreciate a comment. I tried:
chgrp -R 'DOMAIN\group' /path/to/shared/folder
chmod -R 2770 /path/to/shared/folder
...but I kept getting access denied.

*** UPDATE 2 *** I had to grant read access to everyone for the usershares folder to avoid 'cannot stat' errors by ordinary users:
chmod o+r /var/lib/samba/usershares



Original post for this section follows:

Oooh, I haven't managed to get this one to work. I can issue successful commands like the following while logged on to the Ubuntu machine with my domain credentials:

smbclient -k -L //dmsc01
OS=[Windows Server 2003 R2 3790 Service Pack 2] Server=[Windows Server 2003 R2 5.2]

Sharename Type Comment
--------- ---- -------
C$ Disk Default share
IPC$ IPC Remote IPC
ADMIN$ Disk Remote Admin
OS=[Windows Server 2003 R2 3790 Service Pack 2] Server=[Windows Server 2003 R2 5.2]

Server Comment
--------- -------

Workgroup Master
--------- -------

So SOMETHING's working, but I can't manage to get remote machines to connect to hosted shares. I've tried the following smb.conf (key lines included):

workgroup = mydomain
security = ads
realm = MYDOMAIN.LOCAL
encrypt passwords = yes
idmap uid = 10000-40000
idmap gid = 10000-40000
template homedir = /dev/null
template shell = /bin/false
winbind separator = \
winbind use default domain = yes
winbind enum users = yes
winbind enum groups = yes
winbind cache time = 300
winbind nested groups = yes

#=====================Shares====================
[tmp]
path = /tmp
browseable = yes
writeable = yes
guest ok = no


All I get when attempting to connect, however, is errors like the following in the client logs:

[2008/05/05 10:27:14, 1] libads/kerberos_verify.c:ads_secrets_verify_ticket(237)
ads_secrets_verify_ticket: failed to fetch machine password
[2008/05/05 10:27:14, 1] smbd/sesssetup.c:reply_spnego_kerberos(316)
Failed to verify incoming ticket with error NT_STATUS_LOGON_FAILURE!

And from the log.winbindd-idmap:

[2008/05/05 10:25:11, 1] nsswitch/idmap_tdb.c:idmap_tdb_alloc_init(397)
idmap uid range missing or invalid
idmap will be unable to map foreign SIDs
[2008/05/05 10:25:11, 0] nsswitch/idmap.c:idmap_alloc_init(750)
ERROR: Initialization failed for alloc backend, deferred!


Any ideas?

Wednesday, April 30, 2008

Silverlight 2.0 integration with Windows Forms

Here's how you can host Silverlight 2.0 beta 1 applications in existing Windows Forms applications and have two-way communication between them. There may be an ActiveX approach that will accomplish this, but the approach I took was with a WebBrowser control.

First, set up the Windows Forms client. I'll use Form1, the hardest working form of them all. I simply drag the WebBrowser control onto the form. In its constructor, I set a few properties needed for having the embedded WebBrowser:


public partial class Form1 : Form {
public Form1() {
InitializeComponent();

webBrowser1.AllowWebBrowserDrop =
webBrowser1.IsWebBrowserContextMenuEnabled =
webBrowser1.WebBrowserShortcutsEnabled = false;
webBrowser1.ObjectForScripting = this;

webBrowser1.Navigate("http://<url of Silverlight application>");
}


I also added a property and a method in the Windows Form for the hosted Silverlight application to call:


public void ButtonClicked(string message) {
MessageBox.Show("ButtonClicked: " + message);
}

public string Test {
set {
MessageBox.Show("Test: " + value);
}
}


In the Silverlight application, use managed code like the following (e.g. in a click event handler, load event, etc.) to call the custom methods on the hosting form (note that you need a reference to System.Windows.Browser to get to the browser):



using System.Windows.Browser;
/* ... */

string msg = "Clicked at " + DateTime.Now.ToString();
HtmlWindow w = HtmlPage.Window;
ScriptObject o = (ScriptObject)w.GetProperty("external");
if (null != o)
{
try
{
// Set a property value on the host form
o.SetProperty("Test", msg);

// Call a method on the host form
o.Invoke("ButtonClicked", new object[] { msg });
}
catch { }
}


Note the catch block: I haven't yet discovered how to detect if the Silverlight application is being hosted in a WebBrowser from inside (if it is being run directly in a browser, the 'external' object exists but invoking custom properties and methods will fail).

Calling methods in the Silverlight application from the WebBrowser control is a bit more complex and involves a few steps:

1) Stage the Silverlight application and methods for scripting

In App.xaml, you must register each Silverlight page for scripting support. For example, if I have a page called Page, I need code like the following:



Page p = new Page();
this.RootVisual = p;
HtmlPage.RegisterScriptableObject("Page", p); // The identifier ("Page") here is arbitrary and refers to your key for identifying the object from script



Now that I've done this, I have to mark each Silverlight page class with the ScriptableType attribute:


[ScriptableType()]
public partial class Page : UserControl
{
/* ... */



Also, each public method I intend to call in the marked class from external script must be marked with the attribute:


[ScriptableMember()]
public void SetSearchText(string msg)
{
/* ... */



2) Set up scripting support in the web page hosting the Silverlight application

The WebBrowser control can call script methods within the page, but doesn't seem to be able to call the Silverlight control object directly (I made several attempts to do this but was unsuccessful). What I ended up doing that worked was to set up a script method corresponding to each method I want to call within the Silverlight application.

First, alter the tag on the Silverlight control so that it calls a script method of yours when it loads:



<div style="height:100%;">
<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/MySilverlightApp.xap" Version="2.0" Width="100%" Height="100%" OnPluginLoaded="pluginLoaded" />
</div>



Now, add a script block in the HEAD tag with a method corresponding to the above to store a reference to the Silverlight control when it loads:



<head runat="server">
<title>Test Page For DiggSample</title>
<script type="text/javascript">
var scControl;

function pluginLoaded(sender) {
scControl = sender.get_element();
}
</script>
...



Next, add one script method for each method you marked exposed within the Silverlight application. Note the formatting (you must call it in the form: objectName.Content.<name you chose as the Silverlight script object identifier>.method(arguments)):



<script type="text/javascript">
function SetSearchText(msg) {
scControl.Content.Page.SetSearchText(msg);
}
</script>



Finally, from within the Windows Forms application, you can call the method you exposed via the WebBrowser control as follows:



private void btnSetSearchText_Click(object sender, EventArgs e)
{
webBrowser1.Document.InvokeScript("SetSearchText", new string[] { "foo" });
}



That's it--you should be able to have two-way communication between the Windows Forms application and the Silverlight application hosted via its WebBrowser control.

Tuesday, April 29, 2008

Debugging Kerberos authentication issues

I have found the following registry key to be of greatest assistance when debugging Kerberos issues. It sets the following parameters:
  • Turns on verbose debug logging
  • Forces Kerberos to use TCP instead of UDP (MaxPacketSize parameter)
  • Increases the token size so that users with large numbers of groups will fit inside the Kerberos ticket
Just save the following as a .reg file and double-click it on your server to enter it into the registry.

----COPY BELOW THIS LINE----
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters]
"LogLevel"=dword:00000001
"KerbDebugLevel"=dword:ffffffff
"LogToFile"=dword:00000000
"MaxTokenSize"=dword:0000ea60
"MaxPacketSize"=dword:00000001

----COPY ABOVE THIS LINE----

PerformancePoint 2007 Monitoring Server per user authentication



I had an interesting time getting Kerberos authentication working for PerformancePoint 2007 Monitoring Server. The deployment guide is pretty thorough, but I had some issues getting the Kerberos authentication to function. After making the changes recommended in the guide for Kerberos auth and per-user security, the Dashboard Designer would produce the following error when trying to refresh:

Unable to connect to the specified server. Make sure the address is correct.


After reviewing Kerberos logging messages, I found that this was a Kerberos error. I used adsiedit to set SPNs rather than the SetSPN utility as I find it a bit faster to work with. I set the service principal names above on the Monitoring Server application pool identity domain account (locate the account in the tree, right-click and choose Properties, select the servicePrincipalName attribute, and click Edit). This is because:
  • My PPSMonitoring web runs on the dppt01 server on port 40000;
  • My PPSPlanningWebServices web runs on the dppt01 server on port 46787; and
  • My PPSPlanningAdminConsole web runs on the dppt01 server on port 46788.
This wasn't sufficient to make it work, however. I also had to:

- Set one more SPN (for both the short and fully-qualified domain name) on both the server's computer account and the Monitoring Server application pool identity:
  • HTTP/dppt01.domain.local
  • HTTP/dppt01
- Change the application pool identity of the PPSMonitoringCentral app pool (for some reason, the installer defaulted this to Network Service instead of my app pool identity, ppt-pool-dev).

After doing these steps and allowing for replication, Dashboard Designer was again able to connect and enumerate resources.

Friday, April 25, 2008

Integrating PerformancePoint 2007 into MOSS

Being new to PerformancePoint 2007, it wasn't immediately apparent to me how to integrate it into MOSS. I found that you do this by installing the Dashboard Viewer for SharePoint Services on the MOSS server.

Prerequisites on MOSS Server
  • Microsoft ASP.NET 2.0 AJAX Extensions 1.0
Installation
  1. Mount the PerformancePoint 2007 media in the MOSS server.
  2. Choose the Monitoring Server installation and complete it.
  3. Run the Monitoring Server Configuration Manager.
  4. Uncheck all options except for the Dashboard Viewer for SharePoint Services.
  5. Select the site collection in which to install the Dashboard Viewer.
If you need to later install the Dashboard Viewer web part on an additional site collection, this post has an excellent guide to doing so. In step 2 where the author references uploading the master page, I did this differently:
  • Navigated to http:///_catalogs/masterpage/Forms/AllItems.aspx, and clicked the Upload button.
  • Browsed to %programfiles%\Microsoft Office PerformancePoint Server\3.0\Monitoring\Assemblies\ and chose PerformancePointDefault.master.
  • Once uploaded, used the context menu on the uploaded master page and used the Approve/Reject link to approve the uploaded item.

Tuesday, April 22, 2008

Further adventures with Citrix WISP installation

Continuing with earlier efforts to get WISP working, I attempted to re-add/re-deploy the solutions after first undeploying/removing them. Prerequisite steps:

Turn on WISP logging. You can import the following registry key to do so (save as a .reg file and double-click it; don't forget to actually create the folder):

------COPY BELOW THIS LINE-----
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Citrix\WISP]
"LogFolder"="C:\\temp\\WISP_logs"
-----COPY ABOVE THIS LINE-----

Turn on verbose MOSS (ULS) logging:
  1. Open Central Administration, click Operations.
  2. Click Diagnostic Logging.
  3. Under the Event Throttling section, set Verbose in "Least critical event
    to report to the trace log."
  4. Under the Trace log section, type 20 in Number of log files.
  5. Click OK.

To add the solutions:

stsadm -o addsolution -filename CitrixWssCore.wsp
stsadm -o addsolution -filename CitrixAppDeliveryWebPart.wsp
stsadm -o addsolution -filename CitrixContentRedirection.wsp
stsadm -o addsolution -filename CitrixMossCore.wsp

While adding seems to be pretty safe, you have to be very careful about the order of deployment of the various WSPs. The CitrixWssCore.wsp must be deployed first, and this deployment doesn't necessarily work. You must carefully review stsadm output to see what your results were before proceeding. After initiating the deployment, check the Timer Job Status page in CA to see if the job is complete and/or run stsadm -o enumsolutions and look for the solution in the list with the Deployed node set to true.

stsadm -o deploysolution -name CitrixWssCore.wsp -immediate -allowgacdeployment

On this attempt, I was deploying CitrixWssCore.wsp first as directed. Note the value of the LastOperationResult node:

<Solution Name="citrixwsscore.wsp">
  <Id>fe3deba9-9b5d-4105-9983-2af1db3c0e42</Id>
  <File>CitrixWssCore.wsp</File>
  <Deployed>FALSE</Deployed>
  <WebApplicationSpecific>FALSE</WebApplicationSpecific>
  <ContainsGlobalAssembly>TRUE</ContainsGlobalAssembly>
  <ContainsCodeAccessSecurityPolicy>FALSE</ContainsCodeAccessSecurityPolicy>
  <LastOperationResult>DeploymentFailedFileCopy</LastOperationResult>
  <LastOperationTime>4/21/2008 4:14 PM</LastOperationTime>
</Solution>

I didn't find any particular reason for this failure, but I repeated the operation, and the next time got success values in these nodes.

Once I deployed the key prerequisite package, it was on to the others. The CitrixAppDeliveryWebPart also balked:

<Solution Name="citrixappdeliverywebpart.wsp">
  <Id>8a0a1be2-7648-4703-9cca-8ea0fa625793</Id>
  <File>CitrixAppDeliveryWebPart.wsp</File>
  <Deployed>FALSE</Deployed>
  <WebApplicationSpecific>TRUE</WebApplicationSpecific>
  <ContainsGlobalAssembly>FALSE</ContainsGlobalAssembly>
  <ContainsCodeAccessSecurityPolicy>TRUE</ContainsCodeAccessSecurityPolicy>
  <LastOperationResult>DeploymentFailedFeatureInstall</LastOperationResult>
  <LastOperationTime>4/22/2008 10:34 AM</LastOperationTime>
</Solution>

This also occurred on my second attempt. So I started digging through the MOSS ULS logs (it's a good idea to turn on verbose logging before starting operations like this, as exceptions do not generally get logged to the Windows event log). I found the following key message:

Line 19554 : 04/22/2008 10:41:33.12 OWSTIMER.EXE (0x058C) 0x1404 Windows SharePoint Services Topology 8zpd High Solution Deployment : Error - Add Feature definition for citrixappdeliverywebpart.wsp Exception message - A feature with ID 94af8a34-19db-4114-876d-5a7a587a8405 has already been installed in this farm. Use the force attribute to explicitly re-install the feature.

Apparently, the uninstall procedure (I had made earlier attempts to install these solutions) did not properly remove the features. I was able to get this one to pass by adding the -force switch to the stsadm deploy solution command.

stsadm -o deploysolution -name CitrixAppDeliveryWebPart.wsp -immediate -allowgacdeployment -allowcaspolicies -url http://server -force

After this, I forced the remaining solution deployments as well (CitrixContentRedirection.wsp and CitrixMossCore.wsp) and the rest succeeded.

stsadm -o deploysolution -name CitrixContentRedirection.wsp -immediate -allowgacdeployment -force

stsadm -o deploysolution -name CitrixMossCore.wsp -immediate -allowgacdeployment -force


After deployment of these features comes activation. Unless your application pool identity has admin privileges in various areas (this should not be the case), you will need to use the stsadm commands to activate the features. You must activate the CitrixAccessCore feature, and you must activate it before the others. Fortunately, activation does not use a timer job, so you get immediate feedback from stsadm about the success or failure of your request.

stsadm -o activatefeature -name CitrixAccessCore -url http://server
stsadm -o activatefeature -name CitrixTopNavigation -url http://server
stsadm -o activatefeature -name CitrixQuickLaunchNavigation -url http://server
stsadm -o activatefeature -name CitrixAdministrationTool -url http://server
stsadm -o activatefeature -name CitrixAppDeliveryWebPart -url http://server
stsadm -o activatefeature -name CitrixContentRedirectionModule -url http://server
stsadm -o activatefeature -name CitrixContentRedirectionMenu -url http://server
stsadm -o activatefeature -name CitrixContentRedirectionNewMenu -url http://server


The key step after getting everything installed is to configure the connection to the Citrix farm. From the site collection root, go to Site Settings | Modify All Site Settings > Citrix Administration and specify the applicable settings. At first I tried going to the Advanced Administration and copying the contents of our Citrix farm's WebInterface.conf file into the large textbox, but that is not sufficient.

Now if I could just get past the "No Resources found" message presented by the Citrix Application Delivery web part...

*** UPDATE ***
I got the Application Delivery web part working. It turned out the CitrixWssCore feature did not deploy properly in spite of the success message returned by stsadm -o enumsolutions. The contents of the WISP logs were the only place I saw the exception:

AccessCore.DeploymentJob: Wednesday, April 23, 2008 1:36:01 PM
Service Provider Deployment run as Identity: DOMAIN\server-farm-account
CreateEventLog() Error: Requested registry access is not allowed.
at System.ThrowHelper.ThrowSecurityException(ExceptionResource resource)
at Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable)
at System.Diagnostics.EventLog.CreateEventSource(EventSourceCreationData sourceData)
at System.Diagnostics.EventLog.CreateEventSource(String source, String logName)
at Citrix.WISP.Util.CoreLog.CreateEventLog(CultureInfo locale)
....
Info: Attempting to create Web Virtual Directory (CitrixAccessPlatform-f6ec3ff1-328a-4fdf-b78b-61f0f5b703d0):
ADS Path: IIS://localhost/W3SVC/1634379371/Root/f6ec3ff1-328a-4fdf-b78b-61f0f5b703d0
File Path: C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\CitrixAccessPlatform\f6ec3ff1-328a-4fdf-b78b-61f0f5b703d0
IISObject: Exception has been thrown by the target of an invocation.

Our MOSS server farm account was not a local machine administrator on the SharePoint machine, and apparently this is required for the CitrixWssCore deployment to create the custom event log and its web site. I had to grant these rights and the redeploy the solution with the -force option to correct it. The key point is that you must review all possible logs, including the WISP logs, to check for installation/deployment problems.

Citrix, won't you please build a real installer for WISP that will take care of some of these details/checks?