Archive for ‘.NET’

February 26, 2008

The elusive quest for fast remote desktop to my Mac laptop

I desperately didn’t want to pay the $199 for Timbuktu, but I finally gave in.  The quest was simple: find a reliable, fast way to remote into my MacBook laptop running Leopard from my desktop running Windows 2008, over a gigabit LAN.  The laptop sits next to me–I just want to use one keyboard.  The simplest features will do: I’m not looking for clipboard access across sessions, or file copying, or anything other than pure speed.  One keyboard, one mouse, 54" of screen real-estate, two OS’s and 12G of RAM between them.  Should be heaven, right?  It isn’t.

VNC is the first tool that pops up when starting on this quest.  As I’ve written before, VNC is a dog: it might feel great for people who are used to 56k modems, but I have watched movies from my Dell M90 across RDP on my desktop.  I want fast.

How do I define fast?  Well, I don’t need to watch movies, but when I run my mouse across the dock bar the icons should just…move.  No flickering, no stuttering.  Timbuktu manages to pull that off.

So I tried the canon of remote services: LogMeIn, GoToMyPC, and a handful of others.  LogMeIn, while free, took roughly 7 seconds to redraw my 17" laptop screen in a browser window.  GoToMyPC was the best after that, but still horridly chunky.

I then found Symantec’s PCAnywhere works with OS X.  The latest version (12.1) was priced just a little less than the Timbuktu solution.  I found a free trial of 12.0, downloaded, and failed on install in Win2k8.  I checked the usual suspects (Admin privileges, directory access), without success.

I found Bomgar (www.bomgar.com), but I didn’t have the heart in me to try a product that "starts at $1,988".  I’d rather just turn to my left and type on the MacBook keyboard…

It was my hope after reading some of the hurlyburly around RDP that I might find an alternative to Timbuktu, but nothing showed significant promise, not yet at least.  For now, Timbuktu will have to do, even though it hurts to pay for something I’ve used for free for years!

February 9, 2008

Not Happy with Mozy

header-mozy-logoAfter reading this post, I had to check my Mozy install on my desktop–sure  enough, it reported that it hadn’t run successfully in 5 days, and the error message was a "required update".  No other clues would have alerted me to failed backups (it doesn’t show any kind of visual indicator until 7 days have gone by).  I would have been extremely upset to discover that in a recovery effort. 

So, I downloaded and installed (it requires a reboot–seriously?  Aren’t we past that?), and now my hourly backup option is gone; it is at most 12 times a day, and on low CPU impact.  Not happy with Mozy.  I decided to look back at Carbonite–my first impressions two years ago (I backed up 30G in about a week) was that it was clunky, but it sounds like it has gotten better.  I participated in the Beta back in early 2006, but my beta account is no longer active (schucks!)

The install was pretty painless on Vista x64, which is great.  I now have to wait for quite some time before all my content is backed up.  For the time being, I’m still running Mozy, but the whole point of automated backups is to not have to worry–and I worry about Mozy.

February 9, 2008

Remoting into your Mac from a PC

I’ve been on a quest to find software that would make my MacBook even remotely usable from a PC.  Using VNC on my gigabit LAN can be compared with using RDP over a 1200 baud modem.  I’ve tried every conceivable configuration without getting any faster than "agonizingly-torpid".

I finally stumbled across Timbuktu.  It’s not free, and I think I vaguely remember this company from a decade ago for Windows/Unix remote access.  I signed up for the 14-day trial, and after a couple of weeks of dithering, finally installed.  It’s not perfect (it’s got an awfully aged UI), but it is definitely the best I’ve used so far in terms of responsiveness–running my mouse across the icon bar at the bottom is relatively smooth.  For the first time, I’ve considered my MacBook usable from my desktop.

