I’ve written a few posts on how to speed up web sites by sending the correct headers to leverage browser caching and compressing .php, .css and .js files without mod_gzip or mod_deflate.

The intended audience for this post is developers who have already applied most or all of Google’s Web Performance Best Practices and Yahoo’s Best Practices for Speeding Up Your Web Site and are wondering how to speed up WordPress sites in particular.

I assume you’re familiar with WordPress caching and are already using a caching plugin, such as WP Super Cache, W3 Total Cache or the like.

Reduce HTTP requests

Reducing HTTP requests should be the very first thing step in speeding up any site. If you are using plugins, watch them carefully for inefficiencies like added CSS and JavaScript files. Combine, minify and compress these files. Some plugins allow you to turn off their bundled CSS in the plugin’s settings page. Where possible, copy the plugin’s CSS into the current theme’s style.css and turn off the extra file.

Delete deactivated plugins

Remove any plugins you’re not using. Deactivated plugins can be deleted from the Plugins page.

Speed up the mod_rewrite code

jdMorgan from WebmasterWorld.com has written a replacement for the .htaccess rewrite rule used by WordPress. This will speed up the WordPress mod_rewrite code by a factor of more than two.

This is a total replacement for the code supplied with WP as bounded by the “Begin WP” and “End WP” comments, and fixes several performance-affecting problems. Notably, the unnecessary and potentially-problematic container is completely removed, and code is added and re-structured to both prevent completely-unnecessary file- and directory- exists checks and to reduce the number of necessary -exists checks to one-half the original count (due to the way mod_rewrite behaves recursively in .htaccess context).

http://www.webmasterworld.com/apache/4053973.htm

The following code is adapted from the original to add png, flv and swf to the list of static file formats:

# BEGIN WordPress
# adapted from http://www.webmasterworld.com/apache/4053973.htm
#
RewriteEngine on
#
# Unless you have set a different RewriteBase preceding this point,
# you may delete or comment-out the following RewriteBase directive
# RewriteBase /
#
# if this request is for "/" or has already been rewritten to WP
RewriteCond $1 ^(index.php)?$ [OR]
# or if request is for image, css, or js file
RewriteCond $1 .(gif|jpg|png|ico|css|js|flv|swf)$ [NC,OR]
# or if URL resolves to existing file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# or if URL resolves to existing directory
RewriteCond %{REQUEST_FILENAME} -d
# then skip the rewrite to WP
RewriteRule ^(.*)$ - [S=1]
# else rewrite the request to WP
RewriteRule . /index.php [L]
#
# END wordpress 

Only load the comment-reply.js when needed

In the default WordPress template, the comment-reply.js script is included on all single post pages, regardless of whether nested/threaded comments is enabled. A simple tweak changes the theme to only include comment-reply.js on single post pages only when it makes sense to do so: if threaded comments are enabled, commenting on that post is allowed, and a comment already exists.

Remove the following line from your theme’s header.php:

<?php if ( is_singular() ) wp_enqueue_script( 'comment-reply' ); ?>

Add the following lines to your theme’s functions.php.

// Don't add the wp-includes/js/comment-reply.js?ver=20090102 script to single post pages unless threaded comments are enabled
// adapted from http://bigredtin.com/behind-the-websites/including-wordpress-comment-reply-js/
function theme_queue_js(){
  if (!is_admin()){
    if (is_singular() && (get_option('thread_comments') == 1) && comments_open() && have_comments())
      wp_enqueue_script('comment-reply');
  }
}
add_action('wp_print_scripts', 'theme_queue_js');

Only load the l10n.js when needed

In WordPress 3.1, a l10n.js script is loaded. It is “mostly used for scripts that send over localization data from PHP to the JS side using wp_localize_script().” Whether it’s safe to remove this file seems to be a matter of debate, but should you decide you want to remove it…

Add the following lines to your theme’s functions.php.

// Don't add the wp-includes/js/l10n.js?ver=20101110 script to non-admin pages
// adapted from http://wordpress.stackexchange.com/questions/5451/what-does-l10n-js-do-in-wordpress-3-1-and-how-do-i-remove-it
function remove_l10n_js(){
  if (!is_admin()){
    wp_deregister_script('l10n');
  }
}
add_action('wp_print_scripts', 'remove_l10n_js');

Replace unecessary code executions and database queries

