NTFS on OS X

Trying to write to an NTFS volume on OS X, and all you find are third party packages and complicated config file manipulations asking you to reboot? Do this….

Every once in a while someone brings over an external NTFS formatted drive and plugs it into my Mac to exchange some large data sets. While the Mac can easily read NTFS, it doesn’t appear to have the capability to write to that file system.

Appears is the operative phrase.

If you search for a solution in the open, you’ll find companies selling commercial products, drivers, and mounters. Some people have posted complicated looking instructions telling instructing you to mess with low level system files, that may or may not exist, ending in a full system reboot that typically solves the problem for that lone drive.

NTFS on OSXHere’s the generic no-software required solution.

First connect your NTFS drive to the Mac, it’ll mount with some name like “My Disk.”

Open a Terminal window and enter the command:
$ mount

The mount command will tell you what drives are listed. Find the one that has your drive name listed in it and copy the device name:
/dev/disk1s2 on /Volumes/My Disk (hfs, local, nodev, nosuid, journaled, noowners, mounted by me)

Now eject the drive, but don’t disconnect it from the machine.

Go manually create the directory (shown in bold above); this is where the mount point will be:
$ cd /Volumes
$ mkdir My\ Disk

NOTE: The backslash escapes the next character, in this case allowing a space in the directory name.

Now, mount the drive as read-write using this command:
$ sudo mount -o rw -t ntfs /dev/disk2s1 /Volumes/My\ Disk

Make sure that you’ve used the same device location you copied down the the prior steps.

At this point your drive should appear on the desktop, and you ought to be able to read and write to it just fine. No rebooting necessary!

Note that you can get to it from the Terminal as well:
$ cd /Volumes/My\ Disk
$ ls

Note that sometimes Finder may act a little wonky with timing problems and a huge file. Apparently the underlying Unix system has no problem. You can copy a big file to the drive:
$ rsync –progress SuperBigFile.zip /Volumes/My\ Disk

Or a whole directory:
$ rsync -r –progress LargeDeepDirectory /Volumes/My\ Disk

When done, make sure you are not running any programs that are accessing the drive or have their current directory set to the drive:
$ cd /Volumes

Then, eject the drive normally, or unmount it from the command line — your choice.
$ sudo umount /Volumes/My\ Disk

Full disclosure and warnings: This was tested on OS X 10.6.5, though support has been around to do this for a while. And, any time you’re doing something that deals with questionable file system access, make sure there’s nothing on the drive you don’t mind losing. Have a backup. There’s always a slight risk, but it’s very close to zero — why state all this? Because I assume no responsibility if something goes wrong.

C# Must Haves

Resources for quickly getting up to speed on C#.

This is the page of C# resources that I wish I had when I got started.

Visual Studio 2010Snag a copy of Visual Studio, whether it’s the free Express version, or one of the uber-featured ones.

Reactive Extensions
In addition to .NET, snag the Reactive Extensions (Rx) library.


Expression Blend 4If you’re able to, grab a copy of Expression Blend as well for graphical layouts. Not mandatory, but it helps.


And you’ll want these books:

C# 4.0 in a Nutshell: The Definitive ReferenceWPF 4 UnleasedLinq in ActionEntity Frameworks

Reactive Framework conflict (SOLVED)

The type ‘System.IObservable exists in both ‘c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll’ and ‘c:\Program Files (x86)\Microsoft Reactive Extensions\Redist\DesktopV2\System.Observable.dll’ (SOLVED)

During an upgrade of a C# WPF application that was using Reactive Extensions, I ran into this compile error:

The type ‘System.IObservable exists in both ‘c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll’ and ‘c:\Program Files (x86)\Microsoft Reactive Extensions\Redist\DesktopV2\System.Observable.dll’

This is roughly the same kind of Defined in Multiple Assemblies problem as I faced before. (Solution provided.)

In this case, the System.Observable.dll was pinned to the 3.5 release of the Reactive Extensions.

