October 2006 - Posts - Jon Galloway

October 2006 - Posts

Showing a Connection String prompt in a WinForm application

datalink

When I was putting together the Data Dictionary Creator program, I needed to allow users to input a connection string. A lot of winform applications that require data connections give you a textbox and tell you to figure it out yourself, but I really wanted to show a prompt that let you test your connections, select databases on a server, etc.

I was surprised that I couldn't find a nice, free, winform control to build a connection string. I found something on CodeProject with a smart solution - it pops up the standard Data Link Properties dialog. The code mostly worked, but had some problems (passwords were lost if user didn't check "Allow Saving Password", problems with integrated security). I found some general suggestions in the comments and newsgroup postings and threw in some exception handling, and came up with something that worked pretty well for me. It's a little trickier than it looks, since setting certain properties in just the right order shifts the dialog into modes which hide tabs and stuff.

This requires references to a few COM objects:

%PROGRAMFILES%\Microsoft.NET\Primary Interop Assemblies\adodb.dll
%PROGRAMFILES%\Common Files\System\Ole DB\OLEDB32.DLL

I found an article about using CreateObject or GetTypeByProgID to avoid the interop references, I think I'd rather ship the interop stubs than worry about dynamic object calls failing when I'm shipping an application, but it's interesting.

The next step for this would be bundle this up in a user control (textbox with an ellipses button to launch the dialog, maybe a balloon tip to show connection errors), but I'm not sure I'll get to that any time soon. Here's the code as a simple function that pops the dialog and returns the selected connection string: 

/// <summary> /// Displays a Connection String Builder (DataLinks) dialog. /// /// Credits: /// http://www.codeproject.com/cs/database/DataLinks.asp /// http://www.codeproject.com/cs/database/DataLinks.asp?df=100&forumid=33457&select=1560237#xx1560237xx /// /// Required COM references: /// %PROGRAMFILES%\Microsoft.NET\Primary Interop Assemblies\adodb.dll /// %PROGRAMFILES%\Common Files\System\Ole DB\OLEDB32.DLL /// </summary> /// <param name="currentConnectionString">Previous database connection string</param> /// <returns>Selected connection string</returns> private string PromptForConnectionString(string currentConnectionString) { MSDASC.DataLinks dataLinks = new MSDASC.DataLinksClass(); ADODB.Connection dialogConnection; string generatedConnectionString = string.Empty; if (currentConnectionString == String.Empty) { dialogConnection = (ADODB.Connection)dataLinks.PromptNew(); generatedConnectionString = dialogConnection.ConnectionString.ToString(); } else { dialogConnection = new ADODB.Connection(); dialogConnection.Provider = "SQLOLEDB.1"; ADODB.Property persistProperty = dialogConnection.Properties["Persist Security Info"]; persistProperty.Value = true; dialogConnection.ConnectionString = currentConnectionString; dataLinks = new MSDASC.DataLinks(); object objConn = dialogConnection; if (dataLinks.PromptEdit(ref objConn)) { generatedConnectionString = dialogConnection.ConnectionString.ToString(); } } generatedConnectionString = generatedConnectionString.Replace("Provider=SQLOLEDB.1;", string.Empty); if ( !generatedConnectionString.Contains("Integrated Security=SSPI") && !generatedConnectionString.Contains("Trusted_Connection=True") && !generatedConnectionString.Contains("Password=") && !generatedConnectionString.Contains("Pwd=") ) if(dialogConnection.Properties["Password"] != null) generatedConnectionString += ";Password=" + dialogConnection.Properties["Password"].Value.ToString(); return generatedConnectionString; }

Reading the SQL 2005 instance and installation directory from a DOS batch file

SQL 2005 installs each instance to a numbered directory based on the order installed: MSSQL.1, MSSQL.2, etc. That makes scripting a little tricky. Fortunately, you can find them in the registry.

The install path for the SQL 2005 database server is here:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\SQL2005\Setup\SQLPath

You can look up specific instances in the the Instance Names registry node. For instance, to find the SQL2005 instance, you'd look at this key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL\SQL2005

Looking up registry values in a DOS batch file is a little tricky. Fortunately, Robert VanderWoude has a great tip for reading registry values via creative use of the FOR /F command.

So, with all that out of the way, we can read the SQL Server instance with this line:

FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL" /v SQL2005') DO SET SQLINSTANCE=%%B

and the SQL Server base installation directory with this:

FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\SQL2005\Setup" /v SQLPath') DO SET DATADIRECTORY=%%B\Data

Why would you want to read that kind of stuff in a batch file? Well, to write a Batch files to check SQL 2005 (MDF) files in and out of Subversion source control, or course.

Posted by Jon Galloway | with no comments

Batch files to check SQL 2005 (MDF) files in and out of Subversion source control

Here are a few batch files I whipped up to help our team keep development databases in sync with our Subversion repository. These handle detach / reattach from the database, so running the checkout script has us the latest version in the repository in twenty seconds.

These scripts rely on 7-zip to compress / decompress the MDF file to speed up the checkin / checkout. You can download 7-zip here, or you can modify the scripts if you want to use another commandline compression program.

There are a few things you're going to have to fill in (marked by ***FILL-IN***), but I've done my best to fill in what I can - for instance, I'm defaulting the data directory based on the SQL 2005 install directory in the registry. You can override any of the variables if your data directory's on another drive or something.

1. Update from SVN, unzip, and attach to database

@ECHO OFF
::Name of database you're connecting to
SET DATABASENAME=***FILL-IN***
::Database instance
SET SERVER=%COMPUTERNAME%\***FILL-IN***
::Path to your subversion repository
SET SVNPATH=svn://***FILL-IN***
SET WORKINGDIRECTORY=%~dp0
::Set the directory you'll be checking the MDF file out to. Defaults to current directory.
SET WORKINGDIRECTORY=C:\Projects\***FILL-IN***\Trunk\
SET DATADIRECTORY=C:\Program Files\Microsoft SQL Server\MSSQL.4\MSSQL\Data
FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\SQL2005\Setup" /v SQLPath') DO SET DATADIRECTORY=%%B\Data

TITLE Checking out latest version of %DATABASENAME% database
ECHO Updating from source control
PUSHD %WORKINGDIRECTORY%
SVN update
"%SVNPATH%/%DATABASENAME%.mdf.zip"

ECHO Decompressing database (MDF) file
"%PROGRAMFILES%\7-zip\7z.exe" e -y %DATABASENAME%.mdf.zip

ECHO Detaching database
osql -E -S %SERVER% -d master -Q
"alter database [%DATABASENAME%] set single_user with rollback immediate"
osql -E -S %SERVER% -d master -Q
"sp_detach_db '%DATABASENAME%'"

ECHO Copying database (MDF) file
move "%WORKINGDIRECTORY%\%DATABASENAME%.mdf" "%DATADIRECTORY%\%DATABASENAME%.mdf"

ECHO Reattaching the database
osql -E -S %SERVER% -d master -Q
"sp_attach_single_file_db '%DATABASENAME%', '%DATADIRECTORY%\%DATABASENAME%.mdf'"
osql -E -S %SERVER% -d master -Q
"alter database [%DATABASENAME%] set multi_user"

ECHO Done
POPD

 

2. Detach from database, zip, check in to SVN, and reattach to database

@ECHO OFF
::Name of database you're connecting to
SET DATABASENAME=***FILL-IN***
::Database instance
SET SERVER=%COMPUTERNAME%\***FILL-IN***
::Path to your subversion repository
SET SVNPATH=svn://***FILL-IN***
SET WORKINGDIRECTORY=%~dp0
::Set the directory you'll be checking the MDF file out to. Defaults to current directory.
SET WORKINGDIRECTORY=C:\Projects\***FILL-IN***\Trunk\
SET DATADIRECTORY=C:\Program Files\Microsoft SQL Server\MSSQL.4\MSSQL\Data
FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\SQL2005\Setup" /v SQLPath') DO SET DATADIRECTORY=%%B\Data

TITLE Checking out latest version of %DATABASENAME% database
ECHO Detaching database
PUSHD %WORKINGDIRECTORY%
osql -E -S %SERVER% -d master -Q
"alter database [%DATABASENAME%] set single_user with rollback immediate"
osql -E -S %SERVER% -d master -Q
"DBCC SHRINKDATABASE (%DATABASENAME%)"
osql -E -S %SERVER% -d master -Q
"sp_detach_db '%DATABASENAME%'"