WordPress saves settings specific to your blog in the database. These settings include what language your blog is written in, whether text is read left-to-right or vice versa, the path to the template directory, etc.

The default WordPress theme contains a number of database queries in order to figure out these things and build the correct page. The default theme needs this flexibility, but your theme does not. Joost de Valk recommends replacing these database queries with static text in your theme files in his post Speed up WordPress, and clean it up too!

An easy way to do this is to browse to your web site and then view the source code. Copy the content that won’t change from page to page and paste it into your theme, overwriting the PHP with the generated HTML.

For example, my theme’s header.php file contains this line:

<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>

The source code of the rendered page displays this line:

<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">

On my blog, this HTML output is never going to be anything different, so why make WordPress look these settings up in the database each time a page is loaded? This line is an excellent candidate for replacement. The footer.php file contains a handful more opportunities for replacement, but go through each of your theme’s files and look for references to the template directory and other data that won’t change as long as you’re using the theme. All told, I was able to replace 12 database queries with static HTML.

Joost also recommends checking for unnecessary or slow database queries, and installing a helpful debugging plugin, in his post on Optimizing WordPress database performance.

Clean out your MySQL database

Delete spam comments

From the Dashboard, click Comments, then click on Empty Spam.

Delete post revisions

If you don’t use post revisions, you may want to delete them from the wp_posts table. Back up your database, then run the following SQL query:

DELETE FROM wp_posts WHERE post_type = "revision";

Before: 683 records
After: 165 records

This does not delete the latest draft of unpublished posts. It’s a good idea to optimize the table after deleting the revisions.

You can stop WordPress from saving post revisions by adding the following code to wp-config.php:

define('WP_POST_REVISIONS', false );

Optimize your MySQL database

Optimizing your MyISAM tables is comparable to defragmenting your hard drive. It’s probably been a while since you’ve done that, too.

