Just a short, simple blog for Bob to share his thoughts.
09 July 2010 • by bob • Rants
I saw a video the other day for the song "Crying for John Lennon," which is a truly pathetic piece of hero worship about a boorish, drug addicted, womanizing narcissist. Putting aside the fact that John Lennon is no person to be admired, this video and song are another entry in a long line of juvenile visions of a world where nothing evil ever happens. The trouble with such a naïve approach to life is that it presupposes that everyone agrees with your interpretation of evil. How utterly immature.
Some cultures ignore their neighbors, some cultures fight their neighbors, while other cultures eat their neighbors. There is no common ground - there is no singular interpretation of what constitutes the concept of good or bad, much less a concept of "peace."
But for that matter, many a conquered people in western cultures have believed in peace at all costs. Crowds of angry youths who have been so sheltered by the blanket of freedoms which have been thanklessly provided for them are lulled into adolescent complacency and they form a misguided view of the world that ultimately leads to their destruction. I think that John Stuart Mill put it best when he said:
"War is an ugly thing, but not the ugliest of things. The decayed and degraded state of moral and patriotic feeling which thinks that nothing is worth war is much worse. The person who has nothing for which he is willing to fight, nothing which is more important than his personal safety, is a miserable creature and has no chance of being free unless made and kept so by the exertions of better men than himself."
For every person who dreams of pacifism no matter the cost, there are a dozen people who are willing to kill them simply for their shoes. I have travelled abroad - and I have met some of these types of people. It is difficult for simple minds to understand that there are some people in the world who hate you just because you exist. It's nothing that you have done, it's nothing that you believe, and there's nothing that you can do about it.
So while the songwriter who inspired me to write this post may be crying for John Lennon, I am weeping for our future - because if people like this songwriter continue to persist in their delusions, we are truly doomed.
15 June 2010 • by Bob • Humor
Let there be no misunderstanding – I love Famous Amos cookies. But that being said, Famous Amos is out to kill me.
If I eat a small handful of Famous Amos cookies, I will pay for it with severe heartburn that lasts for several hours. But the following week, I’ll buy another package – I know that I'm going to be in pain, but I just can't help myself.
I know that one of the hardest experiences for mankind is trying to kick the smoking habit, but I have to be honest – trying to stay away from Famous Amos cookies is much harder. At least for me, anyway.
What’s even worse is when I have just enough pocket change to buy a little bag of cookies from the vending machine and the @#$% machine won’t take one of my coins. Those machines do that just to mess with me, I’m sure of it. All I can do is stare at the bag of cookies – just out of reach – and there’s nothing that I can do. There they sit – right in front of me – taunting me to resort to drastic measures.
[Deep Sigh.]
I have to go – the day is getting late and I feel like a snack.
I wonder how much change I have?
07 May 2010 • by Bob • FTP
For this installment in my series about FTP Clients I'm going to review the SmartFTP Client from SmartSoft Ltd. For this blog post I used the SmartFTP Client Ultimate Edition version 4.0.1105.0, and it is available from the following URL:
At the time of this blog post, SmartFTP is a for-retail product that is available in three editions: Home, Professional, and Ultimate. A description of the prices and features that are available in each edition is currently available from the following URL:
As for myself, I would use at least the Professional edition, and that statement is based on the features that I typically look for in an FTP client. (Although I would have loved to have had the Ultimate Edition several years ago when I used Telnet to connect to servers. <grin>)
The SmartFTP Client is pretty intuitive and it's easy to navigate within the application. If you are used to using typical Windows applications then you should find that the user interface follows most of the established paradigms that you would expect from a Microsoft application; it seemed to me that the design emulated the relevant parts of Windows Explorer, Visual Studio, and Office with an FTP focus.
For example, switching your directory listing views align with most Windows applications, and the site management functionality is managed through a hierarchical set of "Favorites."
Each "Favorite" has a variety of additional settings that you can edit by open the properties dialog for the favorite.
One of the great features in all editions of the SmartFTP client is a nicely-implemented Remote Edit functionality, which allows you to invoke your favorite editor from inside the client's GUI.
The SmartFTP Client does not have a built-in command-line interface, although there is a script-based command-line interface that you can download separately from the SmartFTP web site. That being said, that script is not created by the folks at SmartSoft, and it's functionality is extremely limited.
For me personally, the SmartFTP Client's extensibility model more than makes up for the lack of command-line functionality. More often than not I'm simply using the command-line in order to script FTP operations, and the SmartFTP extensibility features provide a great deal more capabilities than I would have available to me when automating a command-line FTP client.
I haven't spent a great deal of time working with the extensibility features, but so far I am pretty impressed. I was able to take one of the samples and retool it into a simple FTP client pretty easily. (I will include that as an example in a later blog post.) In the meantime, you can download the SDK for the SmartFTP Client from the following URL:
The SmartFTP Client supports both Implicit and Explicit FTPS, so the choice is up to you to decide which method to use. The FTPS method is stored as the Protocol in a favorite's properties, which is easily located in the General settings for a favorite.
Once again, the following rules apply for FTP7 when determining whether to specify Implicit or Explicit FTPS:
If you are using Implicit FTPS, make sure that you configure your FTP client to connect on port 990.
Because the SmartFTP Client's properties for favorites allow you to specify the virtual host name as part of the user credentials, the SmartFTP Client works great with FTP7's virtual host names. All that you need to do is use the "ftp.example.com|username" syntax when specifying your username, and when you connect to the FTP7 server it will route your requests to the correct FTP virtual host site.
The SmartFTP Client provides built-in support for the HOST command, which means that you can have real multi-homed FTP sites when using the SmartFTP Client to connect to FTP7 sites that are configured with host names. In order to use true HOSTs in the SmartFTP Client, you need to configure the client to send the FEAT command before logging in. This is configured in the Connection settings in the drop-down menu for "Send FEAT."
As an FYI - I had some discussions with Mat Berchtold from SmartSoft while I was writing this review, and Mat informed me that the SmartFTP Client doesn't automatically assume support for the HOST command; sending the FEAT command before logging in allows the client to discover if HOST is supported before continuing.
Mat Berchtold from SmartSoft also mentioned that some firewalls do not yet recognize the HOST command, and therefore those firewalls may not pass the HOST command through the firewall. That's something to think about if you start to see connection failures related to hostnames not being found - you can check your FTP server's logs to see if the HOST command is arriving at the server.
This concludes our quick look at some of the features that are available with the SmartFTP Client, and here's the scorecard results:
Client Name | Directory Browsing | Explicit FTPS | Implicit FTPS | Virtual Hosts | True HOSTs |
---|---|---|---|---|---|
SmartFTP Client Ultimate 4.0.1105.0 | Y | Y | Y | Y | Y 1 |
1 As noted earlier, true FTP HOSTs are fully supported, but you need to configure the SmartFTP Client to send the FEAT command before logging in. |
Note: I've included the following disclaimer in all of my posts, and this post is no exception. ;-] There are a great number of additional features that the SmartFTP Client provides - once again I'm just keeping the focus on those topic areas that apply to FTP7.
Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/
02 May 2010 • by Bob • Windows
I put together this list for my brother when Windows 7 launched. I got the information from a variety of sources, thereby living up to the old adage that "Copying from one person is plagiarism, copying from a hundred people is research." Some of these are new to Windows 7, while others have been around a little while. In any event, here are some notes that explain how to interpret the keystrokes:
Shift+Click | Open a new instance of the program |
Ctrl+Click | Cycle between windows in a group |
Middle Click | Open a new instance of the program |
Ctrl+Shift+Click | Open a new instance of the program as Administrator |
Shift+Right-Click | Show window menu |
Alt+F4 | Close the active window |
Alt+Tab | Switch to previous active window |
Alt+Esc | Cycle through all open windows |
Win+Tab | Flip 3D |
Ctrl+Win+Tab | Persistent Flip 3D |
Win+T | Cycle through applications on taskbar (showing its live preview) |
Win+M | Minimize all open windows |
Win+Shift+M | Undo all window minimization |
Win+D | Toggle showing the desktop |
Win+P | Open the projection menu (generally used for laptops connected to projectors) |
Win+[Up] | Maximize the current window |
Win+[Down] | If the current window is maximized, restore it; if the current window is restored, minimize it |
Win+[Left] | Dock the current window to the left half of the screen • If it is already docked left, it is moved to the right half of the screen • If it is already docked right, it is restored to its original size |
Win+[Right] | Dock the current window to the right half of the screen • If it is already docked right, it is moved to the left half of the screen • If it is already docked left, it is restored to its original size |
Win+Shift+[Left] | Move current window to the left monitor (with dual monitors) |
Win+Shift+[Right] | Move current window to the right monitor (with dual monitors) |
Win+Home | Minimize all but the current window |
Win+Space | Peek at the desktop |
Win+[Plus sign] | Zoom in |
Win+[Minus sign] | Zoom out |
Win+1 | Open the first program on your Quick Launch bar |
Win+2 | Open the second program on your Quick Launch bar |
Win+n | Open the nth program on your Quick Launch bar |
Win+U | Open the ease of access center |
Win+F | Open the search window |
Win+X | Open the Mobility Center |
Win+E | Open Explorer |
Win+R | Open the Run window |
Win+B | Move focus to notification tray (the right-most portion of the taskbar) |
Win+Pause | Open the System Properties portion from the Control Panel |
Ctrl+Shift+Esc | Open Windows Task Manager |
Win, [Right], Enter | Shutdown |
Win, [Right], [Right], R | Restart |
Win, [Right], [Right], S | Sleep |
Win, [Right], [Right], H | Hibernate |
Win, [Right], [Right], W | Switch Users |
Win+L | Locks computer |
Alt+[Left] | Go back |
Alt+[Right] | Go forward |
Alt+[Up] | Go up a directory |
Alt+D | Move focus to address bar |
Alt+D, Tab | Move focus to search bar |
Alt+Enter | Open the Properties window of the current selection |
Ctrl+Mousewheel | Change the view type (extra large, small, list view, detail, etc.) |
Alt+P | Show/hide the preview pane |
28 April 2010 • by Bob • FrontPage
I've had a few questions about getting the FrontPage 2002 Server Extensions (FPSE2002) AllowUNC feature to work with Windows Server 2008, so I thought that I would put together a blog from some of the information that I had been giving out whenever someone was having problems.
As a little bit of background information, Windows 2003 Server shipped with a later version of FPSE2002 than had previously been released, and that version of FPSE2002 was used as the code base for the version of FPSE2002 that was later shipped for Windows Server 2008. One the great features of this release was the ability to host your content on a remote server using a UNC share, which is something that web administrators had been requesting for years. Microsoft wrote a full whitepaper that details all of the possible configurations and steps to configure FPSE2002 with this feature at the following URL:
That being said, that whitepaper is quite large, and not all of it is necessary if you simply want to host FPSE2002-based content on a UNC path. With that in mind, I have come up with an abbreviated set of steps that uses the whitepaper as a base for enabling this feature. To be more specific, I was able to implement this feature by using only the following sections of that whitepaper:
The body of this blog post is an excerpt from the whitepaper, and contains only the steps that I used to get my test scenario up and running. For my test, I set up a domain controller, a file server, and a web server; all running Windows Server 2008 or Windows Server 2003. I include notes when necessary to highlight issues that I ran into.
Additional Notes:
You must configure a shared folder on the file server and grant the Web server access to the contents of that folder. Note that you must set the permissions for the folder itself, not a parent folder. It is recommended that you also implement IP Security on the file server, so that only the Web server, the domain controller, and other administrator computers can access the file server over TCP/IP. For more information about configuring IP Security, see Setting Up IPsec Domain and Server Isolation in a Test Lab.
Giving Everyone full control to your server share is necessary so that all users of your Web site can view the Web site information and run the ASP pages required to use FrontPage 2002 Server Extensions. However, you do not want to allow other computers or other servers access to the file share and those ASP pages. It is recommended that you implement Internet Protocol (IP) Security to help prevent users and computers from circumventing the FrontPage 2002 Server Extensions and Internet Information Services security for the file share and ASP pages.
Note - The separate user management feature for FrontPage 2002 Server Extensions also helps secure the process for accessing ASP pages through the file system. It is recommended that you implement this feature if you are connecting Web sites to UNC shares. For more information about managing users separately, see Authenticating Users Separately For Each Virtual Server.
You use Internet Information Services (IIS) to create your new virtual server. You must also decide how to configure the security settings for your virtual server.
Note - If you chose to allow anonymous access for the virtual server, you must specify the domain account to use for anonymous users. When you use a local folder, you can use the default anonymous user (usually IUSR or IUSR_Machinename). To connect to a shared resource on a domain, however, you must specify an account with rights to the domain. Be sure to use an account with limited rights to the computers and resources in your domain. Do not unintentionally give anonymous users the ability to administer your server or print to your network printers.
Note from me:
As stated by me earlier, this entire article does not appear to work unless you specify a domain-level IUSR account in IIS, even if you are going to not allow anonymous access. In my testing, it seems to fail when anonymous is disabled and the anonymous user had been local, whereas it succeeded when the anonymous user is a domain-account with rights to the share, even though anonymous is disabled for the site.
After you have created the virtual server, you must configure the security settings. When a Web site user requests a file that actually resides on a network share, there are two methods that FrontPage Server Extensions can use to provide the required authentication information:
Warning - Basic authentication forwards the requestor's username and password over the network. This means that usernames and passwords can be captured using a network packet analyzer. Only use basic authentication if you are sure that potential hackers don't have access to your network cabling or wireless media.
Note from me:
As stated by me earlier, I only tested with Basic Authentication; I did not try Kerberos. Since we are making a single hop to another server, I would expect simple NTLM to fail. See KB 315673 for a description of single versus double hop setups when working with IIS configurations. But that being said, Windows Authentication in an Internet environment is impractical, so in most scenarios this point is moot.
After you create the virtual server, and before you can extend it with FrontPage 2002 Server Extensions, you must set the following registry entries to enable your Web server to work with a shared UNC folder:
Both subkeys are under the following path in the registry depending on your version of Windows:
If these subkeys do not exist yet, you can add them as new string values, and then set them to 1.
After the virtual server has been created and configured, you are ready to extend it with FrontPage 2002 Server Extensions. You must extend the virtual server before you can publish Web site content to it.
After you extend the site, it is recommended that you run server health to make sure the permissions are set correctly and do not allow unauthorized access. To run server health, use the following command-line operations:
cd /d "%ProgramFiles%\Common Files\Microsoft Shared\Web Server Extensions\50\bin"
owsadm.exe -o check -p 80 -w /
As I mentioned in the beginning of this post, there are a lot of steps to get this working, but it's possible to do so.
I hope this helps. ;-]
22 April 2010 • by Bob • IIS, WebDAV, IIS 6
We recently ran into a situation where a customer thought that they were seeing file corruption when they were transferring files from a Windows 7 client to their IIS 6.0 server using WebDAV. More specifically, the file sizes were increasing for several specific file types, and for obvious reasons the checksums for these files would not match for verification. Needless to say this situation caused a great deal of alarm on the WebDAV team when we heard about it - file corruption issues are simply unacceptable.
To alleviate any fears, I should tell you right up front that no corruption was actually taking place, and the increase in file size was easily explained once we discovered what was really going on. All of that being said, I thought that a detailed explanation of the scenario would make a great blog entry in case anyone else runs into the situation.
First of all, the customer was copying installation files using a batch file over WebDAV; more specifically the batch file was copying a collection of MSI and MST files. After the batch file copied the files to the destination server it would call the command-line comp utility to compare the files. Each MSI and MST file that was copied would increase by a small number of bytes so the comparison would fail. The customer computed checksums for the files to troubleshoot the issue and found that the checksums for the files on the source and destination did not match. Armed with this knowledge the customer contacted Microsoft for support, and eventually I got involved and I explained what the situation was.
Windows has a type of file format called a Compound Document, and many Windows applications make use of this file format. For example, several Microsoft Office file formats prior to Office 2007 used a compound document format to store information.
A compound document file is somewhat analogous to a file-based database, or in some situations like a mini file system that is hosted inside another file system. In the case of an MST or MSI file these are both true: MST and MSI files store information in various database-style tables with rows and columns, and they also store files for installation.
With that in mind, here's a behind-the-scenes view of WebDAV in IIS 6.0:
The WebDAV protocol extension allows you to store information in "properties", and copying files over the WebDAV redirector stores several properties about a file when it sends the file to the server. If you were to examine a protocol trace for the WebDAV traffic between a Windows 7 client and an IIS server, you will see the PUT command for the document followed by several PROPPATCH commands for the properties.
IIS needs a way to store the properties for a file in a way where they will remain associated with the file in question, so the big question is - where do you store properties?
In IIS 7 we have a simple property provider that stores the properties in a file named "properties.dav," but for IIS 5.0 and IIS 6.0 WebDAV code we chose to write the properties in the compound document file format because there are lots of APIs for doing so. Here's the way that it works in IIS 5 and IIS 6.0:
So believe it or not, no harm is done by modifying a compound document file to store the WebDAV properties. Each application that wants to pull information from a compound document file simply asks for the data that it wants, so adding additional data to a compound document file in this scenario was essentially expected behavior. I know that this may seem counter-intuitive, but it's actually by design. ;-]
Once I was able to explain what was actually taking place, the customer was able to verify that their MST and MSI files still worked exactly as expected. Once again, no harm was done by adding the WebDAV properties to the compound document files.
You needn't take my word for this, you can easily verify this yourself. Here's a simple test: Word 2003 documents (*.DOC not *.DOCX) are in the compound document file format. So if you were to create a Word 2003 document and then copy that document to an IIS 6.0 server over WebDAV, you'll notice that the file size increases by several bytes. That being said, if you open the document in Word, you will see no corruption - the file contains the same data that you had originally entered.
I hope this helps. ;-]
08 April 2010 • by Bob • Rants
I had originally written the following for a Facebook note, but I think that it's better as a blog post:
Let's face it, if you have known me for any period of time during the past two decades you would quickly realize that outside of church, family, and music, working with computers is my next biggest passion. Being been hired by Microsoft in late 1995 was one of those moments where I smacked myself on the head and questioned why I hadn't thought of that before. It's just great when it turns out that you can actually make a living doing one of your hobbies. (Making a living making music would be great, too, but I work with a large number of people who have all realized that having a normal day job means that you can actually afford your music hobby. Whereas trying to make a living at music often means wondering where your next meal is coming from. But I digress...)
Anyway, I've had several different jobs since I joined Microsoft, which always leads to the following question from friends and family: "So, what do you do for Microsoft?"
Over the past few years I have worked on a team with several gifted people that create several technologies that perform a lot of the behind-the-scenes work for the Internet, and these days I spend my time writing about these products and telling people how they can use them. With that in mind, I thought that I'd answer a little bit of the "What do you do for Microsoft?" question by way of illustration.
The following blog post that I wrote recently branches off into several links where I discuss writing a bunch of code to do a variety of things that many people would probably find... well... less than exciting:
MSDN Blog: Merging FTP Extensibility Walkthroughs
As I said, you might not find it exciting - but for me, this why I get up in the morning, and at the end of the day it's why I still love my job.
;-)
24 March 2010 • by Bob • FTP
Since I started reviewing FTP clients I've had a few requests to look at a few different FTP clients, and I've managed to analyze a few of those clients in my blog. A few weeks ago I had a request from one of my readers that really caught my interest - Shabbir Talib contacted me through my blog and asked me to review the Kermit FTP Client. I found his request especially appealing because I used to use Kermit before the public learned about the Internet; back then I was using Kermit to access dial-up Bulletin Board Systems (BBS's) and to connect to my college's VAX system. That being said, I hadn't used Kermit in years so I couldn't resist taking a look.
To start things off, the Kermit Project is developed and distributed by Columbia University in New York City. More information about the project, downloadable installation packages, and software licenses for purchase are available from:
I need to stress here the Kermit is actually a full suite of connectivity applications, the Kermit FTP Client is only one part of that communications suite. So from the outset the Kermit is more than overkill if you're just looking to transfer some files to and from your FTP site. The Kermit Dialer takes the place of what most FTP clients would have as a Site Manager, and opening that application will display a large number of templates for various connection types.
Rephrasing my earlier statement, saying that Kermit is overkill is really an unfair assessment when you consider the sheer number of options that Kermit gives you. If you are used to creating and configuring FTP site connections in most FTP clients, you generally have a small handful of options that you can specify. This is not true for Kermit 2.1.3 - the wizard for creating a new FTP connection in the Kermit GUI led me through eleven wizard-based pages of options before the connection was created.
Once you connect, however, the Kermit GUI is just a wrapper for command-line FTP functionality - so you have to know what you're doing in FTP to get around, and there is no explorer-style functionality like you get with graphical FTP clients like Core FTP or FileZilla.
Since the Kermit GUI is just a wrapper for the command-line, you may have already guessed correctly that the Kermit FTP Client (ftp.exe) works just fine from a command prompt. What's more, Kermit has a built-in scripting language that far surpasses the scripting capabilities for the built-in Windows command-line ftp client (also named ftp.exe.) For example, you can script what action to take if something goes wrong - like retrying a failed upload. More information about scripting the Kermit FTP Client is available at the following URL:
From what I've seen of Kermit's scripting support, this appears to be an extremely rich feature for people that need more options for scripting an FTP client.
The Kermit FTP Client supports FTPS, and it allows you to configure options such as separate protection levels for the command and data channels for a connection.
Once you have the security options specified for the connection, connecting to an FTP site using FTPS is pretty straightforward.
I could find nothing in the Kermit FTP Client documentation that referenced support for implicit FTPS, and when I configured one of my FTP sites to use implicit FTPS I could not connect to it using Kermit. (But in all fairness, you may recall from some of my earlier blog posts that Implicit FTPS is often considered deprecated.)
Like the MOVEit Freely FTP client, everything is happening from a command-line, so you can use both FTP7's Virtual Hosts and the actual FTP HOST command. (As I have mentioned in previous blog posts, you should take a look at my Virtual Hosts and Host Names in FTP7 blog post for more information about FTP Virtual Host Names and FTP True Host Names, and see https://datatracker.ietf.org/drafts/draft-hethmon-mcmurray-ftp-hosts/ for more information about status of the FTP HOST command.)
That being said, FTP7 virtual hosts are supported by using the "ftp.example.com|username" syntax when specifying your username, and when you connect to the FTP7 server it will route your requests to the correct FTP virtual host site.
True FTP hosts can be used by specifying the FTP HOST command using the Kermit FTP Client's support for custom commands. The syntax for this command is listed below:
ftp quote host ftp.example.com
Note: You need to send the HOST command before sending USER and PASS.
This concludes our quick look at some of the features that are available with the Kermit FTP Client, and here's the scorecard results:
Client Name | Directory Browsing | Explicit FTPS | Implicit FTPS | Virtual Hosts | True HOSTs |
---|---|---|---|---|---|
Kermit FTP Client 2.1.3 | N | Y | N | Y | Y 1 |
1 As noted earlier, true FTP HOSTs are available when using the "ftp quote HOST ftp.example.com" syntax. |
Note: Keeping with my standard disclaimer, there are a great number of additional features that the Kermit FTP Client provides - I'm just keeping the focus on those topic areas that apply to FTP7.
Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/
22 February 2010 • by Bob • Blogging
This blog isn't that old, I only created the site a few months ago, but it's amazing how much spam I get. It seems like every other day I have another spammer that is pretending to post comments, when they are actually just posting links to their (often bogus) business web sites.
Fortunately I have comment moderation turned on so their posts are never actually posted to the web site, but spammers are never deterred - they continue to post new comments to my site in the hopes that maybe something will get through. So I fully expect that some spammer is going to post so innocuous piece of worthlessness to this blog post within the week.
[Heavy sigh.]
Spammers suck.
02 February 2010 • by Bob • Family, Marriage
Valentine's Day is just around the corner, which is always an occasion for me to become a little introspective. With that in mind, I remember the days of our courtship when we would promise to love each other forever and to grow old together; yet now as I look back on our lives, I realize that we had no idea what we were saying. We were young and in love and completely clueless about what being in love really meant.
Mark Twain once wrote that "No man or woman really knows what perfect love is until they have been married a quarter of a century," and now that we have passed that milestone I can look back and begin to catch a glimpse of this elusive concept called "true love."
Love has meant staying together through times of destitute poverty when we didn't know from where our next meal would come. Love has meant enduring months of separation when I was serving abroad in our country's armed forces. Love has meant countless sleepless nights raising children and meeting their every need. Love has meant staying by each other's bedside to nurse one another back to health. Love has meant walking side-by-side through that timeless season of joy mixed with pain that all parents must suffer when watching their children grow up and leave home.
Over the years I have learned that true love is not the offspring of well-meant promises made hastily in your youth; true love is borne of a thousand little things over thousands of days and nights as you grow older together, until you find that so much time has passed that you cannot remember a time when you were ever apart.
Will Durant wrote that "The love we have in our youth is superficial compared to the love that an old man has for his old wife," and I have found my greatest joy in growing old with you.