The solution was to:

  1. Download the .NET 4.0 version of Reactive Extensions (Rx_Net4.msi).
  2. Install it.
  3. Remove System.Observable from the project.
  4. Re-add the System.Observable to the project, being super careful to select the latest version

Error 0x80070057 (SOLVED)

Copy File

An unexpected error is keeping you from copying the file. If you continue to receive this error, you can use the error code to search for help with this problem.

Error 0x80070057: The parameter is incorrect.

SOLVED!

Went to copy a directory on Windows 7 from one drive to another, something that I had done quite frequently, even earlier that day.

However, this time, and nothing had changed substantially with the source files, I got an Error 0x80070057 message stating “The parameter is incorrect.” At that point the copy dialog from my simple drag and drop would allow me to retry (useless) or abort mid-copy.

The error message was unusually cryptic and less that helpful:

Copy File

An unexpected error is keeping you from copying the file. If you continue to receive this error, you can use the error code to search for help with this problem.

Error 0x80070057: The parameter is incorrect.

The disk was not full and a check disk revealed no errors.

THE SOLUTION
The destination directory name that I was copying into was pretty long, I basically had used a descriptive prefix, a date stamp of YYMMDDHHMMSS, by a space dash space, and a short descriptive comment. All in all it was about ~55 characters in length.

The directory I was copying from was a fairly deep structure.

That made me wonder if the fully qualified name of some directory path wasn’t exceeding some limit. On Windows, it appears to be 256 characters. On a Mac it appears to be 1023 characters.

Tricks aside, I was limited to the file system limits.

So, on the same disk, with the same files, immediately after yet-another-failure to copy, I renamed the destination folder to something considerably shorter and tried again.

Quick experimentation showed that was indeed the problem: the resulting path name formed during the copy was too long.

Solution: shorten the destination folder name and/or tighten up the path.

WPF Responsiveness Problem

Ran into an interesting problem where a WPF application was acting really, really, really slow. So slow that moving the application window was jumpy. Selecting items in a grid would take several seconds. Scrolling a list box of simple items would grind the CPUs for a while. And even typing in a regular text box was so delayed that I could type a word, sit back, and every few seconds a character would appear.

The problem turned out to be with the input stack at the operating system. Seems that the Pen / Tablet Driver was bringing the system to its knees, but only affecting WPF applications.

Disabling the driver and restarting the WPF application instantly showed colossal speed improvements for response time; the application responded near instantly. Re-enabling the driver while the application was running reverted the system to the broken state, although turning the driver back off did not bring the WPF application out of it’s slow like crawl. Restarting the WPF application resolved the problem, but the driver had to be disabled.

(Test conducted with WPF 3.5 SP 1 and Windows 7.)

Find and Replace in Word using C# .NET

Solution to how to do a global search and replace in MS-Word, including across floating text objects, in C#/.NET.

Heads up, this article contains high quantity of geek content. Non-geeks should move along.

I’ve been trying to use Microsoft.Office.Interop.Word to perform a global bulk search and replace operations across an entire document. The problem was, however, if a document contained a floating text box, which manifested itself as a shape object of type textbox, the find and replace wouldn’t substitute the text for that region. Even using Word’s capability to record a macro and show the VBA code wasn’t helpful, as the source code in BASIC wasn’t performing the same operation as inside the Word environment.

What I wanted was a simple routine to replace text anywhere inside of a document. If you Google for this you’ll get the wrong kind of textbox, the wrong language, people telling you not to use floating textboxes, and all kinds of weird story iterators.

One site seemed to have the solution; many kind thanks to Doug Robbins, Greg Maxey, Peter Hewett, and Jonathan West for coming up with this solution and explaining it so well.

However, the solution was in Visual Basic for Applications, and I needed a C# solution for a .NET project. Here’s my port, which works with Office 2010 and Visual Studio 2010 C#/.NET 4.0. I’ve left a lot of redundant qualifiers and casting on to help people searching for this article.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using Microsoft.Office.Interop.Word;