If you’re using phpMyAdmin, browse to your WordPress database. Under the Structure tab, at the bottom of the list of tables, click on the link “Check all”. In the “With selected” menu, choose “Optimize table”. (I would have recommended just optimizing tables that have overhead, but the wp_posts table can be optimized even when it doesn’t show any overhead.

For MyISAM tables, OPTIMIZE TABLE works as follows:

  • If the table has deleted or split rows, repair the table.
  • If the index pages are not sorted, sort them.
  • If the table’s statistics are not up to date (and the repair could not be accomplished by sorting the index), update them.

http://dev.mysql.com/doc/refman/5.1/en/optimize-table.html

Flush the Buffer Early

When users request a page, it can take anywhere from 200 to 500ms for the backend server to stitch together the HTML page. During this time, the browser is idle as it waits for the data to arrive. In PHP you have the function flush(). It allows you to send your partially ready HTML response to the browser so that the browser can start fetching components while your backend is busy with the rest of the HTML page. The benefit is mainly seen on busy backends or light frontends.

http://developer.yahoo.com/performance/rules.html#flush

Add flush() between the closing tag and the opening tag in header.php.

</head>
<?php flush(); // http://developer.yahoo.com/performance/rules.html#flush ?>
<body>

OK, so this isn’t technically a WordPress-specific tweak, but it’s a good idea.

The results are in, and they’re good. After compressing .php, .css and .js files without mod_gzip or mod_deflate and sending the correct headers to leverage browser caching, Ardamis.com now has a Google Page Speed score of 93/100.

Ardamis.com PageSpeed score of 93/100

Ardamis.com Page Speed score of 93/100

Page Speed just keeps getting better, and it keeps getting tougher to score well. I’m happy, but not satisfied yet. The remaining hurdle is to serve static content from a cookieless domain. I’m looking into the CDN offered by Amazon.com, but it’s a paid service.

It required only a few small changes to move from XHTML 1.0 Strict to HTML5, but as of today, ardamis.com is being served as valid HTML5. For some time, I’ve been waiting for HTML5 to get closer to becoming a W3C recommendation, and for better support from user agents, but I’ve gotten caught up with other improvements to the site and decided to make the transition now.

Over the next few weeks, I’ll be updating the HTML to incorporate some of the new tags. I’m pretty excited about replacing divs with new semantic elements like <header>, <article>, and <footer>.

As a follow-up to my post on compressing .php, .css and .js files without mod_gzip or mod_deflate, I’m documenting the changes I made to the .htaccess file on ardamis.com in order to speed up page load times for returning visitors and satisfy the Leverage browser caching recommendation of Google’s Page Speed Firefox/Firebug Add-on.

A great explanation of why browser caching helps the web deliver a better user experience is at betterexplained.com.

Two authoritative articles on the subject are Google’s Performance Best Practices | Optimize caching and Yahoo’s Best Practices for Speeding Up Your Web Site | Add an Expires or a Cache-Control Header.

I’d like to point out that in researching browser cashing, I came across a lot of information that contradicted the rather clear instructions from Google:

It is important to specify one of Expires or Cache-Control max-age, and one of Last-Modified or ETag, for all cacheable resources. It is redundant to specify both Expires and Cache-Control: max-age, or to specify both Last-Modified and ETag.

I’m not sure that this recommendation is entirely correct, as the W3C states that Expires and Cache-Control max-age are used in different situations, with Cache-Control max-age overriding Expires in the event of conflicts.

If a response includes both an Expires header and a max-age directive, the max-age directive overrides the Expires header, even if the Expires header is more restrictive. This rule allows an origin server to provide, for a given response, a longer expiration time to an HTTP/1.1 (or later) cache than to an HTTP/1.0 cache.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

It would seem that Cache-Control is the preferred method of controlling browser caching going forward.

HTTP 1.1 clients will honour “Cache-Control” (which is easier to use and much more flexible).
HTTP 1.0 clients will ignore “Cache-Control” but honour “Expires”. With “Expires” you get thus at least a bit control for these old clients.

http://www.peterbe.com/plog/cache-control_or_expires

In any event, Page Speed won’t protest if you do end up sending both Expires and Cache-Control max-age, or if you remove both Last-Modified and ETag, but I was able to get the best results with just setting Cache-Control max-age and removing the ETag.

Setting the headers in .htaccess

On Apache, configuring the proper headers can be done in the .htaccess file, using the Header directive. The Header directive requires the mod_headers module to be enabled.

I’m choosing to set a far future Expires header of one year on my images files, because I tweak the CSS and JavaScript pretty often, and don’t want those file types to be cached as long.

Add the following code to your .htaccess file to set your Cache-Control and Expires headers, adjusting the date to be one year from today.

# Set Cache-Control and Expires headers
<filesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|swf|mp3|mp4)$">
Header set Cache-Control "max-age=2592000, private"
Header set Expires "Sun, 17 July 2011 20:00:00 GMT"
</filesMatch>
<filesMatch "\.(css|css.gz)$">
Header set Cache-Control "max-age=604800, private"
</filesMatch>
<filesMatch "\.(js|js.gz)$">
Header set Cache-Control "max-age=604800, private"
</filesMatch>
<filesMatch "\.(xml|txt)$">
Header set Cache-Control "max-age=216000, private, must-revalidate"
</filesMatch>
<filesMatch "\.(html|htm)$">
Header set Cache-Control "max-age=7200, private, must-revalidate"
</filesMatch>

Removing ETags in .htaccess

Most sources recommend simply removing ETags if they are not required.

Entity tags (ETags) are a mechanism that web servers and browsers use to determine whether the component in the browser’s cache matches the one on the origin server.

If you’re not taking advantage of the flexible validation model that ETags provide, it’s better to just remove the ETag altogether.

http://developer.yahoo.com/performance/rules.html#etags

Add the following code to your .htaccess file to remove ETag headers.

# Turn off ETags
FileETag None
Header unset ETag

Set Expires headers with ExpiresByType (optional)

If your host has the mod_expires module enabled, you can specify Expires headers by file type. Godaddy does not have this module enabled.

# Set Expires headers
ExpiresActive On
ExpiresDefault "access plus 1 year"
ExpiresByType text/html "access plus 1 second"
ExpiresByType image/gif "access plus 2592000 seconds"
ExpiresByType image/jpeg "access plus 2592000 seconds"
ExpiresByType image/png "access plus 2592000 seconds"
ExpiresByType image/x-icon "access plus 2592000 seconds"
ExpiresByType text/css "access plus 604800 seconds"
ExpiresByType text/javascript "access plus 604800 seconds"
ExpiresByType application/x-javascript "access plus 604800 seconds"

Removing the Last-Modified header in .htaccess (optional)

