The August 2008 Blog
send me a comment

Agent to List Databases+Info on a Server (Friday, Aug 22)
[ permalink ] [ e-mail me ] [ ]

I meant to write this up last night, but I got tired and went to bed instead. So here's an early morning blog post for you.

This is code for an agent that will connect to a server, get all the databases (and templates) on the server, and write a ton of information about each database to a comma-delimited file for your spreadsheeting pleasure:

Just import the LSS file into a new agent, save it, and run it. You will be prompted for a server and an output file name, and in return you will get a CSV file with lots and lots of information.

Note that I have only tested this on Domino 8 and you MUST have rights to run remote console commands on the server you run this against -- if you don't, you can get a subset of this information using NotesDbDirectory, but it's a LOT slower (I leave this as an exercise for the reader). Also, the code to get a list of servers is Windows-only, so you Mac guys may need to comment a few things out (not sure).

Oh, and speaking of CSV files, the reverend Steve McDonagh posted a fix to my CsvReader class for those of you who need to use CsvReader on an iSeries box. Apparently you have to open text files in a very special way on an iSeries.

Passport Renewal (Saturday, Aug 16)
[ permalink ] [ e-mail me ] [ ]

A couple months ago I realized my passport was going to expire early next year. I know I'll be out of the country a few more times this year (Collaboration University and UKLUG in London, and the View Developer conference in Amsterdam), so I figured I'd look into getting my passport renewed in January after all that travel was over.

Well, then someone told me that some countries won't accept your passport if it's going to expire within 6 months of your anticipated return date. I thought that was strange, but I did a quick search (since Google knows everything) and sure enough it's true. In fact, you can even look up the country you're going to on the US International Travel site and check the passport expiration rules.

Just to be safe I went ahead and renewed my passport. I even paid the extra $60 for the "Expedited" service since CollabU and UKLUG are next month, and I remember that a few people had serious delays with their passports before ILUG last year. Happily, I got my new passport less than 2 weeks after I sent the application off (along with my current passport, which was a little scary to be without) for processing. It's nice when things work the way they're supposed to.

Ninjalympics (Wednesday, Aug 13)
[ permalink ] [ e-mail me ] [ ]

Tired of the Olympics? Too bad they're not televising the Ninjalympics:

AskANinja Ninjalympics

AskANinja also has the best explanation of the problem with Net Neutrality I've ever heard.

Yellow Day: Infinite Recursive Notes Icon (Monday, Aug 11)
[ permalink ] [ e-mail me ] [ ]

In celebration of Yellow Day, here's a little something to make you dizzy: an infinite recursive Lotus Notes icon:

Infinite Recursive Lotus Notes Icon

It's not quite as smooth as the Hasselhoffian recursion (thanks Damien) or the Sierpinski zoom, but it's not bad for something I threw together in front of the TV. If you have greater graphic abilities than I do (which is likely), please feel free to improve on the technique.

Macho Manscara (Saturday, Aug 9)
[ permalink ] [ e-mail me ] [ ]

I was listening to the Wait, Wait, Don't Tell Me podcast this morning (a funny "week in review" sort of show), and they had a story about a company that is trying to enter the largely untapped market of male cosmetics. Their new line is called Taxi Man.

In a hurry for dinner? Late for work? Don't worry men, just apply a little Manscara and Guy-Liner and you'll be as fresh as ever.

Dude, you look Mantastic!

Cauliflower Mushroom (Wednesday, Aug 6)
[ permalink ] [ e-mail me ] [ ]

I was walking through my back yard yesterday and saw this laying near some trees:

Sparassis crispa aka Cauliflower Mushroom (looks like a loofah sponge to me)

It's about the size of a small teapot. I thought it was a loofah sponge that the dog dragged into the yard, but it was rooted to the ground. A little Internet research later, and I'm pretty sure it's a Sparassis crispa, also known as a Cauliflower Mushroom. Supposedly it's edible and delicious when young and fresh, but I don't think I'll be eating it.

Just for kicks, I also uploaded the picture to WikiMedia Commons. I'm not a Wikipedia contributor or anything (well, I guess I am now), but I had a hard enough time identifying what the heck it was that I figured I'd share the photo with the world. Maybe that'll help someone else.

Run Command Line Tools Using Java (Tuesday, Aug 5)
[ permalink ] [ e-mail me ] [ ]

In case you didn't realize this, you can actually run programs and command line tools using Java, similar to the LotusScript "Shell" function. The advantage this has over the Shell function is that you can capture the output of a command line tool or statement without having to resort to creating batch files and trying to wait until they're done.