But there’s a problem–it’s priced at $199!  I am having a VERY hard time seeing how I’d be willing to pay $199 for something that’s out of the box on Windows.  You have to buy a "two-pack" multi-platform license, and there’s just no way I could justify that.  Does anyone know of alternatives?  And before anyone suggests another flavor of VNC, I’ve tried them all.

January 17, 2008

Autonomy Search Developer Starter

So you’ve got an Autonomy IDOL in hand, and you’ve been asked to build a search application around it.  Here are some thoughts on getting started.

Let’s assume you’ve got the content in.  In a later post I’ll cover some of the fetches/connectors that you have access to, and what you can do with them.  For now, let’s start with a simple query.  Assume that the IDOL is installed on the server search, on port 9000.  Open your browser to:

http://search:9000/action=query&text=*

An installed IDOL listens on many ports: the default port of 9000 is where the IDOL Proxy Service sits and listens.  The response for an “action=query” is to return results that match the “text=” query.  By default, the response will contain up to 6 records, showing the default fields for each records (usually that includes a small subset of the metadata, and none of the content for each record), and will look something like this:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<autnresponse xmlns:autn="http://schemas.autonomy.com/aci/">
  <action>QUERY</action>
  <response>SUCCESS</response>
  <responsedata>
     <autn:numhits>6</autn:numhits>
     <autn:hit>
       <autn:reference>test_document.doc</autn:reference>
       <autn:id>1</autn:id>
       <autn:section>0</autn:section>
       <autn:weight>96.00</autn:weight>
       <autn:database>News</autn:database>
     </autn:hit>
    ...
  <responsedata>
</autnresponse>

Lesson #1: All meaningful Autonomy interaction is through URLs, and the response is typically in XML.  Some simple C# code to handle the response above would look like:

   1: XmlDocument xml = new XmlDocument();
   2: xml.Load("http://search:9000/?action=query&text=*");
   3:  
   4: XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
   5: nsmgr.AddNamespace("autn", "http://schemas.autonomy.com/aci/");
   6:  
   7: XmlNode node = xml.SelectSingleNode("/responsedata/autn:hit[1]/autn:reference", nsmgr);

The next step is to figure out how to issue queries that are more meaningful than text=*.  For that, we turn to Autonomy’s built-in help page.  You access it by–you got it–going to a URL:

http://search:9000/action=help

Lesson #2: Always have the help URL open on a monitor.  The HTML help that is displayed is the single best resource for questions; and ironically, it isimage not searchable.  Non-searchable help?  From a search company?  Yes.  Perhaps that was left intentionally as a challenge to the buyer to set up their first source…  In any case, your first friend will be the Query node, where you can find all sorts of helpful information on how to build the specific query you’re looking for.  Remember, unless your users are technical, it will most likely be your responsibility to “query cook”, accepting simplified input from your users and creating the complex URL that Autonomy needs.

In future posts, I’ll look at some of the specifics of the query URL, and how to see the impact in the logs.

May 11, 2006

EAP For Jetbrains DotTrace 2.0

Normally I see this hit the wires with a little more fanfare, but this just kinda showed up in one of the announce blogs I read: Jetbrains opened up the EAP for dotTrace 2.0. I love the dotTrace tool (as indispensable as Resharper is), it’s fantastically easy to use (seriously, point and click, no recompile/code changes needed). There are some attractive features up from the 1.1.2 release (with which I just spent the weekend, and learned some interesting things about System.Messaging)–from the notes:

  • Memory profiling support
  • CPU snapshot comparasion (sic)
  • Support for multiple snapshots
  • Collapsing recursive calls and blocks of filtered code

Among others–comparison! The weekend was partially as long as it was because I found it difficult to compare profiles of pre- and post-change snapshots. Just what the doctor ordered. And finally, memory profiling–not just CPU time. Perfect.

If you haven’t tried profiling your code, this is an easy way to start: download, install, open, point at your compiled exe or web app, and let it go. You will be surprised at what you see. Oh–and as to price, compared with the others I’ve used (notably DevPartner Studio) the price is right. Not quite NProf right, of course, but right enough.