I’m following Google’s instructions and not removing the Last-Modified header, but if you wanted to do so, you could use:

# Remove Last-Modified header
Header unset Last-Modified

Busting the cache when files change

What happens when you change files and need to force browsers to load the new files? Christian Johansen offers two methods in his post on Using a far future expires header.

I’d like to note that, as of today, Google Webmaster Tools is reporting over one million inbound links to pages on ardamis.com.

one million inbound links

One million inbound links!

I’ve been spending quite a bit of time on ardamis.com lately, giving it a new look, working at improving the site’s navigation, cultivating some inbound links, and posting more regularly. It’s rewarding to see that the effort is paying off.

Over the last few days, I’ve been concentrating on reducing page load times by sending the proper headers and compressing files.

I’ll give it some time and see how performance improves.

According to Google’s Webmaster Tools’ performance overview, with Super Cache running, a single minified CSS, a single minified JavaScript, etc. but no compression or header tweaks:
On average, pages in your site take 2.8 seconds to load (updated on Jun 28, 2010). This is faster than 53% of sites.

The chart illustrating page load times is pretty much all over the place, but at no time has the site dipped into the 20th percentile, indicating a ‘fast’ site. I’m trying to change that.

File compression is possible on Apache web hosts that do not have mod_gzip or mod_deflate enabled, and it’s easier than you might think.

A great explanation of why compression helps the web deliver a better user experience is at betterexplained.com.

Two authoritative articles on the subject are Google’s Performance Best Practices documentation | Enable compression and Yahoo’s Best Practices for Speeding Up Your Web Site | Gzip Components.

Compressing PHP files

If your Apache server does not have mod_gzip or mod_deflate enabled (Godaddy and JustHost shared hosting, for example), you can use PHP to compress pages on-the-fly. This is still preferable to sending uncompressed files to the browser, so don’t worry about the additional work the server has to do to compress the files at each request.

Option 1: PHP.INI using zlib.output_compression

The zlib extension can be used to transparently compress PHP pages on-the-fly if the browser sends an “Accept-Encoding: gzip” or “deflate” header. Compression with zlib.output_compression seems to be disabled on most hosts by default, but can be enabled with a custom php.ini file:

[PHP]

zlib.output_compression = On

Credit: http://php.net/manual/en/zlib.configuration.php

Check with your host for instructions on how to implement this, and whether you need a php.ini file in each directory.

Option 2: PHP using ob_gzhandler

If your host does not allow custom php.ini files, you can add the following line of code to the top of your PHP pages, above the DOCTYPE declaration or first line of output:

<?php if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) ob_start("ob_gzhandler"); else ob_start(); ?>

Credit: GoDaddy.com

For WordPress sites, this code would be added to the top of the theme’s header.php file.

According to php.net, using zlib.output_compression is preferred over ob_gzhandler().

For WordPress or other CMS sites, an advantage of zlib.output_compression over the ob_gzhandler method is that all of the .php pages served will be compressed, not just those that contain the global include (eg.: header.php, etc.).

Running both ob_gzhandler and zlib.output_compression at the same time will throw a warning, similar to:

Warning: ob_start() [ref.outcontrol]: output handler ‘ob_gzhandler’ conflicts with ‘zlib output compression’ in /home/path/public_html/ardamis.com/wp-content/themes/mytheme/header.php on line 7

Compressing CSS and JavaScript files

Because the on-the-fly methods above only work for PHP pages, you’ll need something else to compress CSS and JavaScript files. Furthermore, these files typically don’t change, so there isn’t a need to compress them at each request. A better method is to serve pre-compressed versions of these files. I’ll describe a few different ways to do this, but in both cases, you’ll need to add some lines to your .htaccess file to send user agents the gzipped versions if they support the encoding. This requires that Apache’s mod_rewrite be enabled (and I think it’s almost universally enabled).

Option 1: Compress locally and upload

CSS and JavaScript files can be gzipped on the workstation, then uploaded along with the uncompressed files. Use a utility like 7-Zip (quite possibly the best compression software around, and it’s free) to compress the CSS and JavaScript files using the gzip format (with extension *.gz), then upload them to your server.

For Windows users, here is a handy command to compress all the .css and .js files in the current directory and all sub directories (adjust the path to the 7-Zip executable, 7z.exe, as necessary):

for /R %i in (*.css *.js) do "C:Program Files (x86)7-Zip7z.exe" a -tgzip "%i.gz" "%i" -mx9

