Tuesday, November 20, 2007

Calling Exchange COM objects from a .NET web service

Suppose we have the following sample code (assuming you're using System.DirectoryServices and your project has references to System.DirectoryServices and CDOEXM):

string ldapPath="ldap://{DN to user object}";
string homeMDBUrl = "{DN to private exchange store}";
using(DirectoryEntry de = new DirectoryEntry(ldapPath)){
IMailboxStore mbx = (IMailboxStore)de.NativeObject;
mbx.CreateMailbox(homeMDBUrl);
de.CommitChanges();
}


Works fine when run from a fat client. But when we call it from an IIS-based app, it errors with:

Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))

What gives?

This is a generic COM error saying "I couldn't reach a resource you need" (or something close to that). The best bet is that logging in to the Exchange server failed.

Exchange COM objects make requests under the identity associated with the process, not the thread. When trying to call into Exchange via COM (gotten from the NativeObject property on the AD object in .NET), the following do NOT work:
  • setting the user via impersonation in web.config
  • setting the user of all websites in IIS mmc
  • setting the user of the specific website in IIS mmc
  • setting the user of IIS Admin / W3SVC services
There is only one way to effectively get it to work: the ASP.NET worker process must itself run as the user who has rights to touch Exchange. This can be set in machine.config within the tag like this:

<processModel username="{domain\userid}" password="{password}" />


Setting that properly causes the ASP.NET worker process to run as that user at the process level. All other overrides are at the thread level and do not work.

With the machine.config file altered and IIS restarted (yes, you have to iisreset for changes to take effect), calling the code above within a web service / web application should work assuming your other parameters are correct.

Thursday, March 8, 2007

HOWTO: Change a cascaded style in IE / Firefox / Opera

So you want to alter an HTML element's style dynamically. Seems simple enough on the surface -- just alter the .style property appropriately, right?

<a href='javascript:showElement("div2")'>click me</a>
<div id='div2' style='display:none'>This will show up!</div>

<script type='text/javascript'>
function showElement(id)
var el = document.getElementById(id);
if (el){
el.style.display = 'block';
}
}

</script>

You go test it, it works fantastic. You develop the rest of your page and complete it. So to do things properly, you move most of the style attributes into a CSS file instead of doing inline style definitions. So now you have:

css file:
.toggleme {
display:none;
}


page file:

<div id='div2' class='toggleme'>This will show up!</div>

You go back and test your page, but it doesn't work any more! No error, but the div doesn't show up either. What gives?

It turns out that most browsers handle the .style attribute of an element as meaning the attribute value directly from the html itself, instead of the cascaded value. IE uses .currentStyle and .runtimeStyle to renote the read/write properties for cascaded styles, while Firefox/Opera/etc uses the DOM standard of document.defaultView.getComputedStyle(). But we want something we can call that will just set the silly style regardless of browser and regardless of where the style is actually declared.

I wrote an open source framework for doing a fair amount of client-side manipulation that is browser independent. I call this Interactive Website Framework -- you can check it out at IWF on sourceforge. But for our needs, we really only need a single function (which I modified slightly to eliminate calls to other functions in the framework):

function iwfStyle(id, styleName, newStyle){
var el = document.getElementById(id);
if (!el) { return false; }
var ret = '';
if (typeof(newStyle) != 'undefined'){
// assigning new style
if (el.runtimeStyle){
ret = el.runtimeStyle[styleName] = newStyle;
} else {
ret = el.style[styleName] = newStyle;
}
} else if (el.currentStyle) {
// reading IE style
ret = el.currentStyle[styleName];
} else {
// reading DOM style
try {
var cs = document.defaultView.getComputedStyle(el,null);
ret = cs.getPropertyValue(styleName);
} catch(e) {
}
}
return ret;
}


Now if we change our showElement function to simply call iwfStyle, we're set:

<script type='text/javascript'>
function showElement(id)
iwfStyle(id, 'display', 'block');
}

</script>

So now the call will work regardless of browser or where the style is defined. Check out the full framework on sourceforge. It includes a client-side Xml parser, an Ajax abstraction layer, and some rudimentary gui enhancements, like animating elements, docking elements, drag-n-drop, etc.

HOWTO: Temporarily bypass connection limit - terminal server has exceeded max number of allowed connections

So you need to remote desktop into a Windows 2000/2003/XP/Vista box, but when you do you get the dreaded "terminal server has exceeded max number of allowed connections" error causing you to flail and try to contact all those you think *might* be connected. Which is a major hassle, especially when all you really need to do is touch one little thing and jump right out.

To see who's currently connected (from the command line of your local box):

C:\>qwinsta /server:[server name or ip here]
SESSIONNAME USERNAME ID STATE TYPE
console 0 Conn wdcon
rdp-tcp 65536 Listen rdpwd
jane.doe 2 Conn rdpwd
john.doe 3 Disc rdpwd


So you can see jane.doe and john.doe are both logged into the box. But john.doe is disconnected, so let's pick him to boot:


C:\>rwinsta /server:[server name or ip here] 3


Where the "3" is john.doe's ID. That should boot him off. If it doesn't, the alternative is to login to the console session. We can do this using a command line switch for the Remote Desktop client. Open a command prompt and run:


mstsc.exe /console


This tells Remote Desktop to try to connect to the console instance when you click Connect. This should allow you one more concurrent connection over the limit imposed by windows (usually 2). Happy Remote Desktopping!

HOWTO: Ubuntu Edgy Eft (6.10) + Ruby 1.8.5 + Gem 0.9.2 + Rails 1.2.2

There have been several excellent articles / blogs / etc explaining how to get the latest version (as of 2007-03-08) of ruby + gem + rails running on Ubuntu 6.10 Edge Eft, but no one resource met my needs to get me completely up and running.

So here's the various excellent resources I used to finally get ruby + gem + rails working on my ubuntu system:

Install ruby:
http://www.rubywizards.com/viewtopic.php?pid=19

Grab the gem source
http://rubyforge.org/frs/?group_id=126&release_id=9501

To Install gem:
tar -zxvf rubygems-0.9.2.tgz
cd rubygems-0.9.2
ruby setup.rb

If you get the zlib error, you probably need to get additional libs:
apt-get install zlibc zlib1g zlib1g-dev
(see http://www.nabble.com/Gems-zlib-problem-t992896.html for more info)

Re-compile and re-install ruby now that the new libs are there
http://www.rubywizards.com/viewtopic.php?pid=19

Make sure you're running the latest version:
ruby -v
ruby 1.8.5 (2006-08-25) [i686-linux]

if you still get the zlib error, copy the zlib over (this should be one line):
sudo cp /usr/lib/ruby/1.8/i486-linux
/zlib.so /usr/local/lib/ruby/site_ruby/1.8/i686-linux/

Great info about the zlib error in Ubuntu:
http://www.penlug.org/twiki/bin/view/Main/LinuxBookReviewsAgileWebDevelopmentwithRails

Then re-install gem:
ruby setup.rb

make sure gem works:
gem -v
0.9.2

Then grab rails:
gem install rails --include-dependencies --remote

make sure you're good to go:
rails -v
Rails 1.2.2


I hope this helps someone!