ECHO Copying database (MDF) file
copy "%DATADIRECTORY%\%DATABASENAME%.mdf" "%~dp0"

ECHO Reattachind database
osql -E -S %SERVER% -d master -Q
"sp_attach_single_file_db '%DATABASENAME%', '%DATADIRECTORY%\%DATABASENAME%.mdf'"
osql -E -S %SERVER% -d master -Q
"alter database [%DATABASENAME%] set multi_user"

ECHO Compressing database (MDF) file
"%PROGRAMFILES%\7-zip\7z.exe" u -tzip %DATABASENAME%.mdf.zip %DATABASENAME%.mdf
del %DATABASENAME%.mdf

ECHO Checking in to source control
svn add %DATABASENAME%
.mdf.zip
svn commit %DATABASENAME%
.mdf.zip -m "Automatic check-in"

ECHO Done
POPD

 

Yes, you could do this with Powershell, too. That's not what I did.

Posted by Jon Galloway | with no comments
Filed under: ,

[link] 9MinutesOfFame

Back in February, I posted about MyLastFM, an open source player for Last.FM radio. MyLastFM is a really slick looking application with some slick code under the covers. It's the product of a killer team - Eric's the programmer and Nicole's the designer.

This dynamic duo just released 9MinutesOfFame.com.  As I'd expected, the HTML code is as pretty as the design - semantic markup with all the cool Web2 Javascript libraries. Nice!

It's a little hard to describe the concept; luckily the splash intro makes it pretty clear:

Kinda like a user driven reblogger site mixed with digg. Neat idea.

So, head on over to www.9minutesoffame.com, submit your feed url, and take over the site for five hundred and forty glorious seconds. And if you're like me, go ahead and view the source. Hey, an ASP.NET page with no nested tables! It can be done!

Subscription updates for my blog

If you subscribe to my weblog's RSS feed (rather than the main weblogs.asp.net feed), you'll need to update it to my new feedburner feed link: http://feeds.feedburner.com/jongalloway

 

While I'm at it, if you'd like to get my posts via e-mail, you can subscribe here. It's really simple, just go to the link and enter your e-mail address.

Posted by Jon Galloway | with no comments
Filed under: ,

Can Operating Systems tell if they're running in a Virtual Machine?

Or, do androids know they're dreaming of electric sheep...

There was some recent news on Windows Vista EULA restrictions relating to Virtual Machines. Vista Home Editions aren't allowed to be run inside a Virtual Machine, and Vista Ultimate in a VM will restrict access to applications which use DRM. We're still waiting for clarification from Microsoft, but it seems like the popular interpretations are basically right.

This raises the question - is this a EULA restriction, or is it going to be enforced. Can it be enforced? Can an operating system tell if it's running in a Virtual Machine?

That's really two questions:

  1. Can Operating Systems currently detect if they're running in a VM?
  2. Will Operating Systems always be able to detect if they're running in a VM?

Well, I only know what I read. Let me know if you disagree...

Can Operating Systems currently detect if they're running in a VM?

Yes, they can. Right now they do it through a couple of techniques - direct hardware fingerprinting and inferred hardware fingerprinting.

Direct hardware fingerprinting is pretty straightforward. Virtual Machines have predictable hardware profiles, so you can just query for "virtual hardware" that's only available in VM's and can't easily be changed. The Virtual PC Guy describes this approach here:

The easiest way to detect that you are inside of a virtual machine is by using 'hardware fingerprinting' - where you look for hardware that is always present inside of a given virtual machine.  In the case of Microsoft virtual machines - a clear indicator is if the motherboard is made by Microsoft... [WMI Script to check the motherboard vendor]
If the motherboard is made by "Microsoft Corporation" then you are inside of one of our virtual machines.

The inferred hardware fingerprinting approach is a bit more dodgy. It works by making direct machine level calls to the virtualized CPU that will reveal if the CPU is real or virtual. Some of these call instructions that the VMM's don't currently support. Others make system calls that will only succeed on specific virtual hardware, usually because of special machine calls the VM's implement to allow communication with the host OS and optimize use of host OS resources (e.g. the Virtual Machine Additions for Virtual PC / Virtual Server , or VMWare's VMware Command Line Tools). This kind of stuff is pretty slick, but it makes "undocumented system calls" look boring.