// BEGIN: Somewhere in your code
Application app = null;
Document doc = null;
try
{
  app = new Microsoft.Office.Interop.Word.Application();

  doc = app.Documents.Open(filename, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing);

  FindReplaceAnywhere(app, find_text, replace_text);

  doc.SaveAs(outfilename, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing, Missing);
}
finally
{
  try
  {
      if (doc != null) ((Microsoft.Office.Interop.Word._Document) doc).Close(true, Missing, Missing);
  }
  finally { }
  if (app != null) ((Microsoft.Office.Interop.Word._Application) app).Quit(true, Missing, Missing);
}
// END: Somewhere in your code             



// Helper
private static void searchAndReplaceInStory(Microsoft.Office.Interop.Word.Range rngStory, string strSearch, string strReplace)
{
    rngStory.Find.ClearFormatting();
    rngStory.Find.Replacement.ClearFormatting();
    rngStory.Find.Text = strSearch;
    rngStory.Find.Replacement.Text = strReplace;
    rngStory.Find.Wrap = WdFindWrap.wdFindContinue;

    object arg1 = Missing; // Find Pattern
    object arg2 = Missing; //MatchCase
    object arg3 = Missing; //MatchWholeWord
    object arg4 = Missing; //MatchWildcards
    object arg5 = Missing; //MatchSoundsLike
    object arg6 = Missing; //MatchAllWordForms
    object arg7 = Missing; //Forward
    object arg8 = Missing; //Wrap
    object arg9 = Missing; //Format
    object arg10 = Missing; //ReplaceWith
    object arg11 = WdReplace.wdReplaceAll; //Replace
    object arg12 = Missing; //MatchKashida
    object arg13 = Missing; //MatchDiacritics
    object arg14 = Missing; //MatchAlefHamza
    object arg15 = Missing; //MatchControl

    rngStory.Find.Execute(ref arg1, ref arg2, ref arg3, ref arg4, ref arg5, ref arg6, ref arg7, ref arg8, ref arg9, ref arg10, ref arg11, ref arg12, ref arg13, ref arg14, ref arg15);
}

// Main routine to find text and replace it,
//   var app = new Microsoft.Office.Interop.Word.Application();
public static void FindReplaceAnywhere(Microsoft.Office.Interop.Word.Application app, string findText, string replaceText)
{
    // http://forums.asp.net/p/1501791/3739871.aspx
    var doc = app.ActiveDocument;

    // Fix the skipped blank Header/Footer problem
    //    http://msdn.microsoft.com/en-us/library/aa211923(office.11).aspx
    Microsoft.Office.Interop.Word.WdStoryType lngJunk = doc.Sections[1].Headers[WdHeaderFooterIndex.wdHeaderFooterPrimary].Range.StoryType;

    // Iterate through all story types in the current document
    foreach (Microsoft.Office.Interop.Word.Range rngStory in doc.StoryRanges)
    {

        // Iterate through all linked stories
        var internalRangeStory = rngStory;

        do
        {
            searchAndReplaceInStory(internalRangeStory, findText, replaceText);

            try
            {
                //   6 , 7 , 8 , 9 , 10 , 11 -- http://msdn.microsoft.com/en-us/library/aa211923(office.11).aspx
                switch (internalRangeStory.StoryType)
                {
                    case Microsoft.Office.Interop.Word.WdStoryType.wdEvenPagesHeaderStory: // 6
                    case Microsoft.Office.Interop.Word.WdStoryType.wdPrimaryHeaderStory:   // 7
                    case Microsoft.Office.Interop.Word.WdStoryType.wdEvenPagesFooterStory: // 8
                    case Microsoft.Office.Interop.Word.WdStoryType.wdPrimaryFooterStory:   // 9
                    case Microsoft.Office.Interop.Word.WdStoryType.wdFirstPageHeaderStory: // 10
                    case Microsoft.Office.Interop.Word.WdStoryType.wdFirstPageFooterStory: // 11

                        if (internalRangeStory.ShapeRange.Count > 0)
                        {
                            foreach (Microsoft.Office.Interop.Word.Shape oShp in internalRangeStory.ShapeRange)
                            {
                                if (oShp.TextFrame.HasText != 0)
                                {
                                    searchAndReplaceInStory(oShp.TextFrame.TextRange, findText, replaceText);
                                }
                            }
                        }
                        break;

                    default:
                        break;
                }
            }
            catch
            {
                // On Error Resume Next
            }

            // ON ERROR GOTO 0 -- http://www.harding.edu/fmccown/vbnet_csharp_comparison.html

            // Get next linked story (if any)
            internalRangeStory = internalRangeStory.NextStoryRange;
        } while (internalRangeStory != null); // http://www.harding.edu/fmccown/vbnet_csharp_comparison.html
    }

}

