VMWare Fusion Daemon

I've got a Mac mini that I want to set up with a headless copy of VMWare that can run a virtual server.

To do that...

  1. Set up your VM in Fusion like you normally would. Configure it with the appropriate settings as appropriate--OS, processor, network, whatever. Get it set up now.
  2. Create a plist file called /Library/LaunchDaemons/com.vmware.selfhost.plist that look this:
            /Applications/VMware Fusion.app/Contents/Library/vmrun
            /Users/Shared/Virtual Machines/Windows Server 2012 R2.vmwarevm/Windows Server 2012 R2.vmx
  • Check permissions by running this command from the OS X terminal:
    ls -l /Library/LaunchDaemons/com.vmware.selfhost.plistYou should get output that looks like this:-rw-r--r--  1 root  wheel  787 Jan 13 01:44 com.vmware.headlessvm.plist
  • Set up the daemon using launchctl
    launchctl load /Library/LaunchDaemon//com.vmware.selfhost.plist
  • 2014-02-16

    hg permissions

    Don't forget to ...

    chmod -R 777 .hg

    Yeah. Permissions on the .hg directory.


    Mozilla, Idiots.

    So Mozilla announced today that in an effort to tighten security and improve performance, they will disable plugins in FireFox by default. I applaud them. The likes of Java and Acrobat have been crushing my computer for years. What's wrong, though, is they've left Flash enabled. (http://www.engadget.com/2013/01/31/java-silverlight-disabled-by-default-firefox/)

    I've been very vocal about my support for the future of the web. Html 5 is definitely the way of the future. Yeah, as a Microsoft developer, I'm saddened to see Silverlight die a slow miserable death (and/or become the Windows [Phone, Desktop] App Store platform of choice. Alas, Silverlight's time as a web app is numbered. So too is Flash's. In fact, Flash died on June 29th, 2007. Yet, here it is enabled, in FireFox by default, while all other plugins are gone.

    This isn't Mozilla alone. Back to my rant on Google. Why does Chrome force Flash down our throats, too? Chrome is almost my perfect browser, with only a handful of exceptions--Flash being the single biggest one.

    Developers, repeat after me.

    Flash is dead. STOP SUPPORTING FLASH.

    Mozilla--you guys are a bunch of morons.

    Google--you guys are a bunch of morons.

    Microsoft--I'm proud that you were able to leave Flash behind in the recent release of Windows. And Apple, with the iPhone. Kill Flash. Now.


    Google Part 1

    Let's talk tech. Google is a has been.

    Wait a minute? Did I really just type that on my Blogger account while using Chrome with Gmail open? Yes, yes I did.

    Flash back to last decade, and Google was an innovator. They were coming into the new millennium with a great search engine, and great new product offerings such as Gmail, Chrome, Voice, Calendar, and even Android. I should know. I use most of these every day. (Let's ignore for a moment that many of these techs were built by buying them).

    But there's been something that's bothered me with each new release. Bugs. Lots of them.

    Don't get me wrong, there is a lot of great stuff that's been done. Gmail is rock solid.Those are apps that really defined the new Web. Before Gmail, everyone was using Outlook or Outlook Express or the Mozilla client with some SMTP / POP3 service. Some folks had Hotmail. Some folks had Yahoo. But none of them really took the web clients seriously. Then Gmail came along. And everyone else was playing catchup. Sure, Google used the massive (at the time) 1GB of storage to lure people in, but really it was the quality App that made people stay.

    Calendar is another great service. Easy to use, very functional, and integrated with Exchange.

    But then it starts to fall apart. Along came this little service called Google Talk. Which I loved. To this day, it's still my favorite chat client. But, I've resorted to using Trillian again (which, I also love... just not as much as Google Talk). Why the switch? Because Google hasn't released a new Talk client in 6 years. Google still hasn't released an official Mac client. Google still hasn't integrated AIM into it--like they did in Gmail Web years ago. Nor have they yet to released Voice integration--like they did in Gmail Web years ago. Hell, Talk still lacks 2-factor authentication. Application Passwords anyone?

    Which, I suppose brings me to my next point. Google Voice is brilliant. Yes, yes, I know it's a fork of the old Grand Central code, which they bought out years ago. But they've really only had two releases of that since. The first was dropping that nasty Flash client that Grand Central had. The second was a couple of crummy mobile apps. I would seriously pay good money for Google Voice, but it's lacking some serious features. Here's a laundry list of things I'd love to see from it:

    • MMS Support (and not the lousy Sprint integration)
    • Three way calling
    • A better web client--one that functions more like Gmail
    • Better yet, fully integrate voice into Gmail. I don't like managing my messages in two places.
    • Business user support--that means give me the ability to have an "Office" number that rings to my cell phone, and don't restrict me--let me have my personal GV number that rings to  my cell phone, too.
    • Fax support. Yes, some places still prefer faxes.
    • Drop the Flash client for Gmail. It doesn't work. It crashes. And I can't install it/uninstall it from my Mac now--and it is in an unusable state.
    • A better iOS app--and yes, I know, part of that is Apple's fault.

    Which, I guess brings me to the mobile apps. I could go on and on about their mobile apps. Gmail on iOS is a wreck. Gmail on Android is barely usable as is. The Authenticator app doesn't work on my iPhone. Don't ask me why. Goggles is awful. Plus isn't bad, though...

    But, you ask, why am I griping about Google today? Youtube. Yeah, yeah, I  know Google bought Youtube. The website isn't my problem (I've got a few complaints, but I'll save 'em for now...). The mobile apps.

    When I first bought a smartphone, I bought the iPhone 3G. And Youtube was very usable on it. Even on 2G. Somehow, that old phone would buffer and playback videos without any problems. Then I got an Android. And that Youtube app--on T-mobile's 4G (HSPA+) had so many problems buffering video. And so did the next Android I got. And the next one. My signal never seemed to matter. I could navigate the web like a boss. I could download MP3s, stream from Google Music, do whatever. T-Mobile wasn't the problem. But that lousy Youtube app would stutter and skip and fail to buffer time and time again.

    And then I switched back to iOS with the iPhone 5. That old iOS Youtube app was gone. So, I downloaded Google's app. And behold, this one does the same thing.

    So what's going on here? Does Google have a lousy HTTP stack built into their Youtube app? Was the iOS app better at buffering before it started playback? Maybe we're getting to the root of my problems with Google. Do they test their software before releasing it? Do they try to make it work? Or do they just push it on us? Are Apple's programmers that much better? Or are Google's programmers just that lazy.

    I don't know. But what I can tell you is that the bugs that I find in Google's software is what really irks me most about this company. And my experiences from Google lately have really been wearing my patience thin. Sure, we're in a Web 2.0 (or 3.0, if you must) world. But bugs are bugs are bugs. Beta ain't my problem.


    SQL -> MongoDB Tips

    For those of you migrating from SQL to Mongo, here are a few common types of queries. This list is very incomplete. But, I'll ne'er get the proper time I need to complete it.

    Text Queries

    When querying string, mongo relies on the very powerful RegEx format, and you can construct complex text queries that way.
    ·         {"Text_FieldName":"Exact value"}
    ·         {"Text_FieldName":/contains value/}

    If you were to write the above queries in SQL, they might look like this:
    ·         SELECT * FROM Table WHERE Text_FieldName = ‘ExactValue’
    ·         SELECT * FROM Table WHERE Text_FieldName LIKE ‘%contains value%’


    When querying numbers, you can do equalities and operand comparisons (http://docs.mongodb.org/manual/reference/operators/)
    ·         Equals:
    ·         {"Numeric_FieldName":12345}
    ·         Not Equals:
    ·         {"Numeric_FieldName": { $ne: 20 }}
    ·         Less Than:
    ·         {"Numeric_FieldName": { $lt: 20 }}
    ·         Less Than or Equals:
    ·         {"Numeric_FieldName": { $lte: 20 }}
    ·         Greater Than:
    ·         {"Numeric_FieldName": { $gt: 20 }}
    ·         Greater Than or Equals:
    ·         {"Numeric_FieldName": { $gte: 20 }}

    If you were to write the above queries in SQL, they might look like this:
    ·         SELECT * FROM Table WHERE Numeric_FieldName = 12345
    ·         SELECT * FROM Table WHERE Numeric_FieldName != 12345
    ·         SELECT * FROM Table WHERE Numeric_FieldName < 12345
    ·         SELECT * FROM Table WHERE Numeric_FieldName <= 12345
    ·         SELECT * FROM Table WHERE Numeric_FieldName > 12345
    ·         SELECT * FROM Table WHERE Numeric_FieldName >= 12345


    ·         {"Boolean_FieldName":true}
    ·         {"Boolean_FieldName":false}
    If you were to write the above queries in SQL, they might look like this:
    ·         SELECT * FROM Table WHERE Boolean_FieldName = true
    ·         SELECT * FROM Table WHERE Boolean_FieldName = false


    ·         {"Date_FieldName": {"$gte": new Date(2010,3,1), "$lt": new Date(2011,3,1)}}
    If you were to write the above queries in SQL, they might look like this:
    ·         SELECT * FROM Table WHERE Date_FieldName BETWEEN ‘2010-03-01’ AND ‘2011-03-01’


    Why Would Anyone Use Cygwin?

    So, while browsing Lifehacker today, I came across an article (http://lifehacker.com/5807358/how-to-get-mac-os-xs-best-features-on-windows) that focused on using some of OS X's nicest features in Windows.

    They suggested that using a *nix command line processor would make you feel right at home. I scratched my head as they said that, as Cygwin has given me grief over the years. It doesn't quite behave like a good ol' *nix shell, yet it doesn't behave like something in Windows it should. I've seen bugs with Grep and RegExes, to name a couple frustrations. Turns out, thought, I'm not alone...
    Why anyone would use a poorly ported bash shell in Windows as opposed to the absolutely remarkable Windows Powershell is beyond me. PowerShell gives you the full power of the .NET framework, WMI, and ActiveXObjects directly from the command prompt. I'm sorry but cygwin just can't compete (on any level) with the native Windows Powershell.
    Bill Clark approved this comment
    Bill and Neal are right. PowerShell is amazing. Microsoft has a winner with that tech... As I'm sure you've already seen by reading this blog, I love PowerShell.

    Alas, Zoidberg away!


    Mustache Templates

    Time again to post a link to something I need to read up on.

    Mustache provides functionality for merging JSON into HTML templates. Must research.



    SQL Server -> MongoDB - Foreign Keys

    MongoDB, and for that matter, other nosql databases, is a new beast for many developers. Foreign Keys is a concept that may need to be implemented in Mongo, although, before you explore this route, I highly encourage you to try to embed sub-information in your document rather than try to relate it. NoSQL engines do a beautiful job of persisting whole objects.

    Regardless, you'll at some point, run into a scenario where it doesn't make sense to keep embedding documents into other documents. And a DBRef probably makes sense. Read more about 'em here. The folks at mongodb.org recommend that, when you can, you use manual references ("Unless you have a compelling reason for using a DBRef use manual references."). This is an example of a manual reference:

    original_id = ObjectId()
        "_id": original_id
        "name": "Broadway Center"
        "url": "bc.example.net"
        "name": "Erin"
        "places_id": original_id
        "url":  "bc.example.net/Erin"

    But you can also do a DBRef, doing embedding something like this in your document:

    { $ref : <value>, $id : <value>, $db : <value> }

    And apparently the order of the fields matter.

    Also, apparently the C# Driver offers support for DBRefs--which may be nice than manual refs. Helper functions and what not.

    That's all there is. Zoidberg away!


    Subversion Merges

    If you ever need to update your branch with the latest from the trunk, you can perform this command:
    c:\branches\yourbranch> svn merge svn://sourcecontrolserver/svn/Repo/trunk .
    Where c:\branches\yourbranch is the working folder of your branch, svn://sourcecontrolserver/svn/Repo/trunk is the server side path to the trunk, and . is the current Windows folder (which in this case, is your working folder of your branch)

    Viola. Hope you don't have any merge issues.

    Zoidberg away!


    Powershell Scripts for Source Control

    The following scripts should help you identify which files you want to remove from your source control engine...

    gci c:\bleak -include *.suo, *.user -Recurse -name | out-file ToRemove.txt
    gci c:\bleak -include *.user -Recurse -name | out-file ToRemove.txt -append
    gci c:\bleak -include bin -Recurse -name | out-file ToRemove.txt -append
    gci c:\bleak -include obj -Recurse -name | out-file ToRemove.txt -append
    gci c:\bleak -include *.orig -Recurse -name | out-file ToRemove.txt -append

    If you really wanted to get fancy, you could then loop through all of the lines and add something like... hg remove .

    Get-content ToRemove.txt | foreach-object {add-content remove.ps1 "hg remove $_" }

    Happy coding.

    Zoidberg away!


    Source Control Woes and Resolutions

    So a follow up to my Source Control woes from the past post.

    First off, Mountain Lion has changed some of Apache's previous configuration settings--which would explain why it seemed like my changes only sometimes worked. So the lesson here, is if you're using Mountain Lion Server, Apache is configured to use the following location for your .conf files:
    Notably, there's the standard httpd.conf, as well as website specific configs in the sites folder. This is also stark contrast from my previous Lion-upgraded-from-Snow-Leopard folder of...
    Now that that's out of the way, configuration is relatively straight forward. Or is it? Well, it turns out, Subversion (and the Subversion server) are not installed (and actually Uninstalled with the upgrade) with Mountain Lion. So... once I figured out how to get Apache to accept my changes, I then I had figure out how the hell to reinstall Subversion. I hate having the grab some source and/or tar.gz files and run a few make commands--nor do I really want to install macports, homebrew, or fink. It turns out, there's a relatively simple way to reinstall the files you need!

    1. Open XCode
    2. Click XCode (menu) -> Preference
    3. Click on the Downloads Tab
    4. Install Command Line Tools
    And viola--115 meg download later, and Subversion is reinstalled on your Mac. And turns out, so are the apache .so files. Well. One of the two. It turns out that auth_svn_module isn't installed. I won't lie. I don't really know what this does. Nor do I really care for tonight. Turns out, I can browse my file structure without it so, hurray! (I haven't tried writing yet.)

    So for those naysayers out there who are sick of me not posting my code... at the bottom of my httpd.conf file, I've tucked this in...
    LoadModule dav_svn_module /usr/libexec/apache2/mod_dav_svn.conf

      DAV svn
      SVNPath /Path/To/Subversion/Repo1
    You may need to chmod and/or chown if necessary. You know the drill. Now, on to the fun stuff.

    So, now that I'm successfully sick of apache, vi, httpd.conf, and for that matter--all .conf files, I figure I'm going to try to do as much as I can in OS X's Server.app...

    So, I grab the latest version of Mercurial (HG) and install it. After some tutorials later, I determined using Terminal to create repos was great and all-but better yet, let's set up a Mercurial server in Apache...

    So within Server.app, I create my Mercurial Website by doing this...
    1. Navigate to Websites...
    2. Click the plus button
    3. Fill in my domain name... in fact... let's use a Subdomain! source.example.com
    4. Any IP Address. Port 80... Actually...
    5. Let's use an Cert (and the port automagically changes to 443...)
    6. Store files in... wherever. I'm going to manually alias something...
    7. Who can Access... Oooh... I get to choose Open Directory groups... (this is much nicer than vi...)
    8. And. Done.
    Now that I've successfully created a website... I can try hitting https://source.example.com, and viola! It prompts me for a UID and PW. Way to go Apple... I'm relatively impressed with the mostly unimpressive Server.app...

    So, digging deep into my HDD (hey... I haven't yet upgraded this to an SSD...), I find myself navigating to the depths of the underworld of .conf files here...
    And low and behold, I find this beautiful file there named...
    And I decide to add...
    WSGIScriptAlias / /var/hg/hgweb.wsgi
    And of course the text of that file looks something like this...
    config = "/var/hg/hgweb.conf"
    import cgitb; cgitb.enable()
    from mercurial import demandimport; demandimport.enable()
    from mercurial.hgweb import hgweb
    application = hgweb(config)
    Of course, you'll actually want to download that text from somewhere with better documentation than me. So DON'T RELY ON ME FOR THAT TO BE ACCURATE... At least at 1AM on an incoherent Saturday night... (no, really, though, go here for details http://mercurial.selenic.com/wiki/HgWebDirStepByStep#Configuring_Apache_with_mod_wsgi)

    And another thing not to rely on me for is your hgweb.conf file. Which looks something like this...
    /repo1 = /var/hg/repos/repo1
    baseurl = /
    But again, it's 1am, and I'm incoherent at this point... (No really, go here... http://mercurial.selenic.com/wiki/HgWebDirStepByStep#Preparing_the_config)

    And restart your web server. Oh. And whatever you do, do not use the following command...
    sudo apachectl restart
    Apparently that's bunk for OS X Server there days. Who knew? Try this instead:
    sudo serveradmin web stop
    sudo serveradmin web start
    sudo serveradmin settings web
    Sorry. Stop and Start. Restart may work. Settings is interesting. Seriously, though, read up. http://www.justinrummel.com/10-8-mountain-lion-server-what-changed/. Stuff's changed that I didn't know about. In fact, that would explain why my tinkering with Apache up until now felt like my changes weren't making it--they weren't.

    And I'm incredibly tired. But I needed to document some of these ravings-of-a-lunatic before I crash and forget them all.

    Zoidberg away!


    Upgrading to OS X 10.8 (Mountain Lion) and Subversion Server

    Quick warning for everyone out there--performing an upgrade from OS X 10.7 (Lion) to 10.8 (Mountain Lion) will drop your Subversion setup. Expect to lose a lot from your /etc/apache2 folder, including your subversion settings.

    I'm working on re-preparing my server, and at this time I haven't planned a strategy. I might rebuild a new Subversion server, or I may choose to use another source control engine--Mercurial and GIT both have their appeal. Details will follow once I have a strategy.

    Zoidberg away!

    Update: I have found a resolution and posted it here. http://ubercode.bleakllc.com/2012/09/source-control-woes-and-resolutions.html


    Charting Tools in HTML with SVG

    I've been looking at charting tools lately for HTML + SVG, and I've come across these guys... I like it. Licensing is a bit more than my usual post on here, but it's not bad, really...


    Productivity != Time Management

    Thanks David Kadavy for this great quote:
    "Productivity is less about time management than it is about mind management."
    Truth, that.



    Update: The Cost of a C# License

    An update to my earlier post, it seems that there are some developers who agree that C# is a better alternative to Java...



    The Cost of a C# License

    I came across an interesting article today about the cost of a C# license. Good read...


    Thanks Bradley for an interesting read. It's nice to know folks are thinking about this, and this is definitely interesting insight.

    Keyboard Shortcut of the Day

    Control + Shift + I.

    • Outlook -> Go to Inbox
    • Chrome -> Open Developer tools.
    I'm sure it does stuff elsewhere, too. Have fun!

    Zoidberg away!


    Powershell File Copy - Tip of the Day

    You can quickly, conveniently copy a file using the following command:



    What questions do you wish your co-workers had asked candidates in the interview process, whether to identify strengths/ weaknesses, gaps in knowledge, personality issues, and so forth?

    Interview questions. That's a great question. Unfortunately there's no right or wrong answer. A lot of hiring tech folks have switched to a more behavioral-style interviewing questions rather than a pile of technical questions. I've heard arguments for and against both sides, and there's merit to both. I've been on both sides of the table, and here are some of my favorite questions...

     - **What's your favorite Visual Studio keyboard shortcut? Why?** This is a great question because it's not technically deep, but it shows that there's an understanding of how to use the tools that they work with every day. Someone who shows a mastery of the tools they use is usually a better candidate than someone who shows a mastery of a programming language... they're usually more prone to cranking out code that works rather than going through the theoretical computer science type solutions (there are exceptions). If you're interviewing for non-Microsoft and/or non-developer folks, you can change that up by asking something about their preferred IDE and/or toolset.
     - **Can you describe three design patterns? When might you use them? Why are they important for developers?** Design patterns are great questions to ask developers. Junior and even most Mid Level developers will seldom be able to answer this completely, and that might well be okay. Remember that when someone knows patterns, they're more prone to being able to communicate their efforts with other developers.
     - **Can you describe your debugging process.** This is an open ended question that allows the interviewee to speak to how they use their tools every day. There are a dozen right answers to this, and depending on their background, they could be using the tools in the IDE and/or browser and/or disassembler and/or... the list goes on. It may be foreign to you, but what's most important is that they are able to articulate how they work/think, and that they are reasonably capable of tackling problems that come their way.
     - **What databases have you worked with? What's your favorite? Why?** This may or may not be asked for some developers, but it's a great leading question to allow them to pontificate more on their toolset. See above.
     - **What's something that you are passionate about?** Don't ask any more than that. You don't want to ask personal questions in an interview for legal reasons. But the question should invoke a flurry of emotion in the interviewee... and usually it'll lighten the mood. Interviews are tough, and when someone can talk about something they're passionate about, they'll relax, and you can see who they really are.
     - **Can you create a entity relationship diagram for Problem X. Explain your answer.** Where Problem X is something simple... four or five tables with a little bit of normalization. Remember, most ERDs have no single right or wrong answer, but there are definitely ones that are more or less correct.
     - **Can you tell me where you see yourself in X years?** The answer really isn't important in this one. They might say architect or manager or developer or cowboy. It doesn't really matter. What's important is that they have a career goal and objectives and a plan. As an effective manager, you can motivate someone by helping them achieve their goals, and a motivated employee is an employee that produces. Remember: this is a tough question, and not everyone will be expecting it. If someone can't answer, it doesn't necessarily reflect negatively on them, but if over the rest of the interview they are unable to procure any signs of self-motivation, they may be a difficult hire.

    This is just a small sample of the questions I've used over the years. Don't forget to dive in as technically deep as you see fit, but I think these relatively open-ended questions that provide a baseline for many technical roles.


    Code Contribution: T-SQL INSERT Generator

    Good news everybody! Today, I am releasing a helpful T-SQL Script that I use for generating test data from another environment. You'll run this SQL Script against an existing database table with data that you'd like to replicate. It'll generate an INSERT statement that inserts data using a collection of SELECT, UNION ALL clauses.

    Here are the important things to know when using this Script:

    1. It will run for all data in your table. Large tables can take forever. I've tested this for ~8000 or so records with success (slow, but success). I've added some safeguards to minimize any database performance hits including the use of NOLOCK, and prompting you with a a nice warning before executing.
    2. At the very top, is @TableSchema and @TableName, you'll want to assign those as appropriate. I use INFORMATION_SCHEMA.COLUMNS and INFORMATION_SCHEMA.TABLES heavily in this script, so any objects that you'll want to tinker with will need to be available in those system views.
    3. There's a @Debug variable that when active, turns on a few extra datasets and print statements. This may be helpful if you're doing any major work to this.
    4. By default, this PRINTs out the INSERT script. You'll want to copy and paste this into another window, most likely.
    5. There are a handful of data types that I have not tested/supported. Here are the ones that I have tested with:
      'char', 'nchar', 'nvarchar', 'varchar', 'bigint', 'decimal', 'float', 'int', 'money', 'numeric', 'smallint', 'tinyint', 'real', 'uniqueidentifier', 'datetime', 'smalldatetime', 'bit'
      Some notable exceptions include text, ntext, varbinary, and timestamp, and I'm sure there are others out there.
    6. The output can be large. You might be better served by running the INSERT script from a command prompt rather than SQL Management Studio. There was one 2gb file that I could not run from anything but the command prompt.
    7. This is released with no defined license, warranty, or EULA. Use it how you'd like, as you'd like, and modify it as you may. I won't / can't support it, but I hope that my example proves helpful to you.
    Conversely, I'd like to at some point add support to SQL 2008's upsert functionality...

    Here's the code!
    DECLARE @TableSchema VARCHAR(50)
    , @TableName VARCHAR(50)
    , @DEBUG BIT

    -- SETUP
    SET @TableSchema = 'dbo'
    SET @TableName = 'CustomObject'
    SET @DEBUG = 0

    -------------- DO NOT MODIFY ANYTHING BELOW THIS LINE --------------
    IF OBJECT_ID('tempdb..#DataExtractWarning') IS NULL
    -------------- Warning Message --------------
    CREATE TABLE #DataExtractWarning ( RecordCount BIGINT )
    EXECUTE ('INSERT INTO #DataExtractWarning ( RecordCount ) SELECT COUNT(*) FROM [' + @TableSchema + '].[' + @TableName + ']')
    DECLARE @RecordCount BIGINT
    SELECT @RecordCount = RecordCount
    FROM #DataExtractWarning
    PRINT 'WARNING: You are trying to extra data from [' + @TableSchema + '].[' + @TableName + ']'
    PRINT 'This will query approximately ' + CAST(@RecordCount AS VARCHAR(50)) + ' records, and will likely involve quite a bit of waiting'
    PRINT 'Recommendation: Specify Results to File'
    PRINT 'Proceed with EXTREME caution'
    PRINT '... Press F5 to Continue ...'
    -------------- Actual work --------------
    DECLARE @ColumnCount BIGINT
    , @FirstColumn VARCHAR(50)

    WHERE col.TABLE_SCHEMA = @TableSchema
    AND col.TABLE_NAME = @TableName

    @FirstColumn = col.COLUMN_NAME
    WHERE col.TABLE_SCHEMA = @TableSchema
    AND col.TABLE_NAME = @TableName

    DECLARE @Selects TABLE
    tsql VARCHAR(MAX)

    INSERT INTO @Selects
    ( tsql )
    SELECT 'ROW_NUMBER() OVER (ORDER BY [' + @FirstColumn + ']) AS RowNumber'
    CASE WHEN col.DATA_TYPE IN ( 'char', 'nchar', 'nvarchar', 'varchar', 'bigint', 'decimal', 'float', 'int', 'money', 'numeric', 'smallint', 'tinyint', 'real', 'uniqueidentifier', 'datetime', 'smalldatetime', 'bit' )
    ' ' + CASE WHEN col.ORDINAL_POSITION > 1 THEN '+ ' ELSE ',''SELECT '' + ' END +
    WHEN col.DATA_TYPE IN ( 'char', 'nchar', 'nvarchar', 'varchar' )
    THEN ''''''''' + REPLACE([' + col.COLUMN_NAME + '], '''''''', '''''''''''') + '''''''''
    WHEN col.DATA_TYPE IN ( 'bigint', 'decimal', 'float', 'int', 'money', 'numeric', 'smallint', 'tinyint', 'real' )
    THEN 'CAST([' + col.COLUMN_NAME +'] AS NVARCHAR(50))'
    WHEN col.DATA_TYPE IN ( 'image', 'varbinary' )
    THEN ''
    WHEN col.DATA_TYPE IN ( 'uniqueidentifier' )
    THEN ''''''''' + CAST([' + col.COLUMN_NAME + '] AS NVARCHAR( 50)) + '''''''''
    WHEN col.DATA_TYPE IN ( 'datetime', 'smalldatetime' )
    THEN ''''''''' + CONVERT(varchar, [' + col.COLUMN_NAME + '], 126) + '''''''''
    WHEN col.DATA_TYPE IN ( 'bit' )
    THEN 'CAST([' + col.COLUMN_NAME + '] AS NVARCHAR(50))'
    WHEN col.DATA_TYPE IN ( 'text', 'ntext', 'xml' )
    then ''
    WHEN @DEBUG = 1
    THEN '/*' + col.DATA_TYPE + '*/'
    ELSE ''
    WHEN col.DATA_TYPE IN ( 'char', 'nchar', 'nvarchar', 'varchar' ) --'text', 'ntext', 'xml' 
    THEN 'CASE WHEN [' + col.COLUMN_NAME +'] IS NOT NULL THEN '''''''' + REPLACE([' + col.COLUMN_NAME + '], '''''''', '''''''''''') + '''''''' ELSE ''NULL'' END'
    WHEN col.DATA_TYPE IN ( 'bigint', 'decimal', 'float', 'int', 'money', 'numeric', 'smallint', 'tinyint', 'real' )
    WHEN col.DATA_TYPE IN ( 'image', 'varbinary' )
    THEN ''
    WHEN col.DATA_TYPE IN ( 'uniqueidentifier' )
    THEN 'CASE WHEN [' + col.COLUMN_NAME +'] IS NOT NULL THEN '''''''' + CAST([' + col.COLUMN_NAME +'] AS NVARCHAR(50)) + '''''''' ELSE ''NULL'' END'
    WHEN col.DATA_TYPE IN ( 'datetime', 'smalldatetime' )
    THEN 'CASE WHEN [' + col.COLUMN_NAME +'] IS NOT NULL THEN '''''''' + CONVERT(varchar, [' + col.COLUMN_NAME + '], 126) + '''''''' ELSE ''NULL'' END'
    WHEN col.DATA_TYPE IN ( 'bit' )
    WHEN col.DATA_TYPE IN ( 'text', 'ntext', 'xml' )
    then ''
    WHEN @DEBUG = 1
    THEN '/*' + col.DATA_TYPE + '*/'
    ELSE ''
    ELSE ''
    END + 
    CASE WHEN col.ORDINAL_POSITION < @ColumnCount THEN ' + '', '' + ' ELSE ' AS [select]' END
    WHERE col.TABLE_SCHEMA = @TableSchema
    AND col.TABLE_NAME = @TableName


    SELECT 'FROM [' + tab.TABLE_SCHEMA + '].[' + tab.TABLE_NAME + ']  WITH (NOLOCK)'
    WHERE tab.TABLE_SCHEMA = @TableSchema
    AND tab.TABLE_NAME = @TableName

    --SELECT ')'

    SELECT @tsql = COALESCE(@tsql + ' 
    ', '') + tsql
    FROM @Selects

    IF @DEBUG = 1
    SELECT * FROM @Selects
    PRINT @tsql

    DELETE FROM @Selects

    INSERT INTO @Selects

    SELECT 'INSERT INTO [' + tab.TABLE_SCHEMA + '].[' + tab.TABLE_NAME + ']'
    WHERE tab.TABLE_SCHEMA = @TableSchema
    AND tab.TABLE_NAME = @TableName
    SELECT '('
    CASE WHEN col.DATA_TYPE IN ( 'char', 'nchar', 'nvarchar', 'varchar', 'bigint', 'decimal', 'float', 'int', 'money', 'numeric', 'smallint', 'tinyint', 'real', 'uniqueidentifier', 'datetime', 'smalldatetime', 'bit' )
    THEN ''
    ELSE '-- [Currently Unable to Export ' + col.DATA_TYPE + ']'
    END + 
    CASE WHEN col.ORDINAL_POSITION > 1 THEN ',' ELSE '' END + ' [' + col.COLUMN_NAME + ']'
    WHERE col.TABLE_SCHEMA = @TableSchema
    AND col.TABLE_NAME = @TableName
    SELECT ')'

    IF OBJECT_ID('tempdb..#T1') IS NOT NULL
    CREATE TABLE #T1 ( rownum BIGINT , tsql varchar(MAX) )
    EXECUTE (@tsql)

    SELECT @MaxValue = MAX(rownum) FROM #T1 WITH (NOLOCK)

    INSERT INTO @Selects
    ( tsql )
    WHEN rownum <> @MaxValue
    THEN tsql + ' UNION ALL'
    ELSE tsql

    IF @DEBUG = 1
    SELECT * FROM @Selects

    --SELECT * FROM @Selects


    DECLARE outputcursor CURSOR FOR 
    SELECT tsql
    OPEN outputcursor;
    FETCH NEXT FROM outputcursor INTO @Output;

    IF @@FETCH_STATUS <> 0 
    PRINT '         <>' ;

    PRINT @Output
    FETCH NEXT FROM outputcursor INTO @Output;

    CLOSE outputcursor
    DEALLOCATE outputcursor

    IF OBJECT_ID('tempdb..#DataExtractWarning') IS NOT NULL
    DROP TABLE #DataExtractWarning
    Enjoy! Zoidberg away!