For example, here's an agent that will run NBTStat to attempt to determine the machine name and user login name for a given IP address:

import lotus.domino.*;
import java.util.*;

// NOTE: Agent Runtime Security must be at least 2, and
// agent signer must be able to run unrestricted operations
public class JavaAgent extends AgentBase {

    public void NotesMain() {

        try {
            Session session = getSession();
            AgentContext agentContext = session.getAgentContext();
            Document doc = agentContext.getDocumentContext();
            String remoteAddr = doc.getItemValueString("Remote_Addr");
            InetAddress addr = InetAddress.getByName(remoteAddr);
            PrintWriter pw = getAgentOutput();
            pw.println("Remote address is: " + addr.getHostName());
            String[] cmd = new String[3];
            cmd[0] = "cmd.exe" ;
            cmd[1] = "/C" ;
            cmd[2] = "nbtstat -A " + remoteAddr;
            // must be run with unrestricted access
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(cmd);
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(proc.getInputStream()) );
            BufferedReader err = new BufferedReader(
                    new InputStreamReader(proc.getErrorStream()) );
            //int exitVal = proc.waitFor();
            // instead of printing the output, you could parse it of course
            String line = "";
            pw.println("<br/><br/><b>Output is:</b><br/>");
            while ( (line = in.readLine()) != null)
                pw.println("<br/>" + line);
            pw.println("<br/><br/><b>Errors were:</b><br>");
            while ( (line = err.readLine()) != null)
                pw.println("<br/>" + line);
        } catch(Exception e) {

As I mention in the code comments, an agent using this technique must have a runtime security setting of at least 2 ("Allow restricted operations"), and the agent signer must have the ability to run unrestricted operations.

Compile JavaScript to EXE, More LotusScript Speech (Sunday, Aug 3)
[ permalink ] [ e-mail me ] [ ]

My last blog entry about talking LotusScript was supposed to be kind of a throw-away bit of code, but there was enough interest in it that I decided to research the Microsoft Speech Application Programming Interface (SAPI) a bit more. There is also a Java Speech API, but I haven't had time to play with that yet.

Before I get into bullet points though, there was an interesting diversion on one of the pages that came up in my searches. On "The Glass Is Too Big" blog, there was some discussion on using MS SAPI to convert an RSS feed to a podcast, along with some instructions on how to compile JavaScript to an EXE file using the free .NET SDK -- in fact, you may already have the jsc.exe file in your C:\WINDOWS\Microsoft.NET\Framework\v### folder. I'm going to file that away under the "might be interesting to try out sometime" category in my brain. (Yes, I know that technically it's JScript being written/compiled, not JavaScript.)

Anyway, a few tidbits about SAPI:

On the LotusScript side of things, here's a slightly longer bit of sample code than before:

Sub Initialize
    Dim spVoice As Variant
    Dim voices As Variant
    Dim v As Variant
    Dim i As Integer
    Dim msg As String
    Set spVoice = CreateObject("SAPI.SpVoice")
    Set voices = spVoice.getVoices()
    For i = 0 To voices.Count-1
        Set v = voices.Item(i)
        Set spVoice.Voice = v
        msg = "Voice " & i & " is called " & v.GetDescription(0)
        Print msg
        Call spVoice.Speak(msg, 0)
    Dim fileStream As Variant
    Dim fileName As String
    Set fileStream = CreateObject("SAPI.SpFileStream")
    fileName = "C:\TestAudioOutputStream.wav"
    Call fileStream.Open(fileName, 3, False)
    Set spVoice.AudioOutputStream = fileStream
    Call spVoice.Speak("I got two. turn tables, and a microphone", 0)
    Call fileStream.Close
    Set spVoice.AudioOutputStream = Nothing
End Sub

Talking LotusScript (Friday, Aug 1)
[ permalink ] [ e-mail me ] [ ]

Here's a little Friday fun for you. Create a button in a Lotus Notes e-mail with the following code:

Sub Click(Source As Button)
    Dim voice As Variant
    Set voice = CreateObject("SAPI.SpVoice")
    Call voice.Speak("Would you like to play a game?", 0)
End Sub

Then send the e-mail to someone old enough to remember the movie War Games and get them to click the button.

For bonus points, use Tim Tripcony's event binding code to inject this into the PostOpen event of every view and form in a database.

NOTE: I'm not sure what actually installs the voice library (I think it might be MS Office correction: looks like it's on XP by default), so this may not work on your machine. It certainly won't work on a non-Windows machine. Sorry Mac and Linux guys.