Let me know if it worked for you; bug fixes and enhancements welcome.

Virtual Server Problems

I recently switched operating system vendors, and to my surprise when I went to port over the web content from one system to another, things didn’t go as smoothly as I had hoped. What used to be /etc/httpd was now /etc/apache2, and inside this directory files were organized differently that I was used to, and so forth. Still, I would have hoped moving from Apache2 on RedHat to Apache2 on Ubuntu would have been easier.

Empirical evidence was suggesting that all of my user’s virtual sites were working, but all of mine, no matter where I had them on the system, were reporting the error: You don’t have permission to access / on this server.

Here’s what was going on, primarily recounted so if I ever do this to myself in the future, I’ll know what to look for.

The virtual host files, which now appear in /etc/apache2/sites-available as *.conf files, had a slight difference. Some of them had this in their Directory directive:

    Order allow,deny
    allow from all

Mine did not. But, then again, some other websites did not as well. Turns out those directives were placed inside their .htaccess files.

Now, not all sites had the .htaccess file, and things had been working before without the explicit directive in each virtual host .conf file.

Turns out I had some how tromped on the default file, which contains a directive that looks like this:

    <Directory />

      Options FollowSymLinks
      AllowOverride None

    </Directory>

If it is not present, then all virtual hosts must explicitly allow access (via .htaccess or their .conf file).

This directive allows Apache to serve up any file the URL asks for… which one may not want to do. It seems the secure way is to edit the virtual host .conf files, and not rely on some default magic.

But, because that was in my old configuration long ago, and not in the new one, my virtual host .conf files didn’t have it, but my more modern ones for my users did. Depending on which template I used to base new sites off was how some sites worked and some didn’t.

After fixing this, I ran into a new problem. Some sites weren’t coming up still, but this time with permission errors.

When I migrated over the web content, it preserved user and group ownerships from the other system. These did not match the new Apache2 user and group on the new system.

However, I got lucky. There was no user/group mapping on the new system, which meant I could execute a find command to find and fix them. It looked something like this:

    find /home -nogroup -print
    find /home -nouser -print
    find /home -group 49 -exec chgrp www-data ‘{}’ \;

WebCams on OS X

Lots of cool software exists for webcams on OS X.

OS X is capable of using USB and Firewire cameras, with perhaps the most famous being the iSight, second to the Built-in iSight of Apple’s laptops.

Use other cameras!
But it turns out you can use a lot of third party cameras using the Macam driver.

Use multiple cameras!
If you’re using multiple cameras at once, say for security monitoring, you’re going to want to take a look at SecuritySpy, which has motion detection, time lapse, and the ability to view from a remote browser, plus many other features.

Barcode Reader!
EvoBarcode will let you use your camera as a bar code reader.

Web Streaming!
EvoCam will let you stream multiple cameras and push images to servers.

Stop Motion Photographer!
iStopMotion will help you make your own stop motion movies.

Real-time Special Effects!
iGlasses will enhance and alter your video feeds.

Drag’n’Drop Problems with Parallels 4

Since installing Snow Leopard, I can no longer Drag’n’Drop files from Windows to the hosting OS X environment, though the inverse works just fine. Is anyone else having this problem, because I’m not seeing much about it on the Parallel’s forums. I think the bug is real.