June 27, 2005

CruiseControl.NET and Subversion Revision Numbers using NAnt

A while ago, I posted a simple stop-gap solution for retrieving Subversion revision numbers during a CruiseControl.NET build, and had hoped that functionality would shortly make it into a release.  Well, it hasn’t, and I have had to revisit this recently.  Here’s a better solution than the original (using Subversion 1.2.0):

  <echo message="Retrieving Subversion revision number"/>
  <property name="svn.revision" value="00"/>
    <exec
          program="svn.exe"
         commandline=’log "${project::get-base-directory()}" –xml –limit 1′
          output="_revision.xml"
          failonerror="false"/>
    <xmlpeek
          file="_revision.xml"
          xpath="/log/logentry/@revision"
          property="svn.revision"
          failonerror="false"/>
   <echo message="Using Subversion revision number: ${svn.revision}"/>

A little more generic, and much closer to the point–this one does a better job of getting the appropriate Subversion revision number.

September 12, 2004

NAnt, Subversion and VS.NET

I’ve been struggling for a while now with a block in Subversion, a well-known issue that is really quite annoying.  The proposed fixes work fine for various situations, provided that you remember to not create a web project in Visual Studio (or inherit them), or that you never use anything but TortoiseSVN (an incredibly nice tool).

I can’t do either.  While I could go through a number of web projects and patch them up, I can’t ensure that another developer won’t just start a new project that way.  And sure, using the TortoiseSVN client that has been modified to produce _svn folders (versus .svn) is convenient, but there’s a problem: using NAnt to bootstrap–either using the <exec> task, or the <svn-x> tasks from NAntContrib–will end up using the svn.exe, and the value of using the modified TSVN client is gone.

So, I poked around in the docs for TSVN, and found out that you can run the client from the commandline, TortoiseProc.exe.  So my bootstrap target now looks something like this:

<target name="bootstrap">
  <echo message="Updating from Subversion" />
  <if test="${directory::exists(‘_svn’)}">
   <echo message="Using TortoiseSVN"/>
   <exec program="c:program filestortoisesvntortoiseproc.exe"
     commandline="/command:update /path:. /notempfile /closeonend"
     basedir="${project::get-base-directory()}"
     failonerror="false"/>
  </if>
  <if test="${directory::exists(‘.svn’)}">
   <echo message="Using NantContrib SVN task"/>
   <svn-update destination="${project::get-base-directory()}" uri="svn://some-uri"/>
  </if>
</target>

Why the two approaches?  The build server does not have VS installed, and so the .svn folder issue will never come up.  On the development machine, though, it might be nice to test out changes to the bootstrap and build scripts before checking them in (seriously, test before checking in?)

I ran into a minor issue that I logged with the TSVN folks–the exec task has a return code of 1 even on success.  That’s why the failonerror=”false”.  I will post an update when I hear back about the issue.

August 11, 2004

SQL Server 2000: xp_sprintf and the 255 character limit

A while ago, I had written some code to log failed dynamic sql to a log table, for tracing and debugging purposes.  The code looks something like this:

exec sp_executesql @sql, …
if( @@error != 0 )
begin
   exec util_log_error ‘the name of the current stored proc’, 
         ‘Failed to perform some action: %s. 
          More data is available here: %s and here: %s, %s…’, 
          @sql, @moredata, @andmore, @etc, @etc
   return 1
end

The stored procedure “util_log_error” takes care of logging the message to the table, accepting up to 10 variables.  It wrapped master.dbo.xp_sprintf.  I finally found out why certain messages were being truncated–xp_sprintf has a maximum argument size of 255 characters (Found that in the BOL, did you?  No.  Not documented anywhere I could find.  Found it in Google groups)  Some of the dynamic sql we produce gets much larger than that, and it was being truncated.