Note that the above command is to be run from the command line. The batch file equivalent would be:

for /R %%i in (*.css *.js) do "C:Program Files (x86)7-Zip7z.exe" a -tgzip "%%i.gz" "%%i" -mx9

Option 2: Compress on the server

If you have shell access, you can run a command to create a gzip copy of each CSS and JavaScript file on your site (or, if you are developing on Linux, you can run it locally):

find . -regex ".*(css|js)$" -exec bash -c 'echo Compressing "{}" && gzip -c --best "{}" > "{}.gz"' ;

This may be a bit too technical for many people, but is also much more convenient. It is particularly useful when you need to compress a large number of files (as in the case of a WordPress installation with multiple plugins). Remember to run it every time you automatically update WordPress, your theme, or any plugins, so as to replace the gzip’d versions of any updated CSS and JavaScript files.

The .htaccess (for both options)

Add the following lines to your .htaccess file to identify the user agents that can accept the gzip encoded versions of these files.

<files *.js.gz>
  AddType "text/javascript" .gz
  AddEncoding gzip .gz
</files>
<files *.css.gz>
  AddType "text/css" .gz
  AddEncoding gzip .gz
</files>
RewriteEngine on
#Check to see if browser can accept gzip files.
ReWriteCond %{HTTP:accept-encoding} gzip
RewriteCond %{HTTP_USER_AGENT} !Safari
#make sure there's no trailing .gz on the url
ReWriteCond %{REQUEST_FILENAME} !^.+.gz$
#check to see if a .gz version of the file exists.
RewriteCond %{REQUEST_FILENAME}.gz -f
#All conditions met so add .gz to URL filename (invisibly)
RewriteRule ^(.+) $1.gz [QSA,L]

Credit: opensourcetutor.com

I’m not sure it’s still necessary to exclude Safari.

For added benefit, minify the CSS and JavaScript files before gzipping them. Google’s excellent Page Speed Firefox/Firebug Add-on makes this very easy. Yahoo’s YUI Compressor is also quite good.

Verify that your content is being compressed

Use the nifty Web Page Content Compression Verification tool at http://www.whatsmyip.org/http_compression/ to confirm that your server is sending the compressed files.

Speed up page load times for returning visitors

Compression is only part of the story. In order to further speed page load times for your returning visitors, you will want to send the correct headers to leverage browser caching.

By default, the Adobe Updater application that is installed along side various Adobe products like Acrobat and Photoshop is set to check for updates automatically. Specifically, it’s set to check for updates to all installed Adobe products every week, and to download all updates and then notify you when they are ready to be installed. In this post, I’ll explain how to disable this feature by editing a settings file while avoiding the GUI.

Adobe Updater Preferences

Adobe Updater Preferences

In a managed environment, an administrator may not want any software to update itself for any number of reasons. The automatic check can be switched off in the Adobe Updater preferences, but it can be a nuisance to find and requires as many as 9 clicks.

Adobe Updater can be launched from within Adobe products by clicking Help | Check for Updates (note that in some products, the path is Help | Updates, but in either case, you can use the keystroke Alt+H, U). Click Preferences, then uncheck the box next to Automatically check for Adobe updates and click OK, then close the Adobe Updater window. You may have to click Quit in a subsequent window before the application closes.

For a more direct route, the Adobe Updater executable installed with Reader 9 resides at
C:Program Files (x86)Common FilesAdobeUpdater6AdobeUpdater.exe on a 64-bit Windows 7 machine, and at
C:Program FilesCommon FilesAdobeUpdater6AdobeUpdater.exe on a 32-bit Windows XP machine.

All of the configurable settings are saved to a file named AdobeUpdaterPrefs.dat in the user profile, rather than as registry keys. The .dat file extension suggests a binary file, but it’s actually just an XML document that can be opened in any text editor.

The preferences file resides at
C:Users[USERNAME]AppDataLocalAdobeUpdater6AdobeUpdaterPrefs.dat on a 64-bit Windows 7 machine, and at
C:Documents and Settings[USERNAME]Local SettingsApplication DataAdobeUpdater6AdobeUpdaterPrefs.dat on a 32-bit Windows XP machine.

The minimum lines that need to exist for the file to be valid and for “Automatically check for Adobe updates” to be disabled are:

<?xml version="1.0" encoding="UTF-8" ?>
<AdobeUpdater>
<AutoCheck>0</AutoCheck>
</AdobeUpdater>

To disable the auto update check programmatically, this file can be saved as AdobeUpdaterPrefs.dat and a script used to later overwrite the file in the user profile. A rather geekier approach would be to use a batch file to rename AdobeUpdaterPrefs.dat and then write a new file. I prefer the latter method because it requires only a single file and because it could be easily modified to insert lines that would change other settings, such as the location of the aum.log log file or the download directory, which are located in the user profile by default.

A batch file to back-up and then remake the file might look like this:

:: A batch file for writing a new Adobe Updater settings file "AdobeUpdaterPrefs.dat"
:: If an AdobeUpdaterPrefs.dat exists, it is edited and then the next next location is checked, until the script has iterated through all locations
@echo off

%SystemDrive%
cd
SETLOCAL EnableDelayedExpansion

:: Check each location and if the file is found, pass the directory and a label (to the next path to be searched or to an EXIT command) to the function

:XPUpdater6
@echo.
echo Checking for "%USERPROFILE%Local SettingsApplication DataAdobeUpdater6AdobeUpdaterPrefs.dat"
if exist "%USERPROFILE%Local SettingsApplication DataAdobeUpdater6AdobeUpdaterPrefs.dat" (call:REWRITE "%USERPROFILE%Local SettingsApplication DataAdobeUpdater6",XPUpdater5) else (@echo The AdobeUpdaterPrefs.dat file was not found.)

:XPUpdater5
@echo.
echo Checking for "%USERPROFILE%Local SettingsApplication DataAdobeUpdater5AdobeUpdaterPrefs.dat"
if exist "%USERPROFILE%Local SettingsApplication DataAdobeUpdater5AdobeUpdaterPrefs.dat" (call:REWRITE "%USERPROFILE%Local SettingsApplication DataAdobeUpdater5",OUT) else (@echo The AdobeUpdaterPrefs.dat file was not found.)

:OUT
@pause
exit

:REWRITE
:: Configure Adobe Update to not check for updates
:: Move to the correct directory
cd %~1
:: Delete any temp file that this script may have created in the past
if exist AdobeUpdaterPrefs.dat.temp del AdobeUpdaterPrefs.dat.temp
:: Backup the old file
rename AdobeUpdaterPrefs.dat AdobeUpdaterPrefs.dat.temp
:: Write a new minimum settings file (the other data will be filled in when Auto Updater runs)
echo ^<?xml version="1.0" encoding="UTF-8" ?^> >> AdobeUpdaterPrefs.txt
echo ^<AdobeUpdater^> >> AdobeUpdaterPrefs.txt
echo ^<AutoCheck^>0^</AutoCheck^> >> AdobeUpdaterPrefs.txt
echo ^</AdobeUpdater^> >> AdobeUpdaterPrefs.txt
:: Rename the new file
rename AdobeUpdaterPrefs.txt AdobeUpdaterPrefs.dat
@echo The AdobeUpdaterPrefs.dat file was found and modified.
:: Go to the next location in the list
goto :%~2
goto :EOF

File locations in Windows 7

Note that in Windows 7, “%USERPROFILE%AppDataLocal” and “%USERPROFILE%Local SettingsApplication Data” contain the same data. A file added to a subdirectory in one location will appear in the corresponding subdirectory in the other location. So this script will work on Windows 7 because of 7′s backwards compatibility.

If you wanted to the script to run using Windows 7′s native C:Users… directory structure and did not care about the loss of compatibility with XP, you could use the following script instead.

:: A batch file for writing a new Adobe Updater settings file "AdobeUpdaterPrefs.dat"
:: If an AdobeUpdaterPrefs.dat exists, it is edited and then the next next location is checked, until the script has iterated through all locations
@echo off

%SystemDrive%
cd
SETLOCAL EnableDelayedExpansion

:: Check each location and if the file is found, pass the directory and a label (to the next path to be searched or to an EXIT command) to the function

:WIN7Updater6
@echo.
echo Checking for "%USERPROFILE%AppDataLocalAdobeUpdater6AdobeUpdaterPrefs.dat"
if exist "%USERPROFILE%AppDataLocalAdobeUpdater6AdobeUpdaterPrefs.dat" (call:REWRITE "%USERPROFILE%AppDataLocalAdobeUpdater6",WIN7Updater5) else (@echo The AdobeUpdaterPrefs.dat file was not found.)