To say that I’m distrusting of Microsoft Windows’ security is putting things lightly. And when I’m in a situation where Microsoft’s anti-open standards force Microsoft as a necessity, I tend to use a virtual machine to sandbox its activities.

On Mac OS X, I use a wonderful product called Parallels, which has the added bonus of being able to drag’n’drop files and directories between the guest operating system (Windows) and the host operating system (OS X).

After installing the latest Snow Leopard (10.6), I found that while I could drag files into Windows from OS X, the reverse was no longer true. Dragging something from the Windows desktop out to the OS X desktop, which used to work in Leopard (10.5), simply results in nothing happening.

Parallels 4.x Shared Services Drag'n'Drop

Now, I’m aware that Apple did some pretty big changes under the hood in Snow Leopard. And, I’m aware that even the Finder got a fairly intensive overhaul. And, I’m even willing to accept that there might be bumps during the transition process, as the good folks at Parallels update their product to address little tidbits like this.

However, I’m kinda surprised that this kind of thing snuck past testing. Even more to my surprise is that I don’t hear many people talking about it. Such conclusions lead me to think that perhaps I have a local configuration issue.

But then I heard from another user of Parallels that updated to Snow Leopard. He ran into the same problem: Drag’n’Drop worked only in one direction now.

Most of the Snow Leopard fuss currently centers on the fact that Parallels 2.x and 3.x no longer work under Snow Leopard. Parallels made such a good and stable product that early users saw no need to update as it met their needs. However, Apple’s approach to operating systems is far more progressive than Microsoft’s, as they are willing to sacrifice backwards compatibility in software and hardware, if the technology is substantially old and the new benefits far outweigh the trouble. Thus, Apples tends to fix problems, rather than bandaid-ing workarounds; in the long haul everyone benefits with faster, smaller, more featured applications instead of bloatware.

However, I’m riding the Parallels 4.x wave on the bleeding edge. I’ve got the Parallels Tools installed. I’ve got the Enable Drag’n’Drop checked in the Shared Services config. Still, nothing.

I did a little digging around and found one user, Jamie Daniel, who was experiencing the same problem. As his question went unanswered, I tried myself.

I wrote an entry in the Parallels forum entitled Drag files from Guest to Host no longer working, detailing the problem.

And, while I was luckier than Jamie and got an answer, it was fairly clear someone gave a cursory glance and cut’n’pasted a response without reading what I was asking. In short that I did not want Windows to be able to read or write to any OS X drives. For, should Windows get a virus, I didn’t want it having free reign of the OS X filesystem to corrupt. Thus only I, via Drag’n’Drop, should be able to marshal content between the two environments.

Willing to accept the fact that I may have a configuration problem, despite being a power user of Parallels since day one, I am also willing to accept that this is simply a Snow Leopard compatibility issue that Parallels will soon be addressing. Problem is, I can’t seem to raise the issue to a level where someone can confirm or deny it.

Worse yet, I can’t seem to be able to login to Windows via the Finder anymore to mouse a Windows disk within OS X, where as I used to be able to do that as well. While workarounds, from using a USB disk (which mounts in both environments), DropBox, and using the Windows Guest account’s Parallel’s mount point, I’d really like the old capability back.

So, I ask, Parallels 4.x users that are using Snow Leopard, are you no longer able to drag from Windows to the OS X desktop?

If you can, how are you doing it?

If you can’t, please head over to the Parallels forum and let them know it’s broken for you as well. This is not an attack Parallels request, they’re good people — this is just to raise awareness to let them know the issue is real so they can look into it.

UPDATE 14-Sep-2009: Found a work around, but I’m not happy about it. What I don’t like about it is that it appears to expose Windows disks to OS X. While I trust OS X, the inverse does not appear to be necessary to perform a Drag’n’Drop from OS X to Windows. I’d expect the Enable Drag-and-Drop to be enough.