Here are some examples of indirect hardware fingerprinting:

Of course, this approach is subject to the whims of each VMM release, and it may vary from host OS to host OS.

These two approaches remind me of the two ways to target CSS to different browsers - ask them nicely, or beat it out of them.

Will Operating Systems always be able to detect if they're running in a VM?

Of course, that's not a question I can answer with certainty until I can get my hands on a flux capacitor and 1.21 gigawatts. That won't keep me from speculating, though...

Let's step back a second and think about whether or not we want Operating Systems to know if they're running in a virtual environment. In the context of the recent Vista EULA flap, we might want to say no - the EULA restriction is stupid, and it's a good thing that they can't enforce it.

But let's talk about The Blue Pill. It's a theoretical malware application of VM technology in which a rootkit consumes the host operating system and runs as a hypervisor (a hardware virtual machine manager). Once it's done that, it can do whatever it wants without the operating system knowing it's been compromised:

The idea behind Blue Pill is simple: your operating system swallows the Blue Pill and it awakes inside the Matrix controlled by the ultra thin Blue Pill hypervisor. This all happens on-the-fly (i.e. without restarting the system) and there is no performance penalty and all the devices, like graphics card, are fully accessible to the operating system, which is now executing inside virtual machine. This is all possible thanks to the latest virtualization technology from AMD called SVM/Pacifica. [via invisiblethings.blogspot.com]

It's mesmerizing and scary at the same time, kind of like BooBah. There's some doubt as to whether it's code or just talk at this point:

However, there is great doubt throughout computer security circles as to whether blue pill is real or a mere stunt, since details and a working sample of the source code have not been made available, contravening the industry wide standard of full disclosure. [via Wikipedia]

Regardless, the concept has been validated. Microsoft Research and a group from University of Michigan proposed SubVirt (pdf), a VMM rootkit, in May 2006. Their paper is a fascinating schizophrenic game of cat and mouse: well, you could detect this by blah, but then we could zhoop, and even if you flurped we could just breeble. The SubVirt rootkit doesn't take advantage of hypervisor technology and requires a reboot, but on the other hand it seems to be more mature.

We built VMBRs (Virtual Machine Based Rootkits) based on two available virtual-machine monitors, including one for which source code was unavailable. On today’s x86 systems, VMBRs are capable of running a target OS with few visual differences or performance effects that would alert the user to the presence of a VMBR. In fact, one of the authors accidentally used a machine which had been infected by our proof-of concept VMBR without realizing that he was using a compromised system! [Subvirt paper pdf]

The point remains, though - we probably want our operating systems to know if they're running on virtual machines. It sounds like they should always be able to do that. Anthony Liguori, and IBM software engineer who has worked on the Xen hypervisor for two years, says:

Hardware virtualization requires a technique know as "trap and emulation". The idea is that the hardware traps certain instructions and the VMM emulates those instructions in such a way as to make the software believe it is running in a virtual machine. Software emulation implies that these instructions take much longer to complete when executed under a VMM then on normal hardware. This fact is what can be used to detect the presence of a VMM. [via virtualization.info]

You may have noticed that I jumped from talking about software VMM's (VMWare, VirtualPC) to both software and hardware VM rootkits. From what I've read, it looks like this is going to be a cat and mouse game, but the VM rootkits will always need to deal with the timing issues that Anthony mentioned. The SubVirt authors discussed this, too:

A VMBR adds CPU overhead to trap and emulate privileged instructions, as well as to run any malicious services. These timing differences can be noticed by software running in the virtual machine by comparing the running time of benchmarks against wall-clock time. A VMBR can make the detector’s task more difficult by slowing down the time returned by the system clock, but the detector can overcome this by using a clock that can be read without interference from the VMBR (e.g., the user’s wristwatch). [Subvirt paper pdf]

Well, I hope we can do better than wristwatch checks. I'd hope that an OS could check the time of day once an hour and notice a 1% drag due to VM hosting, or at least pick it up over the course of a full day. Not great, but at least it'd be detectable.