:WIN7Updater5
@echo.
echo Checking for "%USERPROFILE%AppDataLocalAdobeUpdater5AdobeUpdaterPrefs.dat"
if exist "%USERPROFILE%AppDataLocalAdobeUpdater5AdobeUpdaterPrefs.dat" (call:REWRITE "%USERPROFILE%AppDataLocalAdobeUpdater5",OUT) else (@echo The AdobeUpdaterPrefs.dat file was not found.)

:OUT
@pause
exit

:REWRITE
:: Configure Adobe Update to not check for updates
:: Move to the correct directory
cd %~1
:: Delete any temp file that this script may have created in the past
if exist AdobeUpdaterPrefs.dat.temp del AdobeUpdaterPrefs.dat.temp
:: Backup the old file
rename AdobeUpdaterPrefs.dat AdobeUpdaterPrefs.dat.temp
:: Write a new minimum settings file (the other data will be filled in when Auto Updater runs)
echo ^<?xml version="1.0" encoding="UTF-8" ?^> >> AdobeUpdaterPrefs.txt
echo ^<AdobeUpdater^> >> AdobeUpdaterPrefs.txt
echo ^<AutoCheck^>0^</AutoCheck^> >> AdobeUpdaterPrefs.txt
echo ^</AdobeUpdater^> >> AdobeUpdaterPrefs.txt
:: Rename the new file
rename AdobeUpdaterPrefs.txt AdobeUpdaterPrefs.dat
@echo The AdobeUpdaterPrefs.dat file was found and modified.
:: Go to the next location in the list
goto :%~2
goto :EOF

Additional benefits

Modifying the preferences file could have other benefits as well. Imagine the time and disk space that could saved by having all of those incremental Adobe updates saved to a network location, rather than downloading them to each workstation.

In this post, I’ll explain how to delete files known as Flash cookies from a Windows computer using a batch file.

Most people are familiar with the concept of cookies – small files saved to your computer by the web sites you visit – and how to delete them. But there is a wide-spread misconception that simply deleting your cookies erases your tracks. Even when you’ve instructed your browser to delete cookies and browsing history, a potentially large collection of files remains, and the paths to these files contain the domain names of the sites that have placed them on your computer.

Local Shared Objects (LSO), commonly called Flash cookies, are collections of cookie-like data stored as a file on a user’s computer. LSOs are used by all versions of Adobe Flash Player…

With the default settings, Adobe Flash Player does not seek the user’s permission to store LSO files on the hard disk.

There is relatively little public awareness of LSOs, and they can usually not be deleted by the cookie privacy controls in a web browser.

http://en.wikipedia.org/wiki/Local_Shared_Object

The files are saved to two locations in the roaming profile:
%APPDATA%MacromediaFlash Player#SharedObjects
and
%APPDATA%MacromediaFlash Playermacromedia.comsupportflashplayersys

As an example, a visit to YouTube will result in the following folders being created:
C:UsersOliverAppDataRoamingMacromediaFlash Player#SharedObjects98X5KV83s.ytimg.com
C:UsersOliverAppDataRoamingMacromediaFlash Playermacromedia.comsupportflashplayersys#s.ytimg.com

Create a text file with the following lines, then save it as deleteLSOs.bat. Run the batch file to delete and remake these folders, thereby clearing all of the subfolders and files.

@echo off
copy "%APPDATA%MacromediaFlash Playermacromedia.comsupportflashplayersyssettings.sol" "%USERPROFILE%Local SettingsTempsettings.sol"
rmdir /s /q "%APPDATA%MacromediaFlash Player#SharedObjects"
md "%APPDATA%MacromediaFlash Player#SharedObjects"
rmdir /s /q "%APPDATA%MacromediaFlash Playermacromedia.comsupportflashplayersys"
md "%APPDATA%MacromediaFlash Playermacromedia.comsupportflashplayersys"
copy "%USERPROFILE%Local SettingsTempsettings.sol" "%APPDATA%MacromediaFlash Playermacromedia.comsupportflashplayersyssettings.sol"

Note that the script backs up and then restores a settings.sol file that contains the Flash Player global settings, which can be managed from the Flash Player Settings Manager.