If you turn on the Share All Disks with OS X, then Drag’n’Drop from the Windows desktop to OS X Desktop works.

Parallels 4 Drag'n'Drop Hack

Snow Leopard: That Doesn’t Sound Like Apple

Had a very strange experience in the Apple Store in Reston, VA where I learned three very disturbing things. Snow Leopard purchasers beware. Hardware purchases, stop in your tracks.

I went to the Apple Store today with a friend that was looking at buying a MacMini and another friend that was picking up a copy of Snow Leopard, which sells for $29. That is, unless you’d like a copy for $25.

Apple’s policy toward operating systems has historically been a good one. There is no home, business, professional, expert, business, yadda-yadda-yadda flavors. There is no upgrade or full version. There is no pricing tier. Everything is one low price, you can upgrade or install fresh at any time.

And, if you buy a machine at the Apple Store it comes with the latest-and-greatest software, and if a new product on it comes out within 30-days, simply come back and pick up your updated version for either free or a very steeply discounted price. This is how it’s been at the Tyson’s Store for years. It shines of Apple customer service.

We went to the new Apple Store in Reston, VA and had the most disturbing news presented by Apple blue-shirt, John.

Unfortunately, I have no way of knowing at this time if what he told us is fact, fiction, or fallacy. So don’t take what you read here as gospel, but rather use it as guideline for formulating solid questions when you deal with Apple for the next few months.

#1) Apple had on display a Mac Box Set (OS X Snow Leopard, iLife ’09, and iWork ’09) for $169. My friend having iLife ’08 and iWork ’08 asked, “is it worth the cost to upgrade?” The Apple guy looked at us and said straight faced, “honestly, no… the features are minimal, just get Snow Leopard.” Now, I appreciate his honesty and opinion, and that alone commanded enough respect for me to retain trust in Apple — much like Macy’s sending people to Gimbel’s. However, I suspect we got lucky and that was not the Apple corporate line. Nor would pointing out you can get it for much less at about $114.

#2) We noticed the word “upgrade” all over the box and asked, “do you have to have Leopard installed to install this?” The answer, surprisingly, was yes. This was an upgrade and not a regular OS X disc like Apple historically has done. We were told that the real OS wasn’t coming out until December. Yes, December. When asked about machine recovery, he confessed they had a special version in the back they could use under dire emergencies. This begs the question if $29 is an upgrade price, with the ‘full’ OS will be the normal $120 later.

Update 31-Aug-2009: An Apple employee in BestBuy also confirmed what’s out now is an upgrade path. Although according to him, if you buy a new machine (with Leopard on it) you get the Snow Leopard update for free, which sounds like the Steve Jobs’s Apple policy we’re used to.

#3) When we asked about the MacMini, we were told that it had Leopard on it and that if we wanted Snow Leopard, we’d have to buy that for an additional $29. However, the electronic Apple Store online was selling MacMini’s with Snow Leopard already installed, without the extra cost. I probed deeply about this. Did the machines really have Leopard, and not Snow Leopard? Yes, the excuse was that they hadn’t moved inventory with the old OS on it. I asked if one simply got the upgrade for free like Tyson’s always used to do. Again, no. When I pointed out that buying online was the-cost-of-Snow-Leopard cheaper, I was met by an indifferent shrug.

All three of these things were very non-Apple.

Again, I don’t know if it was the sales person, the store in general, or Apple taking a page from the Microsoft book of marketing. But suffice it to say there was an abrupt halt on major purchases today.

Customers expect two things from a business, common sense and consistency. Price is often a very distance third.

A Side Note: Customer service plays a big role, and I have another Apple story which illustrates going above and beyond. In BestBuy, when we went to go get a copy of Snow Leopard, they were out of stock. However, while browsing another part of the store, the Apple employee came up and handed over a copy of Snow Leopard. Apparently, a FedEx shipment had just arrived, so he pulled one out of the box, and then hunted down our party in the whole store, on the off chance we hadn’t left yet. That’s service. You know that BestBuy’s floor staff would not have done that.