So after googling unsuccessfully for a while, I decided before I wrote my own COM object to do this trivial task, and called it through the sp_OA procs, that I would look at some of the string functions to see if I could do the same in T-SQL.  In a moment of BOL clarity, I found a way.

It all starts with the STUFF function, a little gem I’ve never used and too often thought was useless.  A little proof of concept is in order:

declare @message varchar(1000),
   @arg1 varchar(400),
   @arg2 varchar(400),
   @repeat int,
   @count int,
   @local varchar(400)

select @message = ‘The first part: %s and the second part: %s’,
   @arg1 = replicate( ‘a’, 400 ),
   @arg2 = replicate( ‘b’, 400 ),
   @repeat = charindex( ‘%s’, @message ),
   @count = 0

while( @repeat > 0 )
begin
   select @count = @count + 1, @local = CASE @count
       when 1 then @arg1
       when 2 then @arg2
       end,
       @message = stuff( @message, @repeat, 2, @local ),
       @repeat = charindex( ‘%s’, @message )
end

print @message

Just keep adding when cases for each argument you might have.  And this could be made better.  Right now, xp_sprintf only supports ‘%s’ replacement.  I leave ‘%d’ support as an exercise to the reader–suffice it to say that I believe it starts with sql_variant, has SQL_VARIANT_PROPERTY( @arg, ‘BaseType’ ) in the middle, and ends with cast().  Say with me, “goodbye xp_sprintf!”

July 16, 2004

AD/AM, ASP.NET, C#, and “Unknown error (0×80005000)”: Keeping a stiff “upper” lip

They say it all boils down to security. It’s the account used by ASP.NET. It’s setting . It’s the way you set up ADAM.

It’s making sure that the ADAM user you are logging in with is a member of the Readers role.

It’s making sure that when attempting to create a System.DirectoryServices.DirectoryEntry, the ADAM username you are trying to bind with is the DN of the username, not the CN or anything else.

It’s making sure that when trying to create that DirectoryEntry to bind with an ADAM user, you set the AuthenticationTypes to None.

Yes, dear reader, it’s all of those. But, if like me you still find yourself with the “Unknown error”, and you’ve played with Reflector and walked through System.DirectoryServices, and googled “ADsOpenObject 0×80005000” and you’ve wept, and shaken your fist–keep going.

If you’ve ghosted your machine back to August 2003 to get rid of the Framework 2.0 beta you installed a few weeks back to play with Monad, and you still get the “Unknown error”, keep going.

If you’ve reinstalled ADAM twelve times, then created a fresh VMWare guest of 2003 with all the trappings, installed ADAM, run your code, and you still get the “Unknown error”, keep going.

When, after 24 hours of frustration, seditious thoughts of the quality of System.DirectoryServices.dll going through your head, you find yourself contemplating a switch to Linux, relax. I have an answer for you:

It’s “LDAP://”, not “ldap://”.

Yeah, I’m that serious.

So, here are the details. I created an ADAM instance with the following application partition:

CN=whywont,DC=this,DC=work

I then went in, and created a user:

CN=please tell me

which has the DN:

CN=please tell me, CN=whywont, DC=this, DC=work

I gave this user a password, and made sure to add it to the CN=Readers group, in the CN=Roles,CN=whywont,DC=this,DC=work container. I configured a virtual directory with in the web.config, only anonymous authentication enabled, and a low privilege account with access to ADAM as the login. Now for the code:

DirectoryEntry entry = new DirectoryEntry( “ldap://localhost:389/CN=whywont,DC=this,DC=work”,
CN=please tell me, CN=whywont, DC=this, DC=work”,
“password”,
AuthenticationTypes.None )

try
{
object adsi = entry.NativeObject ;

Result: Unknown error (0×80005000). But if you change the path to “LDAP://localhost…”, it works.

I’ve been speechless for nearly 2 hours now.

Follow

Get every new post delivered to your Inbox.