There's one more secret weapon against bad VMM's. It's probably the best defense, but you probably aren't going to like it. I'm talking about the TPM, the Trusted Platform Module. Microsoft's Next Generation Secure Computing Base Digital Rights Management (DRM) technology (called Palladium back when Vista was Longhorn) ran on the TPM. Trusted computing works by using a hardware crypto chip which verifies hardware and software loaded by the hypervisor (which runs above the hardware virtualization layer, which runs above the good old CPU's... sheesh, this is getting complicated...).

It's as if an OS running on a Trusted Computing platform was using HTTPS (SSL) to talk to hardware and trusted software like DRM software, but with much stronger crypto. That's a good thing from the point of view of safeguarding against rootkits. It's bad news if you want to use software that works by virtualizing hardware (such as virtual soundcards which record streaming music like TotalRecorder, or virtual DVD drives which let you read ISO images like Daemon Tools or Alcohol 120). It's also bad news if you want full access to DRM protected content, since DRM processing protected by a TPM is quite a bit more robust than the flimsy DRM stuff they're using today. DRM'd media running on a Trusted platform could be sent from disk to soundcard with the same kind of anti-tampering assurance you'd expect when you connect to your bank's website across the big, bad internet. Hmm. Well, we've got a little while to think this through, since it's mostly been removed from Vista and won't ship until future versions of Windows.

[OT] Getting stupid with Smart Art in PowerPoint 2007

Sure, you've seen the Gettysburg PowerPoint Presentation. You may have even seen the Death Start Attack PowerPoint, or David Byrne's PowerPoint fueled artwork. PowerPoint has always been there when we needed our bullet points to say something more.

Now, if you've really got something to say, then Smart Art might help you say it a little better. For the rest of us, PowerPoint 2007 Smart Art pumps our dumb bullet points full of steroids and PCP - they don't really get any smarter, but they're stronger and edgier.

Example:

Boring, right? Plus, presented that way it's obvious that I've got absolutely nothing to say. No problem, I just select the bullet points and click on the Smart Art button, and our bullets go number one with a bullet:

 

Action! Machinery! Gears are turning, things are happening!

 

 

Well, we're not sure what's going on here, but it seems that there are some tradeoffs involved which may require further analysis. There's a delicate balance to be preserved...

 

 

Quality ingredients, wonderful results. Better not let this one stay on the screen too long, but it looks like a million bucks if it just flashes by.

 

 

Well, I think we all suspected what this slide is telling us. Notice, though, how the graphics make the horrible truth inescapable.

 

 

 

Well, they can't all be gems. This one's not so great as a slide, but this might have a shot as your desktop. Wait a minute... keep with me here... what if we airbrush it on a van! Are we talking now?

 

 

 

 

 

 

 

 

 

 

 

 

 

Of course we are. That was a rhetorical question; you weren't supposed to answer. I need to get some minor touch-ups, but believe me when I tell you that heads turn when I drive by.

Now, you're probably sinking into despair at this point. Jon's got access to this process, this Smart Art, which you can't have until 2007. In the meantime, he's going to... well, he'll create so much business value, such a wealth of shared meaning that he'll rule the emerging reputation economy.  I wish your despair was well founded, but it's not. You can test drive PowerPoint 2007 online right now, and unleash your own Smart Art today. If you publish it on Flickr, be a dear and tag it with "smartart", would you?

Posted by Jon Galloway | 1 comment(s)
Filed under:

[OT] Google buying YouTube for $1.65 Billion

MarketWatch: Google to acquire YouTube for $1.65 billion in stock

SAN FRANCISCO (MarketWatch) - Google Inc. said Monday it's buying No. 1 Internet video sharing Web site YouTube Inc. for $1.65 billion in stock. The deal is regarded as a largely defensive one that leapfrogs Google into a leading role in a burgeoning Internet marketplace. Moreover, the Google/YouTube deal highlights how Google (GOOG) and other Internet companies are betting heavily on video to attract more customers and generate more advertising revenue. Indeed, many analysts chiming in on the deal Monday suspect Google's competitors will now seek to buy YouTube-wannabes in order to keep pace with their rival. On Monday, the boards of directors of both Google and YouTube approved the terms of the deal, which was announced after the market closed for the day.

Whoa. I didn't see that coming; I thought Google's video bet was on Google Video. I think it's a smart move, though. They're not buying technology, they're buying users. Will MSN Soapbox have a chance to catch up with the combined user base of Google Video and YouTube?

[via Digg]

[Tool] RegmonToRegfile - Record and playback registry changes

 

I just released a new utility: RegmonToRegfile.

It's easier to explain what you can do with RegmonToRegfile than to explain what it is. RegmonToRegfile works with Regmon (a free tool from SysInternals) to record and playback the registry changes that another program or installation makes. For example, I used it to create the registry files for the IE7 Standalone launcher I've been distributing. I recorded the registry entries when I installed, ran, and uninstalled IE7 and saved the logs, then ran RegmonToRegfile to convert then to regfiles.

Regmon is an excellent tool that monitors what other programs do with the Windows registry. It saves everything that happens to a log file, but doesn't include the option to export to a registry (.reg) file. RegmonToRegfile reads Regmon logs and translates them into .reg files.

STANDARD REGISTRY WARNING: Registry flies can do great damage to your computer. You should always review registry files before you merge them, but that is even more important in this case since the registry files are being generated by a new and unsupported application. I also recommend testing your registry changes on a Virtual PC or VMWare Windows image. This application and the registry files you produce with it are unsupported; use at your own risk.

USAGE: regmontoregfile -input [-output] [-path] [-process] [-keys] [-maxRecords] [-lookup]
Input: Filename of the RegMon log.
Output: Filename of the output registry file. Default: input filename with extension changed to .reg.
Path: Path to input and output file.
Process: Comma delimited list of processes to include. Default:all processes.
Keys: Regular expression of key(s) to include. Default:all keys.
MaxRecords: Maximum number of records (log entries) to process. Default:all records.
Lookup: If true, looks up truncated binary values in the registry. Default:false (do not lookup values, ommit them).

All parameters can be set via config files settings as well. If you specify the path parameter, input and output should not be qualified with a full path.

There are a few limitations:

  1. Regmon only logs the first few bytes of binary values (REG_Binary) written to the registry, so RegmonToRegfile just skips writing these values. In most cases, that's not an issue since I haven't seen any binary values written by a program that would make sense to script anyways - they're usually things like crypto keys or keyboard scan codes. Version 1.0.2 adds the option of looking up truncated binary values in the local registry.
  2. RegmonToRegfile has limited support for registry value types. It handles STRING and DWORD values and can try to lookup BINARY values in your local registry. It does not handle other types, such as EXPAND_SZ, and MULTI_SZ types. This hasn't been a problem in practical use, since most registry entries are either STRING or DWORD type.

Source is included under BSD license.

Update: I forgot to mention that I used the FileHelpers library to do the grunt work of parsing the log files, which freed me up to concentrate on mapping the fields to regfile syntax. FileHelpers is very easy to use, and works really well. If you're parsing any kind of delimited text file without using FileHelpers, you're working too hard. Thanks for pointing that out, Greg!

Posted by Jon Galloway | 17 comment(s)
Filed under: , ,

[.NET Gotcha] Commandline args ending in \" are subject to CommandLineToArgvW whackiness

I recently posted on my confusion when I tried to use commandline arguments ending in \" and got unpredictable results. It seemed that all backslashes before a double quote character needed to be escaped, but if they didn't preceed a doublequote, they didn't need to be escaped.

There's more explanation on the original blog post, but here's a summary:

To pass \\this is a test\\ to a console application, you need to pass in \\this is a test\\\\. The first set of backslashes don't require escaping, but the second set do. Stranger still, adding another backslash to that second set has no effect at all doesn't add a backslash, but adds a doublequote: \\this is a test\\\\\ (with 5 backslashes) yields \\this is a test\\". [thanks for correcting me, Carlos].

Via a comment thread on Raymond Chen's blog, I got some help from Carlos:

"Most apps (including .Net apps) use CommandLineToArgvW to decode their command lines.  It uses crazy escaping rules which explain the behaviour you're seeing."

The explanation on MSDN:

CommandLineToArgvW has a special interpretation of backslash characters when they are followed by a quotation mark character ("), as follows:

  • 2n backslashes followed by a quotation mark produce n backslashes followed by a quotation mark.
  • (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark.
  • n backslashes not followed by a quotation mark simply produce n backslashes.

I prefer Carlos' listing of the rules:

Backslash is the escape character; always escape quotes; only escape backslashes if they precede a quote.

Posted by Jon Galloway | with no comments
Filed under: ,
More Posts Next page »