powershell
PowerShell V2 Add-AcceleratorType function
As I explained TypeAccelerators on IRC, Jaykul mentioned how cool it would be able to make your own,
I came up with a very simple Add-AcceleratorType function that makes this at least a bit easier ,
it works by creating a type with a New Method and you can give a name, returntype and the code to implement the new method, that function gives the ability to add a shortcut Type in PowerShell that allows you to call the new() method to create the object:
I made the Add-AcceleratorType function to do this , you need to add extra assemblies you need to the C# code :
Function Add-AcceleratorType ($name,[string]$type,$code) {
$code = @"
public class $name
{
public static $type New() {$code}
}
"@
Add-Type $code -ReferencedAssemblies System.DirectoryServices
}
# examples
Add-AcceleratorType rnd System.Random 'return new System.Random();'
Add-AcceleratorType Domain System.DirectoryServices.ActiveDirectory.Domain 'return System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain();'
Not as handy as a real type accelerator, but it is very helpful when working with long type names in PowerShell see the AD example
[System.DirectoryServices.ActiveDirectory.Domain]::.GetCurrentDomain()
or
[domain]::new()
even with PowerTab this shortcut helps a lot ;-)
Enjoy,
Greetings /\/\o\/\/
The Weekly Source Code 33 - Microsoft Open Source inside Google Chrome
First, let me remind you that in my new ongoing quest to read source code to be a better developer, Dear Reader, I present to you thirty-third in a infinite number of posts of "The Weekly Source Code."
That said, what does Microsoft Code have to do with Google Chrome, the new browser from Google? Take a look at the Terms and Conditions for the "Chromium" project up on Google Code. There are 24 different bits of third party software involved in making Chrome work, and one of them is WTL, the Windows Template Library, which was released as Open Source in 2004.
Chrome's use of the Open Source Windows Template LibraryWTL is distributed under the MS-PL or Microsoft Public License. This is a VERY relaxed license that basically says "have fun, and don't call if there's trouble." In the Open Source world, licenses like that make people smile.
WTL is a C++ library for Win32 development and is kind of like MFC (Microsoft Foundation Classes), but a lot more lightweight. It was originally worked on by Nenad Stefanovic as an internal thing at Microsoft that was then released as an unsupported sample. Nenad is still listed on the old SourceForge project.
WTL embraces ATL (Active Template Library) which is a series of C++ template classes made to make COM development easier. It was more or less patterned after the STL (Standard Template Library). You may remember that folks like Chris Sells were hard-core ATL wonks. Chris and Chris Tavares (of P&P fame) worked on the ATL Internals book.
WTL was well loved going back to 2002. There's a great post from back then by Simon Steele about The Joys of WTL. Simon says:
The Windows Template Library (WTL) is MFC on template-based steroids - after a successful stretch on the slimfast plan. WTL provides the user-interface frameworks that we need to write proper GUI applications without resorting to the bloated MFC or complicated pure Win32 API programming. A number of the "must-have" classes from MFC are also available as WTL utility classes too, welcome back your old friends CPoint, CSize, CRect and most importantly CString! WTL produces small executables that do not require the MFC run time libraries - in fact if you stay clear of the Visual C++ runtime functions (strcpy and friends) you can dispense with msvcrt.dll as well - leading to really small programs, which run fast too
Windows Template Library was released as Open Source over 4 years ago which is like 28 Internet years. May of 2004 was a long time. I didn't think Microsoft was doing much Open Source that far back, but it appears they were. In fact, back as far as April of 2003 there was talk on the WTL Yahoo Group by Pranish Kumar, then of the Visual C++ team, of trying to figure out how to get the product out into the community in a way that would let it live on.
History: How WTL Became Open SourceI had an IM chat today with Pranish Kumar about how WTL made it out of a 2004 Microsoft as an Open Source project. I'd also encourage you to check out both the Shared Source page at MSFT, the Open Source page, and most importantly, Port 25.
Here's part of my IM with Pranish about how WTL was released:
[WTL] was one of the first if not the first OSS things from Microsoft and it was a tough sell. There was a meeting with some bosses where we were presenting 3 potential OSS items. I guess it was the first "real OSS" with joint MS/Community involvement as opposed to just us posting something externally. WTL was the only one that got approved.
Me: Did it start the Shared Source Initiative?
Yes in the broader sense, I think we took the basis for the license/process from Win CE and a few other components which Microsoft made available (in some form) as shared source. They also looked at BSD and some other licenses.
It was a fascinating experience for many reasons. One of them was seeing the reaction of various Microsoft execs to the whole open source/shared source idea. There was a lot of concern about OSS = Linux, and questions on whether there was business value in us engaging
It's pretty amazing how our stance/attitude has changed, one of the reasons WTL got through is because we convinced management, it had a passionate community base and would really help us foster that base.
I check in on the community now and then (not as regularly as I'd like) and I'm always impressed how it's remained strong.
One of the reasons I wanted to work for ScottGu was because of Microsoft's always improving attitude about releasing source. It's a big company and sometimes moves slow, but more people "get it" now than before.
Digging InChrome uses abstraction libraries to draw the GUI on other non-Windows platforms, but for now, what sits underneath part of ChromeViews is good ol' WTL. Makes sense, too. Why not use a native library to get native speeds? They are using WTL 8.0 build 7161 from what I can see.
Chromium is a lot of code. The source tarball is over 400 megs, if you want to try to compile it yourself with VS2005. Let's try to look at a few tiny interesting bits, though. You can check out their "Build Bot" if you like, and watch the development on the Linux and Mac Versions as they progress each day.
In some places, Chrome uses WTL for little stuff, like macros. For example, in the Chrome AeroTooltipManager, GET_X_LPARAM is a macro:
...snip...if (u_msg == WM_MOUSEMOVE || u_msg == WM_NCMOUSEMOVE) {
int x = GET_X_LPARAM(l_param);
int y = GET_Y_LPARAM(l_param);
if (last_mouse_x_ != x || last_mouse_y_ != y) {
last_mouse_x_ = x;
last_mouse_y_ = y;
HideKeyboardTooltip();
UpdateTooltip(x, y);
}
...snip...
In other places, they rely on it more, like in text_field.cc that includes atlcrack.h. These are not drugs, mind you, but rather "message crackers" to help get at, and react to, the information inside Window Messages. These are used to create a "message map" of all the events you're interested in. These are macros that expand into an obscene amount of code. They are exceedingly handy.
// CWindowImplBEGIN_MSG_MAP(Edit)
MSG_WM_CHAR(OnChar)
MSG_WM_CONTEXTMENU(OnContextMenu)
MSG_WM_COPY(OnCopy)
MSG_WM_CUT(OnCut)
MESSAGE_HANDLER_EX(WM_IME_COMPOSITION, OnImeComposition)
MSG_WM_KEYDOWN(OnKeyDown)
MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
MSG_WM_LBUTTONUP(OnLButtonUp)
MSG_WM_MBUTTONDOWN(OnNonLButtonDown)
MSG_WM_MOUSEMOVE(OnMouseMove)
MSG_WM_MOUSELEAVE(OnMouseLeave)
MSG_WM_NCCALCSIZE(OnNCCalcSize)
MSG_WM_NCPAINT(OnNCPaint)
MSG_WM_RBUTTONDOWN(OnNonLButtonDown)
MSG_WM_PASTE(OnPaste)
MSG_WM_SYSCHAR(OnSysChar) // WM_SYSxxx == WM_xxx with ALT down
MSG_WM_SYSKEYDOWN(OnKeyDown)
END_MSG_MAP()
They also use some handy helpers that are C++ classes around Windows structures. For example, the Windows POINT structure is a class in WTL called CPoint. The class actual derives from the struct. Lots of interesting stuff in there, and WTL is at a pretty low level helping out and keeping things tidy.
Now, moving on to something I found fascinating because it's not documented and may or may not have required some disassembling to accomplish.
Chrome's Odd Use of Data Execution PreventionThis part isn't explicitly about use of open source, but it's darned interesting. This is part of Chrome's WinMain(). It's long, but check out a few interesting bits. First, the big if/else at the beginning. They look at the command line and determine if they (the EXE) are one of three flavors...either a Renderer, a Plugin [host] process, or the Browser process. Notice that they have DEP (Data Execution Prevention) turned on for the Renderer and main Browser, but have to enable ATL7 thinking because there are plugins that weird build in older ways still out there. They are ultimately calling SetProcessDEPPolicy and passing in a flag to enable DEP, as well enabling ATL7 compiled processes. From MSDN help:
"Disables DEP-ATL thunk emulation for the current process, which prevents the system from intercepting NX faults that originate from the Active Template Library (ATL) thunk layer."
These new APIs were added in Vista SP1, Windows XP SP3 and WIndows 2008. Why is ATL special cased? From Michael Howard:
"Older versions of ATL, and by older I mean pre-Visual C++ 2005, used dynamically generated code in small isolated cases. Obviously, without the appropriate APIs this is going to cause problems on a DEP-enabled computer, because you can't execute data. This code is referred to as a "thunk" and versions of ATL in VC++ 2005 and later work correctly with DEP."
Some plugins that might run in a Chrome sandboxed process might be compiled in this way, so that process has a different security DEP setting than the others.
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev_instance,wchar_t* command_line, int show_command) {
// The exit manager is in charge of calling the dtors of singletons.
base::AtExitManager exit_manager;
// Note that std::wstring and CommandLine got linked anyway because of
// breakpad.
CommandLine parsed_command_line;
std::wstring process_type =
parsed_command_line.GetSwitchValue(switches::kProcessType);
const wchar_t* dll_name = L"chrome.dll";
if (process_type == switches::kPluginProcess) {
// Plugin process.
// For plugins, we enable ATL7 thunking support because we saw old activex
// built with VC2002 in the wild still being used.
sandbox::SetCurrentProcessDEP(sandbox::DEP_ENABLED_ATL7_COMPAT);
} else if (process_type == switches::kRendererProcess) {
// Renderer process.
// For the processes we control, we enforce strong DEP support.
sandbox::SetCurrentProcessDEP(sandbox::DEP_ENABLED);
} else {
// Browser process.
// For the processes we control, we enforce strong DEP support.
sandbox::SetCurrentProcessDEP(sandbox::DEP_ENABLED);
}
...snip...
}
When you dig into their use of DEP, notice this interesting comment, as they try to get DEP working under Windows XP SP2 and Windows Server 2003 SP1. They are using the totally unsupported technique outlined in this article from 2005 to try to turn on DEP. If you try to call this on Vista you'll get back STATUS_NOT_SUPPORTED, of course. ;) There's an official Vista API, and that's SetProcessDEPPolicy.
As an side, and interestingly enough, this undocumented API has been added as a patch just last week to WINE (Windows Emulation) for those who try to emulate Windows under Linux, but outside a VM.
Note the most interesting comment in the method:
"// Completely undocumented from Microsoft. You can find this information by
// disassembling Vista's SP1 kernel32.dll with your favorite disassembler.
enum PROCESS_INFORMATION_CLASS {
ProcessExecuteFlags = 0x22,
}"
Looks like The Chromium authors may have disassembled part of the Windows Kernel in order to achieve this security feature under Windows XP SP2. Probably not cool to do that, but they're clearly doing it for good and not evil, as their intent (from reading their code) is to make their browser safer under XP SP2 and prevent unwanted code execution.
This internal and totally unsupported API is in the Microsoft Windows Internals 4th Edition, Chapter 6, on download.microsoft.com (PDF). It's also mentioned in a Microsoft Research PowerPoint (PPTX). An architect on the Windows Kernel team point out in a forum posting that this was internal:
"I want to stress as a disclaimer that NtSetInformationProcess, class ProcessAccessToken, is an undocumented and unsupported infterface. It is reserved for system component use and is subject to change between operating system releases"
You can see the dance Chrome does below or on their source site. They poke around looking for a method that does what they want, using GetProcAddress:
namespace sandbox {namespace {
// These values are in the Windows 2008 SDK but not in the previous ones. Define
// the values here until we're sure everyone updated their SDK.
#ifndef PROCESS_DEP_ENABLE
#define PROCESS_DEP_ENABLE 0x00000001
#endif
#ifndef PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
#define PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION 0x00000002
#endif
// SetProcessDEPPolicy is declared in the Windows 2008 SDK.
typedef BOOL (WINAPI *FnSetProcessDEPPolicy)(DWORD dwFlags);
// Completely undocumented from Microsoft. You can find this information by
// disassembling Vista's SP1 kernel32.dll with your favorite disassembler.
enum PROCESS_INFORMATION_CLASS {
ProcessExecuteFlags = 0x22,
};
// Flags named as per their usage.
const int MEM_EXECUTE_OPTION_ENABLE = 1;
const int MEM_EXECUTE_OPTION_DISABLE = 2;
const int MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION = 4;
const int MEM_EXECUTE_OPTION_PERMANENT = 8;
// Not exactly the right signature but that will suffice.
typedef HRESULT (WINAPI *FnNtSetInformationProcess)(
HANDLE ProcessHandle,
PROCESS_INFORMATION_CLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength);
} // namespace
bool SetCurrentProcessDEP(DepEnforcement enforcement) {
#ifdef _WIN64
// DEP is always on in x64.
return enforcement != DEP_DISABLED;
#endif
// Try documented ways first.
// Only available on Vista SP1 and Windows 2008.
// http://msdn.microsoft.com/en-us/library/bb736299.aspx
FnSetProcessDEPPolicy SetProcDEP =
reinterpret_cast<FnSetProcessDEPPolicy>(
GetProcAddress(GetModuleHandle(L"kernel32.dll"),
"SetProcessDEPPolicy"));
if (SetProcDEP) {
ULONG dep_flags;
switch (enforcement) {
case DEP_DISABLED:
dep_flags = 0;
break;
case DEP_ENABLED:
dep_flags = PROCESS_DEP_ENABLE |
PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION;
break;
case DEP_ENABLED_ATL7_COMPAT:
dep_flags = PROCESS_DEP_ENABLE;
break;
default:
NOTREACHED();
return false;
}
return 0 != SetProcDEP(dep_flags);
}
// Go in darker areas.
// Only available on Windows XP SP2 and Windows Server 2003 SP1.
// http://www.uninformed.org/?v=2&a=4
FnNtSetInformationProcess NtSetInformationProc =
reinterpret_cast<FnNtSetInformationProcess>(
GetProcAddress(GetModuleHandle(L"ntdll.dll"),
"NtSetInformationProcess"));
if (!NtSetInformationProc)
return false;
// Flags being used as per SetProcessDEPPolicy on Vista SP1.
ULONG dep_flags;
switch (enforcement) {
case DEP_DISABLED:
// 2
dep_flags = MEM_EXECUTE_OPTION_DISABLE;
break;
case DEP_ENABLED:
// 9
dep_flags = MEM_EXECUTE_OPTION_PERMANENT | MEM_EXECUTE_OPTION_ENABLE;
break;
case DEP_ENABLED_ATL7_COMPAT:
// 0xD
dep_flags = MEM_EXECUTE_OPTION_PERMANENT | MEM_EXECUTE_OPTION_ENABLE |
MEM_EXECUTE_OPTION_ATL7_THUNK_EMULATION;
break;
default:
NOTREACHED();
return false;
}
HRESULT status = NtSetInformationProc(GetCurrentProcess(),
ProcessExecuteFlags,
&dep_flags,
sizeof(dep_flags));
return SUCCEEDED(status);
}
} // namespace sandbox
It's a really interesting read and there's a lot of stuff going on in the comments, like TODOs, HACKs, and the like. All the stuff you'd expect to see any application of significant size. Funny, it's been at least 5 years since I've thought about C++ deeply. And to think I used to do all this -> stuff full time for money!
There's lots more to see. Check out the About Box version checks where they were blocking on Vista SP1 with UAC disabled. Also, the Threading stuff is interesting as they have a Thread Class that was ported to Mac and Linux. Finally check out Pickle.cc, as they serialize objects by "pickling them." Pickle is serialization for Python, and this looks like they're serializing between C++ and Python, and this is a C++ implementation of Pickle.
Back on WTL, you can download the final MS release of WTL 7.1 at Microsoft Downloads if you're interested. However, the more interesting release is the 8.0 release from June of 2007. This was the most recent release from the community! WTL 8 includes full support for Vista!
I think it's great that Microsoft is releasing more and more code in either Shared Source, Reference Source, or my favorite, Open Source as MS-PL. The fact that Google was able to use it, even this small part, really speaks to the spirit of Open Source.
Related Links
- WTL on Code Project by Michael Dunn
- Part I - ATL GUI Classes
- Part II - WTL GUI Base Classes
- Part III - Toolbars and Status Bars
- Part IV - Dialogs and Controls
- Part V - Advanced Dialog UI Classes
- WTL Yahoo Gruop - Still Active with 4500+ members
- WTL SourceForge Project
© 2008 Scott Hanselman. All rights reserved.
PoshCode OpenSearch
Well, an interesting comment came up today that the new version of PoshCode.org that we’re working on should support OpenSearch and of course, me being me, I said: oh, OpenSearch is easy, gimme a minute…
And three hours later, I’m going to bed.
However, I did manage to add paging support so you can “browse” the repository, and of course … to add OpenSearch. If you visit the repository with an OpenSearch aware browser, like say … Firefox 3, or IE 7, you’ll get a little glowing notification on your search bar that there is a search engine available. You can quickly add PoshCode’s search to your browser with a couple of clicks, and in no time flat you’re searching for PowerShell script.
Incidentally, I also hooked the OpenSearch stuff up to our API output, so OpenSearch aware apps which do not simply render the HTML page can get RSS output that should work for you. We’re not doing all of OpenSearch at this point, but I think the important bits are there (certainly the bits supported in your web browser are).
Feedback is welcome as always, let us know what you think of the new stuff by emailing feedback at poshcode …
The .NET Framework and the Browser's UserAgent String
One of the things I'd said I'd do, Dear Reader, when I went to work for the Big Blue Monster, was to get your feedback into The Company whenever possible. Here's another opportunity for us to effect change, however small.
A while back I made a little site called http://www.smallestdotnet.com that would look at your Browser's UserAgent
and let you know the size that the latest .NET Framework would be for you (ballpark size). In the process I've gotten to see a LOT of interesting Browser UserAgents in the IIS logs.
If you visit the site and scroll down, you'll see YOUR Browser UserAgent at the bottom. Here's mine:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.21022; Media Center PC 5.0; Zune 2.5; MS-RTC LM 8; .NET CLR 3.0.30618)
Notice that I've got IE8 on 64-bit Windows. However, there's other stuff in there, like I have the Zune software, I have Media Center enabled, and I've got three versions of the .NET Framework. In this example, 2.0, 3.0, and 3.5.
Here's a UserAgent that showed up today on http://www.smallestdotnet.com:
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.0.3705; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 1.1.4322; .NET CLR 3.0.04506.590; .NET CLR 3.5.20706; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; Zune 2.5; WWTClient2; MS-RTC LM 8; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Now, this guy is clearly a developer who has installed beta versions of things, but he's also got InfoPath and a bunch of other stuff. Still, that's a pretty crazy UserAgent and it's being transmitted all the time.
UserAgents are added for IE in the Registry, as seen in the screenshot above.
Why Should You Care?In the case of a system with IE and a lot of .NET Framework versions, ASP.NET currently truncates the UserAgent at 256 characters so my own case, the site was only getting part of the story. They might change that truncation number, but ultimately, I think we all want tidy UserAgents, right?
UserAgent length matters. Early versions of FireFox had a UserAgent Limit of 127 characters and used to return null before the bug was fixed last month and now it truncates. The FireFox plugin added when you installed .NET by default only shows the most recent .NET Framework. Do you want that functionality in .NET?
Truncated UserAgents can also mean you might get "Unknown" Back from Request.Browser.Browser. In my case, I was getting an exception from Request.Browser.ClrVersion because the truncated CLR Version was something like ".NET CLR 3.".
There's some people looking at this internally, and there's three groups involved. There's Internet Explorer, involved peripherally, there's the CLR Team and the installer that adds the values, and there's the ASP.NET team who cares because of the server-side sniffing.
Poll/Questions
The questions I have for you are these:
- Do you use these .NET Framework-specific values? What for? How do they improve your site or make your user experience different?
- If the .NET Framework-specific values were removed completely what would that mean to you or your business?
- What if the values were conflated to show just the most recent .NET Framework?
- Could you get the information you needed using just the value of the latest version?
- What if the values were conflated to show just the major side-by-side CLR releases?
- For example, 1.x, 3.5SP1 and 4.0. In that example, 3.5SP1 implies 2.x and 3.0. If you just had 2.0, you'd see 1.x, 2.0, and that'd be it.
- Could you get the information you needed using just the value of the those major CLR/Framework versions?
Please take a moment and do this micropoll. It's ONE question with ONE vote button. Literally two seconds of your time. You can also add the poll to your blog. Also, leave comments and I'll make sure the right people seem them.
© 2008 Scott Hanselman. All rights reserved.
Solo Long Cross-Country
One of the biggest accomplishments in getting your private pilot's license is the "Solo Long Cross-Country." It marks the home-stretch of a lot of training, practice maneuvres, landing drills, and solo flights of increasing complexity.
This flight is where it all comes together: 150 nautical miles total, landing at a minimum of 3 airports, with one leg at least 50 nautical miles.
I planned this flight as a tour of the San Juans and airports I have never been. It took me from Renton (RNT,) to Skagit Regional (BVS,) through Orcas Island (ORS,) Friday Harbor (FHR,) Sequim Valley (W28,) and then finally back to Renton.
Cross-country flights all begin with flight planning, and plenty of it.
Once you've drawn your intended route on the sectional chart (making sure to avoid those pesky restricted areas and military operation areas,) you identify (and plan for) checkpoints that fall every 30 miles or so. For each leg of your journey, you calculate the true direction and distance between each checkpoint. You factor in the magnetic deviation for the area (roughly -18 degrees for most of Western Washington,) and then account for the current atmospheric winds. This gives you a magnetic heading by which you can navigate. Add in the distances and estimated ground speed, and you get a navigation method known as "Dead Reckoning."
Dead Reckoning isn't usually the primary form of navigation, however. The modern aviation world is filled with navigation beacons that help you travel along specific paths from beacon to beacon. These are known as VOR Radials. During your preparations, you identify helpful VOR radials and frequencies, and then account for them in your flight plan.
Finally, you research the airports you plan to land at (and some that you don't) for the communication frequencies, runway information, and traffic patterns. Once you've done all that, a completed flight plan looks something like this:
I had originally planned to leave at 9:00 AM on Saturday, but low clouds kept me hampered in for the better part of the morning. Even once the clouds had lifted at Renton, the Orcas Islands were still covered by fairly low cloud.
Once the clouds finally lifted, I departed to the north. I had originally planned use one of Paine Field's VOR radials for much of my journey, but fly over their airspace as to not interfere with traffic there. Clouds kept me below the 4500 feet that I would have needed, so I called Paine Field and got clearance to transition over the field. I followed the radial to Skagit Regional airport, notched up my first landing of the day, and checked off the requirement for a leg of 50+ nautical miles.
The next checkpoint was Orcas Island. I had originally planned to enter the airport from the north of the island, but the weather favoured a northerly landing. I circled, and instead entered the harbour from the south -- easily the prettiest approach of the day.
The landing went smoothly, so I departed and headed to my next destination. Here's a picture of the Orcas Island airport as you leave:
The next landing was at Friday Harbor, a runway I had heard was slightly challenging due to its slope. It proved to be uneventful, so I parked in transient parking and made my way down to the harbour for lunch.
I found a great place right on the harbour -- Downriggers -- and enjoyed an awesome grilled crab and cheese sandwitch. It was also the most expensive meal I had ever had. The bill wasn't so bad, but the commute sure was a killer :)
After leaving Friday Harbor, I climbed to 5,500 ft to fly across the largest span of the journey. Climbing to 5,500 feet gives a glide distance of about 15 nautical miles -- enough to safely make it back to shore should the engine fail part-way.
Once I found Sequim, I got to enjoy my most challenging landing ever. Sequim Valley airport is 40 feet wide, much thinner than the 100-150 feet most regional airports offer. My initial pass at the traffic pattern was much too tight, so I spaced myself again and landed well on the second attempt.
After a short-field takeoff from Sequim Valley, I hugged the coast to avoid a small chunk of prohibited airspace over the Navy's submarine base at Bangor, Washington. I followed that path until I hit my planned VOR radial for the SeaTac airport, and followed that toward Vashon Island.
As you approach Vashon Island, SeaTac airport becomes quickly evident, as does downtown Seattle.
In the left picture, Seattle's Control Tower is about 25% from the left of the picture, about half-way down. Seattle's runways are nearly perpendicular to you at this point.
As you approach Vashon, you contact Seattle Tower to request a transition across their airspace. Transition across this class of airspace is much more restrictive, since it handles such heavy traffic. They give you an exact altitude to fly (usually 1500 feet,) and ask you to cross over the approach-end of the runway. As you cross the runways, you'll continue to see large commercial jets land below you. Since they are landing, you still have 1/4 mile of vertical separation between you. A typical crossing looks like this. It's amazing how simple and clean it looks when you're not battling lineups, security, and crowds.
After crossing the Seattle airspace, you get told to head toward downtown Kent. After a short while, they release you from their radar service, and it's back to landing at Renton. At the end of a 4-hour flight, I had no clue what was in store for me.
After transitioning through the SeaTac airspace and getting to downtown Kent, I called Renton with my intention to land. They told me to come straight-in for runway 33 (basically North,) and that I was clear to land. They asked me to report when I was 2 miles from the end of the runway. As I reported, they said that I was #3, clear to land. I had not heard anybody else talking with the tower or being cleared to land, so I clarified "#3 clear to land?" A second controller corrected that I was #2 clear to land. Still not a surprise you want to get on your final approach. They told me I had traffic at 12:00 on (obviously short) final approach, which I found.
At this point, I’m making the final adjustments, adding the final notch of flaps, watching airspeed, and we’re about 1 mile out.
As I get closer, the traffic ahead of me still hasn’t landed, and still hasn’t started rolling down the runway. In fact, they appear to be stationary on the end of the runway, and at this point I thought I might have lost the original traffic and was instead watching somebody who had stumbled onto the runway in the midst of an incursion. After reflection, I now think that we were on exactly the same glide-slope – causing little-to-no relative movement between us.
As I was now about ½ mile from the threshold (later confirmed by my GPS log,) this was much too close for comfort. I told the tower that we were too close, and started to make a tight spacing turn. The tower got upset, and said that they only had to give 3500 feet of spacing (although ½ mile is 2600 feet by my calculations.) He had somebody on downwind (parallel the runway, about 1 mile east of it, heading toward me) make a left turn for safety, as I did the same. We both saw each other, and fortunately had plenty of room between us. My diversion to the right, and the left turn after that are the first crags in the bottom part of the graphic below:
He then told me to not turn at all, and started to lose control as I complied. These directions left me heading toward the right, so he finally yelled, "What do YOU want to do?" to which I said that I would be doing a "go around" toward the east channel (the upper-right body of water.) After doing that, I entered the traffic pattern like usual (the loop right, and downward,) and then landed uneventfully.
All-in-all, several errors compounded themselves, but it seems to have started with ATC trying to sequence traffic too tightly together. My initial reaction to do a clearing turn was was stupid of me, and was my first Pilot Error. I have no qualms about the decision I made, but do regret the way I decided to do it. I should have just done a go-around – a spacing turn toward the downwind-final direction was dangerous, and easily could have caused problems.
I completed my landing, post-flight checklists, and headed back to base -- completing a huge milestone in my flying journey. Over the next few weeks, I'll be studying like crazy to prepare for the knowledge test and oral grilling that the official flight examiner will give me. Once I feel ready, I'll complete the last 5-or-so hours of practical flying practice and go for my official check ride!
Microsoft IE8 and Google Chrome - Processes are the New Threads
I happened to install Google Chrome (Alpha) the same day I installed Internet Explorer 8 (Beta). I noticed immediately, as I'm sure many of you have, that both browsers isolate tabs in different processes.
Unix folks have known about the flexibility of forking a process forever. In Unix, fork() is just about the easiest thing you can do. Also, fork()ing in Unix will copy the whole process and all variables into a new space. Everything after the fork happens twice. Multitasking made easy.
In Windows, you call CreateProcess() and you don't get a copy or clone. You just start up a whole new universe, starting from the very beginning - NOT from the call to CreateProcess().
What processes in Windows and Unix do have in common is that they each get their own protected virtual memory space. They are all alone and isolated. If a process crashes it's less of a crisis than if a thread within a process crashes.
(In .NET, AppDomains are like mini-processes, but they just aren't as completely isolated as a process is, so you can still bork an AppDomain enough that the whole process dies.)
Why does all this matter? Well, back in the day, most folks on Windows would recommend that developers interested in multi-tasking use threads. There's even been talk about fibers (really tiny threads within threads...like superstrings ;) ) However, darnnit, processes are easy.
Ah! But they're slow! They're slow to start up, and they are slow to communicate between, right? Well, kind of, not really anymore. There's this thing called Moore's Law that keeps marching on. Making a new process and talking to it in any of the myriad IPC (Inter-process Communication) methods available just isn't that much of a problem these days. Just open up Process Explore and enter "Tree View" sometime to see how many programs you use every day are actually multiple .exe's working together.
You can learn more about IE8 and how their multiple-process model works in both IE7 and IE8. (IE7 had this process isolation feature also...except one tab per security zone.)
You can learn more about Chrome and how they talk between their multiple "Render" processes in this architectural overview. They are using named pipes if you were wondering how Chrome talks to itself.
Tab/Process IsolationI'll open up an instance of IE8 and open one tab with cnn.com and other with hanselman.com. I'll do the same with Google Chrome. Here's what Process Explorer shows.
Why are some of the processes brown? Those are jobs, a new kind of process added in Windows 2000. Jobs are made with CreateJobObject and AssignProcessToJobObject. You can also get a Job using CreateProcess as unless you specify the CREATE_BREAKAWAY_FROM_JOB flag. Jobs in Windows can be controlled as a group and resource limits can be set on them. You can learn more about Jobs and why they can be more secure up on MSDN.
Crash ProtectionThe whole point of having more than one process for a browser is for crash protection. I've had every browser I've ever used crash in one tab while I was hoping to keep my other 49 tabs open.
Let's blow away some processes manually and see what the browsers do. I'll blow away the non-job process for Chrome.exe.
Looks like that process hosted Flash. See how the Flash object has been replaced on the cnn.com home page with a sad puzzle piece? Cool. Chrome hosts plugins in their own process also.
Lets blow away another Chrome.exe process. Ah, looks like that particular process was rendering hanselman.com. It's been replaced by a sad-page icon.
_3.png)
OK, let's blow away an IE8 process....
Ah, looks like the FIRST time a page crashes in IE8, it dumps the process, the tab disappears, then the tab comes back automatically to try to put the user where they were before. I'll kill the new process...
Looks like IE8b2 will only try a few times to automatically restore the bad tab then it gives up and gives its equivalent sad-tab and says "the website continues to have a problem." Also cool. This beta includes an option to turn "automatic crash recovery" off or on.
If the parent process dies (or, in this case, I kill it myself!) then I'll get a dialog from IE8 offering to restore the last session.
I'll get this similar message in Google Chrome.
Very cool. Now I have two browsers that I can open up a buttload of tabs in and not worry about maxing-out process limits or having one bad tab messing up the whole bunch.
PS: If you are poking around in Chrome, try visiting pages like: "about:network", "about:stats", "about:dns" and "about:memory"
© 2008 Scott Hanselman. All rights reserved.
PowerShell 'Suggestion Mode'
One bit of feedback we frequently get is that PowerShell's learning curve has some steeper bumps than we would like. Or simply, is strongly affected by habits learned from other languages or shells.
Interestingly enough, many of these problems aren't new to us -- we just don't have a good way (aside from help) of exposing them to the user. This was something I touched on in the footnotes of a blog in 2005, and started implementing personally shortly after that. Here's an example of its output:
[C:\temp]
PS:14 > "c:\temp\has space\test.ps1"
c:\temp\has space\test.ps1
Suggestion: Did you mean to run the command in quotes? If so, try using & "<command>"
The core of this is implemented by a script, Get-TrainingSuggestion.ps1. It retrieves the last item from your history, and runs a bunch of regular expression comparisons against it. If it finds a match in the list of training rules, it outputs the suggestion that corresponds to that rule.
################################################################################ Get-TrainingSuggestion.ps1
## Retrieve a training suggestion (if applicable) for the last command
## you typed.
##############################################################################
$history = get-history -Count 1
$suggestions = @{
"/\?"="To get help on a topic, use -? instead of /?.`nAlternatively, use get-help <command>.";
".length"="Try using the .Count property instead of the .Length property. Although .Length " +
"often works, .Count is the more consistent way to get the number of objects in a collection.";
";[ \t]*$"="Semicolons are not required as line terminators in PowerShell. Try your command without one.";
"Regex.*]::Match"="PowerShell's -match evaluator is much more efficent than calling it through the .NET API.";
"^`".*`"$"="Did you mean to run the command in quotes? If so, try using & `"<command>`"";
"start "="Are you trying to run the program associated with that path? If so, try invoke-item <path>";
"%.*%"="To access environment variables, try `"`$env:variable`" instead of `"%variable%`"";
"ren[^ ]* [^ ]+ .*:\.*"="Rename-item takes only a name as its second argument. Unless you want the " +
"name to have those path characters, do not include them.";
"dir.*/s.*"="To get a recursive directory listing, try `"dir . * -rec`".";
"dir.*/ad"="To get a list of directories, try `"dir | where { `$_.PsIsContainer }`""
"^get-childitem.*/s.*$"="To get a recursive directory listing, try `"get-childitem . * -rec`".";
"^grep"="To search files for text patterns, use the match-string cmdlet.";
}
$helpMatches = ""
if($history)
{
$lastCommand = $history.CommandLine
## Get the suggestions from the baked list
foreach($key in $suggestions.Keys)
{
if($lastCommand -match $key)
{
$helpMatches += "`nSuggestion: " + $suggestions[$key]
}
}
}
$helpMatches
To use this, simply update your PROMPT function to call Get-TrainingSuggestion.ps1.
function prompt
{
$suggestion = Get-TrainingSuggestion
if($suggestion)
{
Write-Host $suggestion
Write-Host
}
"PS >"
}
PowerScripting Podcast - Episode 40
Cisco is now a qualified IP PBX for Direct SIP with OCS 2007
The following versions of Cisco Unified Communications Manager has been qualified for Direct SIP integration with Microsoft Office Communications Server 2007 (It has been working with some restrictions for quite a while, but is now a tested and “qualified” solution)-
4.2[3]sr3a, 5.1.3.3000-5 & 5.1.3.1000-12 and not least 6.1.1.3000-2
Note that interoperability requires the August 2008 Update Package for OCS 2007 as described in KB952780 and also KB952783 although the latter it is not listed on the UC OIP page. KB957280 is for the Mediation Server role and KB952783 are for all the other roles (Automatically delivered through Microsoft Update). Also the Office Communicator 2007 client update KB954439 is required according to KB957285 (This upgrade currently has to be requested directly through PSS).
The fixes (that we have been waiting for quite a while) allows you to select to break some of OCS 2007 RFC 3966 compliant use of E.164 numbers for interoperability with “certain” PBXs (Read Cisco but it may also apply to other vendors) that do not correctly use or understand the + sign in a E.164 number.
Following are the changes as explained in KB92785 “Outgoing calls from Communications Server 2007 Mediation Server may not be routed correctly” -
By default, Microsoft Office Communications Server 2007 Mediation Server uses a plus sign (+) to prefix E.164 numbers in the Request Uniform Resource Identifier (URI) for outgoing calls. However, certain private branch exchanges (PBXs) do not accept numbers that are prefixed by using a plus sign (+). Therefore, an outgoing call may not be routed correctly. Additionally, the "From" headers for incoming calls from certain PBXs do not comply with Requests for Comments (RFC) 3966, "The tel URI for Telephone Numbers." In this case, Office Communicator does not resolve the number to the correct user.
To make sure that Mediation Server operates correctly together with PBXs, update 952780 adds a new Mediation Server configuration file setting for Communications Server 2007. This configuration file is called RemovePlusFromRequestURI, and it contains one of two settings, YES or NO. If your PBX does not accept numbers that are prefixed by using a plus sign (+), the setting in the configuration file should be YES. The YES setting causes Mediation Server to remove the plus sign (+) from a Request URI for outgoing calls. It also removes the plus sign (+) from the "To" header and the "From" header. If the configuration file setting is set to NO, Mediation Server will not change the Request URI, the "To" header, or the "From" header.
Note that you will have to manually force the Mediation Server to strip of the + sign using the intelligently named configuration file “RemovePlusFromRequestURI”.
Update 952783 introduces functionality for Communications Server 2007 to remove the plus sign (+) from the "From" header when it is not E.164-compliant. If this action does not create an E.164-compliant number, Communications Server 2007 introduces a "P-Asserted-ID" header that has a phone-context value of "enterprise." This header enables the user lookup functionality in Communicator 2007. Additionally, Communications Server 2007 bypasses the server normalization logic if the header contains a phone-context value of "enterprise."
It’s good to see the list of Qualified PBXs expanding; now we can only hope that the Dual Forking scenarios will follow troop with Cisco and all the other vendors who has promised to deliver Interop (E.g. Alcatel, Avaya, Ericsson, Mitel, NEC and Siemens).
Hate Add-Member? (PowerShell's Adaptive Type System to the Rescue)
Do you hate Add-Member as much as I do?
Wait - maybe you aren't familiar with Add-Member or the glory of PowerShell's Adaptive Type System. (ATS). When I looked at the .NET type system, my reaction was "....almost". I'm not trying to throw a rock at .NET - anyone that knows me knows how much I love .NET but the reality is that it's type system "almost" meets the needs of a management system ... but doesn't. That is why we invented the Adaptive Type System.
There are 4 main components of ATS:
Type Adapters.
A lot of technologies implement their own type systems within .NET. Most of these technologies are critical to Management scenarios (WMI, ADSI, XML, ADO, etc) so we needed to do something about this. What I mean by "implement their own type system" is that they have a small number of .NET types which then map to zillions of their own types. There are a zillion WMI objects but they are all represented by a 2 or 3 .NET classes. Type adapters allow us to adapt those technologies so they look like what users what out of a type - namely it's properties and methods. A normal WMIObject would look like this:
Scope : System.Management.ManagementScope
Path : \\JPSLAP14\root\cimv2:Win32_Service.Name="AeLookupSvc"
Options : System.Management.ObjectGetOptions
ClassPath : \\JPSLAP14\root\cimv2:Win32_Service
Properties : {AcceptPause, AcceptStop, Caption, CheckPoint...}
SystemProperties : {__GENUS, __CLASS, __SUPERCLASS, __DYNASTY...}
Qualifiers : {dynamic, Locale, provider, UUID}
Site :
Container :
We adapt that object so it looks like this:
ExitCode : 0
Name : AeLookupSvc
ProcessId : 1068
StartMode : Auto
State : Running
Status : OK
Extended Metadata System
.NET gives you a meat-and-potatoes type system giving you properties, fields, methods, interfaces and events. That is awesome but in management scenarios, we need more. PowerShell extends the typesystem with PropertySets, Aliases, MemberSets and then provides richer set of Properties and methods (e.g. Script Properties, CodeProperties, ParameterizedProperties, etc).
Type MashUps
One of the most powerful and least used aspects of PowerShell is it's type mashup system. What this does is allow anyone to extend the type system with their own properties, methods, metadata, etc. You can extend the types or the instances of the types. This is CRAZY useful when you have one command which outputs objects with a property called SERVER and you want to pipeline it to a command which accepts any object in the pipeline that has a property called COMPUTERNAME. All you have to do is to modify that definition of that type to ALIAS the property COMPUTERNAME to SERVER and now the pipelining happens with no additional code. This is freakishly powerful stuff.
Dynamic Types
In addition to extending a TYPE, you can dynamically extend any instance of a type. Take ANY object. You can add ANY additional property, alias, method, etc to THAT instance of the object and it won't affect any other instance. I find that I want to do this all the time. The mechanism for doing this is Add-Member. Here is what Add-Member looks like:
Adds a user-defined custom member to an instance of a Windows PowerShell object.
Add-Member
(0)-MemberType | -Type <AliasProperty | All | CodeMethod | CodeProperty | Event | MemberSet | Method |
Methods | NoteProperty | Parameterty | Properties | Property | PropertySet |
ScriptMethod | ScriptProperty>
(1)-Name <String>
-InputObject <PSObject> (ByValue)
(2)[-Value <Object>]
(3)[-SecondValue <Object>]
[-Force ]
[-PassThru ]
Here is an example of it in use:
PS>$l = gps lsass
PS>Add-Member -InputObject $l -MemberType NoteProperty -Name test -value "PowerShell ROCKS!"
PS>$l.test
PowerShell ROCKS!
PS>$l |fl t*
test : PowerShell ROCKS!
Threads : {684, 688, 692, 700...}
TotalProcessorTime : 00:01:48.9354983
SOOOO - why do I hate Add-Member?
I love that Add-Member lets me do a zillion things but in reality, 95% of the time, I just want to add a bunch of NOTEPROPERTIES to an object and Add-Member feels way to heavy to accomplish that. I've complained about this a number of times and tried to shame Bruce into fixing it but "to ship is to choose" and it has not popped up as the next best use of available calories. After trying and failing once again, I realized that I was being stupid - that ATS allowed me to control my own destiny.
What I decided to do was to add a new script method PSAddMember() to EVERY object in the system by attaching it to System.Object. This method would have 3 signatures. It would take a name/value pair, it would take a name/value/membertype tuple and it would take a hashtable which is a set of name/value pairs. Here is the file that does that and a demonstration of it in action:
<?xml version="1.0" encoding="utf-8" ?>
<Types>
<Type>
<Name>System.Object</Name>
<Members>
<ScriptMethod>
<Name>PSAddMember</Name>
<Script>
switch ($args.count)
{
1 {
$hash = $args[0] -as [HashTable]
foreach ($key in $hash.keys)
{
Add-Member -InputObject $this -Name $key -value $hash.$key -MemberType Noteproperty -Force
}
}
2 {
$name,$value = $args
Add-Member -InputObject $this -Name $name -value $value -MemberType Noteproperty -Force
}
3 {
$name,$value,$MemberType = $args
Add-Member -InputObject $this -Name $name -value $value -MemberType $MemberType -Force
}
}
</Script>
</ScriptMethod>
</Members>
</Type>
</Types>
----------------------------------------------------------------
PS> $p = gps lsass
PS> $p.PSAddMember("q1","Value1")
PS> $p.PSAddMember("q3",{"*"* $this.Threads.Count},"ScriptProperty")
PS> $p.PSAddMember("q2",{"*"* $this.Threads.Count},"ScriptProperty")
PS> $hash = @{q3=4; q4="Q4"; q5=(gsv alg)}
PS> $p.PSAddMember($hash)
PS> $p
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
1721 19 12688 19756 70 110.45 652 lsass
PS> $p.q1
Value1
PS> $p.q2
*****************************
PS> $p |fl q*
q1 : Value1
q2 : *****************************
q4 : Q4
q5 : System.ServiceProcess.ServiceController
q3 : 4
PS> $p
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
1721 19 12688 19756 70 110.45 652 lsass
Lessons learned/relearned:
- PowerShell's Adaptive Type System (ATS) is awesome.
- With ATS you are in control of your own destiny. (If you don't like the world - change it yourself. [then share to help others])
Enjoy!
Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
OCS Patches for Nortel CS1000 rel 5.5 with MCM 3.5 integration
I recently updated our lab environment and it is now running Windows Server 2008 and Hyper-V. During that process we finally updated our test CS100o to rel 5.5 and that required some updates that are different from the ones listed on the MS UC OIP site (Which are also outdated both 943083 and 943085 has been superseeded) and the ones listed in the Nortel documentation for rel. 5.5 .
In the following I have listed the "Required" patches according to Nortel's documentation and the "Actual" based on the current version of the hotfixes
OCS 2007 Front End
Required - Standard Edition RTM version 6362.0 plus hotfix KB 942872
Actual – Standard Edition RTM version 6362 plus hotfix 945055 (Includes Apiem.dll and Sipstack.dll in version 3.0.6362.17, which 942872 introduces)
Office Communication Server 2007, Mediation Server
Required - December 17, 2007, Version 3.0.6362.36 plus hotfix KB943086 and KB944285
Actual - December 17, 2007, Version 3.0.6362.36 plus hotfix KB943086 and KB944285
OCS Application Proxy Server
Required - OCS 2007 – Standard Edition RTM version 6362.0 plus hotfix KB 942872
Actual – Standard Edition RTM version 6362 plus hotfix 945055 (Includes Apiem.dll and Sipstack.dll in version 3.0.6362.17, which 942872 introduces)
Office Communicator 2007 Client
Required - December 17, 2007, Version 2.0.6362.36 plus hotfix KB 943083
Actual - December 17, 2007, Version 2.0.6362.64 including hotfix KB 951662 that supersedes 943083 (And replaces all files in 6362.65 version)
OMG - Check This Out (Data Visualization with PowerShell)
Doug Finke has been having fun working with PowerShell and .NetMap from MSR. Now he has written this AMAZINGLY tiny script to call the World Bank's WebService and visualize the world by income level. This has to be seen to be believed.
If you were ever unclear on the power of the compositional model (toolkit approach) or the productivity you can achieve with PowerShell - just go visit this blog.
Check it out HERE.
Doug - awesome stuff. Truely wonderful. You've made my day.
Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
Firefox, ClickOnce, XBAPs and .NET 3.5 SP1
One of the things that I noticed immediately when I made the SmallestDotNet was that Firefox was reporting the version of the .NET Framework installed. There's a Firefox extension that is installed with .NET 3.5SP1. I was stoked about this because I'd like users of BabySmash to be able to use ClickOnce from Firefox to launch it.
ClickOnce and FirefoxWhen you install .NET Framework 3.5SP1, there's a key written to the registry whether Firefox is installed or not. If Firefox is installed later, it will notice the key and use the plugin. If it's already installed, it'll just work. The registry key points to a Firefox Extension (XPI) that acts like the 3rd party FFClickOnce extension that a lot of us installed before.
The registry key is at HKLM:\Software\Mozilla\Firefox\Extensions This Firefox Addin helps ClickOnce applications work from inside of Firefox 2 or Firefox 3. It'll be installed with any installation of .NET 3.5 SP1, including the smaller Client Profile.
The add-in looks like this...
And its options dialog looks like this:
On my system the Firefox UserAgent now looks like this:
Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1 (.NET CLR 3.5.30729)
By default, as you can see in the dialog, the browser will report just the most recent version of the .NET Framework unless you say otherwise.
What happens if the FFClickOnce extension is already installed?In Firefox 3 the FFClickOnce add on will automatically get disabled as it has not been updated.
In Firefox 2 the FFClickOnce extension does not alter the user agent string due to a safeguard against creating a user agent greater than 128 characters. What happens when the user clicks on a .application link is dependent on the user’s configuration.
For Firefox 2.0 this is the table of possible prompting/launching configurations. The default for each add-on is marked in bold.
.NET Assistant FFClickOnce Result No Prompt Prompt FFClickOnce prompts and handles the click No Prompt No Prompt FFClickOnce handles the click Prompt Prompt.NET Assistant prompts and handles the click
Prompt No PromptFFClickOnce handles the click
When both add-ons are in the default configuration the user will get the FFClickOnce prompt and click once activation will follow the FFClickOnce path which may bypass IE download policy. In all cases the normal ClickOnce UI will be shown.
What this all means is that ClickOnce will work in FireFox 2 and 3, whether FFClickOnce is installed or not. How's it done?
The plugin is written with standard XUL (pronounced zoo-el) via XML and JS.
As an aside, I think it's cool that the XML namespace for XUL is:
http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul
You can go find the plugin yourself in:
C:\Windows\Microsoft.NET\Framework\v3.5\Windows Presentation Foundation\DotNetAssistantExtension
It's a .jar file, and you can copy it out and rename it .zip and open it up. The basic gist is that the plugin watches for a particular MIMEType and application, and if it matches, it launches the ClickOnce application using the the .NET Framework's PresentationHost.exe.isClickOnce: function()
{
var mimeInfo = dialog.mLauncher.MIMEInfo;
// Checking the file extension may be second guessing the webserver
// but when 'prompt' is set the user will still have a save button.
if (mimeInfo.MIMEType == "application/x-ms-application" ||
mimeInfo.primaryExtension == "application")
{
return true;
}
return false;
},
launch_application: function()
{
this.execute(this.getSystem32Dir() + \\PresentationHost.exe,
"-LaunchApplication " + dialog.mLauncher.source.spec);
dialog.mDialog.close();
}
It's not too complex, and it's sure nice that BabySmash users can use ClickOnce to launch the smash. XBAP
XBAPs, or XAML Browser Applications are also enabled in Firefox in .NET 3.5 using the standard NPAPI browser plugin API. The NPWPF.dll enables XBAPs under Firefox.

XBAPs are WPF applications that run inside the Browser's Chrome. They're good for Intranet applications where you want really easy deployment, the complete .NET Framework (as opposed to Silverlight) and a browser's navigational model.
If you type in about:plugins in Firefox, you can get a list, including this one:
Notice the MIME Types that this plugin has registered for and the extensions (suffixes) it handles. Each of these plugins are automatically installed and enabled when you install the .NET Framework 3.5SP1, so you can count on them.
Thanks to Eric Harding, Troy Martez and Jennifer Lee for helping me pull this information together. They're going to be adding more content to the Windows Client website very soon with more details how for developers to package and use the .NET Client Profile. They'll also be releasing lots of documentation and details on ClickOnce and deployment improvements in the framework. I'll point you to everything I can dig up, Dear Reader, as soon as I can.
Related Links
- Introduction to the Client Profile
- The .NET 3.5SP1 Client Profile
- Screencast on Deploying on .NET 3.5SP1
© 2008 Scott Hanselman. All rights reserved.
Family Calendar Management - Sharing Life between Outlook and Web Calendars and the Magic of iCalendar
Recently while talking to a friend I said something like "Oh, yes, my wife send me a meeting request for that." My friend was shocked. "How did you get your wife to send you Outlook Invites?" they said.
I was surprised they thought it was a big deal that we might manage our lives and appointments the same way a business runs their meetings. Why manage one's calendar with attention and detail at work, the use a Post-It Note or a Dry Erase board at home? Each to his or her own, to be sure, but ultimately find a system that works for you.
Don't give me the standard "Wow, that's a lot of work to set this up" comments. This took all of 10 minutes to do, I'm just being extra detailed for those who like their instructions along with pictures, clear steps and a little philosophy and history.
Here's what works for us and how we set it up. I talked about it in Podcast 58 on Synchronizing Your Internet Calendars.
Basics in a NutshellThis is the setup my wife and I have. I sync portions* of my calendar with a web calendar. Each of us can see each other's calendars as she subscribes to that calendar. My Outlook is my work email address, and I also have my personal email. She can send me Meeting Invites to either account. When I accept them, they'll show up in both places.

I'm using Outlook and The Wife is using Google Calendar, so this post uses those two products as an example. That's useful because they are both very common, and the combination is common. Also, it's nice to see Microsoft Products working with non-Microsoft Products using Open Standards.
However, the most important philosophical point to get from this section is that whatever service you are using, make sure you pick one that allows you to have control over your data and how it's published. Data Portability is important. You want to make sure you can get your data in and out of your chosen store. Preferably that'll be using a format like iCalendar (RFC 2445). Just knowing that the standard exists is empowering, because now you know what to look for.
Sharing (Publishing) in Outlook 2007In Outlook, there's two kinds of Calendar "sharing." There's Sharing and Publishing, in fact. Sharing in Outlook language means to Share your Calendar internally to your company's Exchange Server, while Publishing means to send your Calendar out to the Internet. By default this means to calendars.office.microsoft.com, but it can mean elsewhere.
TIP: I put my Free Busy info at http://www.hanselman.com/freebusy which just redirects to the Office site. This makes it easy for others to schedule meetings with me without giving away personal information or calendar details. I just publish free/busy time.
You CAN, if you like, publish your calendar out to the Internet as an ICS file, also called a "webcal" and then have other calendars pull from that. However, I prefer to have more control over what I publish, as I've got work meetings and things I may not want out of my Outlook.
SyncMyCal or Google Calendar SyncI want to part (or all) of my calendar into my wife's calendar. She uses Google Calendar, and I've got a Google Calendar using my personal email address.
In order to get my appointments into Google Calendar, I prefer to use SyncMyCal software (I paid $25 for it). There is another free tool from Google called Google Calendar Sync but it's VERY basic. I prefer SyncMyCal (enough to pay for it). It's an addin that runs inside of Outlook and it supports multiple calendars, can sync a specific Outlook category (like just Personal events), does date-range-filters, and will sync Contacts if you like.
Public Calendars and Subscribing to Calendars in OutlookThere's lots of sites that have lists of events and calendars. The best of them, like Upcoming.org include webcal/iCal/xCal feeds for all the events. Most personal web-based calendaring systems like Google Calendar (and my wife's calendar) have URLs that you can subscribe to.
For example, the Subscribe button on the Upcoming site includes an iCal option. These URLs look like:
webcal://upcoming.yahoo.com/calendar/v2/search_all/?search_placeid=RlEYPWubBZtlFXkb&rt=1
Even though they have webcal:// at the beginning, they are still serving the calendars over HTTP. However, the webcal:// "psuedo-protocol" is a hacky way to get something to happen when you click on it. Because I have Outlook installed, clicking that iCal link gets me this dialog:
Clicking yes adds a new calendar to Outlook in "Other Calendars."
This is how I add all sorts of calendars into Outlook. I've got Team Calendars from Sharepoint, Calendars from our Intranet, as well as the wife's.Any calendar can be viewed side-by-side with the main.
Or, I can overlay them. This is really useful for viewing The Wife's calendar and finding time where we can both free. The secondary calendar appears "ghosted" and overlaid over the primary. You can even show multiple (6, 7, etc) calendars and easily find time for meetings amongst your teammates.
If you've got a calendar "in the cloud" with a URL to an ICS, it's easy to add them to Google Calendar. In Calendar click "Add" under Other Calendars and click "Add By Url":
This is where you'd paste in the iCal URL for the calendar you're trying to consume. The wife does this with public calendars. For family there's a faster way. Just click on your calendar and click "share this calendar" and Google takes care of the rest.
IMPORTANT NOTE and CYA DISCLAIMER: It's ironic that while I've been using various plugins for Outlook Calendar synchronization for the last four+ years and never lost a thing, this week while on a trip (and while writing this post) I lost (almost) all my future appointments. Because I'm using SyncMyCal along with three different other experimental plugins, not to mention syncing with Mobile Devices, my gut says it's not SyncMyCal. However, this near-data loss is an important reminder that there's always a chance you can lose something important when you're using any synchronization software that syncs deletes.
I got my data back by going to another machine I had with Outlook on it, launched Outlook and immediately put it into Offline mode so the deletes from the server wouldn't come down. I exported that range of missing appointments from that machine and imported them to another. The final calendar was then updated in Exchange. Crisis averted, but it was a scary time. If you lose your data, I can't help you. Be careful.
* filtering out private/sensitive/NDA work meetings via categories
© 2008 Scott Hanselman. All rights reserved.
Skyping the Wife: Foolproof Video Conferencing with Your Family While on the Road
I really like presenting and traveling around and meeting people, but I just hate being away from my kids. It's visceral. It's physically painful. I bring them whenever I can, but during this last trip to New Zealand and Australia it wasn't possible and I was away for 8 days. Almost killed me.
Since I work from home, when I need to talk to folks in Redmond I use Office Communicator, sometimes ooVoo if we need to talk to multiple people, or sometimes a Roundtable. Roundtables are cool because you get a full 360 degree view of the room.
Using Video Conferencing has become totally fundamental to my work life, and when I travel (a few days a month) it's utterly indispensable.
I've traveled a few times and tried to call the wife via Video Conferencing and had an utter failure. We've had trouble with her figuring out how to answer the call, how to run the app, login, deal with odd dialogs, updates, and all the general gremlins that can potentially take what is supposed to be a great experience and turn it into long-distance tech-support. Nothing lowers the WAF (Wife Acceptance Factor) like telling your wife to crawl under the computer desk and check the microphone cables.
I watched literally three different technical speakers try to get video conferencing work while in the speaker room on this last trip. One succeeded. All the others got themselves into situations where the spouse could IM, but not hear, or hear but not see, or whatever. "Can you hear me now?"
Foolproof Familial Video ConferencingAfter a half-dozen failures I finally got smart. Here's what I ended up doing to make it easy. This has worked for my wife and I nine out of ten times (once there were connectivity problems at the hotel) and it's worked from Europe to the South Pacific.
Step 1 - Hardware
Get a good camera. I recommend the LifeCam VX- or NX- series. The VX-7000 is nice and simple for home. It has a good microphone built-in and the camera will do 640x480 at 20+fps easily.I use the NX-6000 for my laptop.
Step 2 - Software
Download Skype (or ooVoo or Live Messenger). You'll need two accounts, one for you (the techie) and one for your spouse. Personally I recommend a dedicated account for trips for your spouse. Something with a username like "ScottIsTraveling."
Step 3 - Preparation before you travel
Before you travel, declare one machine in the house that video conferencing machine. Log the spouse into the special travel account. Add your account as a Contact to the special travel account. That means that the special account will have only one friend - you. This is important.
Next, go into Options (I use Skype as an example, but hopefully other apps have similar options) and into Privacy. Set the options such that these are true:
"Only allow people who are in my contact list to contact me"
and
"Automatically answer calls from people who are in my Contact List"
and finally, and most importantly:
"Automatically Send Video"
These are the magic three options. With this setup, your spouse will have one contact, you, and when you call it will be auto-answered and the video will start.
Then I leave the account logged in and I check the video camera and microphone before I go.
This allows me to call the house and have video start without the wife even touching the machine. Daddy can show up on the computer and say "Hi! It's me, is anyone there!?" My son can run it and start talking to me, even without Mommy's help.
One last tip, try to use whatever the highest resolution your camera, bandwidth, and software supports. I was able to get near-DVD quality (640x480) this last trip and was thrilled with the quality. Video conferencing has come a long way since my first black-and-white Logitech QuickCam.
Next time you're traveling I encourage you to try this out and see how it goes. This trip I was able to have chats with the family every night with no glitches or troubles. It almost made the time away tolerable.
Technorati Tags: Remote Work,Skype,Video© 2008 Scott Hanselman. All rights reserved.
Windows Live Mesh, Silverlight and the CoreCLR
Disclaimer: Everything in this post is pure conjecture by me, done by simply poking around my system and talking to myself. I don't work for the Live Mesh team, nor do I know anyone on the team. Anyone could have written this.
I was talking to Harry recently and we went poking around in the folder that the Windows Live Mesh client is in. On my machine it's in "C:\Users\scottha\AppData\Local\Microsoft\Live Mesh\"
There's a lot of interesting stuff in there. There's a version of System.Core (LINQ) as well as System.ServiceModel (WCF), but most interestingly there's coreclr.dll. Where have I seen that before? I've seen it in C:\Program Files (x86)\Microsoft Silverlight, of course. It's the Silverlight CLR that you might have on your own system. Remember this isn't the complete CLR, but rather a pared-down more portable version. This makes sense since Mesh plans to do a Mac client and Silverlight runs on Intel Macs.
It's a different version, though. On my machine I've got Silverlight 2 Beta 2 and its digital signature for coreclr.dll is recent while the Mesh coreclr.dll is version 1.1 and from February. That was back before the Mix '08 conference Silverlight 1.1 was re-christened "2.0."
You can see more of the MOE (Mesh Operating Environment) external dependences in the "Moe.exe.managed_manifest" XML file. It appears they've got their own private build of the a tiny CLR and just the libraries they need to make it work.
Even though Silverlight is a Rich Internet Application (RIA) technology and meant for use as a browser plugin, this is the third time I've found Silverlight living outside the browser (although still doing "connected" work).
The first time was when Jamie Cansdale, the author of TestDriven.NET prototyped running Unit Tests with the CoreCLR/Silverlight.
The second time, was the Mac Times Reader. You might have seen the NYTimes Reader, and the News Reader SDK. The Times Reader is a XAML-based WPF application. However, there is a scaled-down version of the Times Reader that was released on the Mac and it uses Silverlight to render XAML. In that application Silverlight is being hosted inside of a Cocoa "chrome" shell application using some MacGyver magic. It appears a lot of custom work was done to render the Reader-specific news feed (it's more than just RSS) in a flow layout.
All of this stuff Mesh is doing struck Harry and I as very interesting. It'd be cool if ISVs could target the CoreCLR (Silverlight) for some scenarios and have their own xcopy deployed private-version of .NET like Mesh. It appears Mesh used this custom version of the CLR so it would have portability between platforms.
It's always interesting to see how other groups at Microsoft do stuff. Just like us (the community), other divisions that use things the Developer Division produces, although since they are on the inside they get to do some magical things since they can just walk down the hall. (I work in my home office, so I'm pretty much limited to Office Communicator or I have to ask Phil to walk down the hall for me.)
I'm going to ask around and find out the full story behind how the Mesh (Beta) Windows Client uses .NET, and maybe I can get one of the more technical folks to do a podcast.
Technorati Tags: Mesh,Silverlight,CLR© 2008 Scott Hanselman. All rights reserved.
