I had an interesting question earlier today which I thought was worth sharing. One of my coworkers was trying to use the code sample from my Programmatically Flushing FTP Logs blog, and he was getting the following error:
Unhandled Exception: System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
at Sample.Main() in c:\Projects\FtpTests\Program.cs:line 25
I knew that the code sample in my blog worked perfectly when I originally wrote it, so I figured that my coworker must be doing something wrong. (And every developer has said "It works on my computer..." at one time or other.) But I decided to give him the benefit of the doubt, so I copied the source code from my blog into a new Visual Studio project and I ran it.
Much to my surprise, I saw the same error that my coworker was seeing if I didn't step the code through with a debugger.
When I stepped through the code in a debugger, I saw the following error message:
At this point I was thinking, "What the heck? I know this code was working before..." I started to wonder if we had released a breaking change to the FTP service sometime during the past two years, but then it suddenly dawned on me: I hadn't started the FTP service on my computer.
That was the source of the problem: I usually have the FTP service configured for manual startup on my development computers, but the FTP methods to start and stop FTP sites and flush the FTP logs do not work when the FTP service is not running. Once both of us started the FTP service on each of our systems the problem went away.
I hope this helps. ;-]
Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/
Whenever I am delivering a presentation where I need to use PHP, I typically use a batch file that I wrote in order to rapidly deploy PHP on the system that I am using for my demos. The batch file usually takes less than a second to run, which always seems to amaze people in the audience. As a result, I usually have several people ask me for my batch file after each presentation, so I thought that it would make a good subject for today's blog.
I should mention that I have used this batch file in order to demonstrate PHP with IIS in a variety of scenarios, and one of my favorite demos is when I would borrow someone's laptop and plug in a flash drive where I had IIS Express pre-installed, and then I would run the batch file in this blog to deploy PHP. Next I would launch IIS Express, open a web browser on their system, and then browse to http://localhost/ in order to show that IIS Express was working correctly. Lastly I would write a simple PHP "Hello World" page to show that PHP was up-and-running on their system in a matter of seconds.
That being said, I have to point out that there is a very important prerequisite that you must have in order to follow the steps in the blog: you need to start with a known-good installation of PHP from one of your systems, and I'll explain what I mean by that.
My batch file expects to find a folder containing ready-to-run files for PHP in order to deploy PHP on a new system. I originally obtained my PHP files by using the Web Platform Installer (WebPI) to install PHP, and then I copied the files to my flash drive or some other repository. (Note that WebPI usually installs PHP in the "%ProgramFiles(x86)%\PHP" folder.) If you don't want to use WebPI, you can also download PHP from http://windows.php.net/, but you're on your own for configuration.
Once I have the files from a known-good installation of PHP, I create the following folder structure in the location where I will be storing the files that I use to deploy PHP on other systems:
- <root folder>
- SETUP_PHP.cmd (the batch file from this blog)
- PHP (the folder containing the PHP files)
- etc. (all of the remaining PHP files and folders)
One thing to note is that the PHP.INI file you use may contain paths which refer to specific directories on the system from which you are copying your PHP files, so you need to make sure that those paths will exist on the system where you deploy PHP.
Here is an example: when I used WebPI to install PHP 5.5 on a system with IIS, it installed PHP into my "%ProgramFiles(x86)%\PHP\v5.5" folder. During the installation process, WebPI updated the PHP file to reflect any paths that need to be defined. At the time that I put together my notes for this blog, those updates mainly applied to the path where PHP expects to find it's extensions:
extension_dir="C:\Program Files (x86)\PHP\v5.5\ext\"
What this means is - if you want to deploy PHP to some other path on subsequent systems, you will need to update at least that line in the PHP.INI file that you are using to deploy PHP. In my particular case, I prefer to deploy PHP to the "%SystemDrive%\PHP" path, but it can be anywhere as long as you update everything accordingly.
The following batch file will deploy the PHP files in the "%SystemDrive%\PHP" folder on your system, and then it will update IIS with the necessary settings for this PHP deployment to work:
REM Change to the installation folder
REM Cheap test to see if IIS is installed
if exist "%SystemRoot%\System32\inetsrv" (
REM Check for the PHP installation files in a subfolder
if exist "%~dp0PHP" (
REM Check for an existing installation of PHP
if not exist "%SystemDrive%\PHP" (
REM Create the folder for PHP
REM Deploy the PHP files
xcopy /erhky "%~dp0PHP\*" "%SystemDrive%\PHP"
REM Configure the IIS settings for PHP
appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='%SystemDrive%\PHP\php-cgi.exe',monitorChangesTo='php.ini',activityTimeout='600',requestTimeout='600',instanceMaxRequests='10000']" /commit:apphost
appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='%SystemDrive%\PHP\php-cgi.exe',monitorChangesTo='php.ini',activityTimeout='600',requestTimeout='600',instanceMaxRequests='10000'].environmentVariables.[name='PHP_FCGI_MAX_REQUESTS',value='10000']" /commit:apphost
appcmd.exe set config -section:system.webServer/fastCgi /+"[fullPath='%SystemDrive%\PHP\php-cgi.exe',monitorChangesTo='php.ini',activityTimeout='600',requestTimeout='600',instanceMaxRequests='10000'].environmentVariables.[name='PHPRC',value='%SystemDrive%\PHP']" /commit:apphost
appcmd.exe set config -section:system.webServer/handlers /+"[name='PHP_via_FastCGI',path='*.php',verb='GET,HEAD,POST',modules='FastCgiModule',scriptProcessor='%SystemDrive%\PHP\php-cgi.exe',resourceType='Either']" /commit:apphost
Once you have all of that in place, it usually takes less than a second to deploy PHP, which is why so many people seem interested during my presentations.
Note that you can deploy PHP for IIS Express just as easily by updating the "%SystemRoot%\System32\inetsrv" paths in the batch file to "%ProgramFiles%\IIS Express" or "%ProgramFiles(x86)%\IIS Express" paths. You can also use this batch file as part of a deployment process for PHP within a web farm; in which case, you will need to pay attention to the paths inside your PHP.INI file which I mentioned earlier.
Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/
OK - I have to admit, I have used SkyDrive for several years now, and I have learned to become dependent on it because I like having several of my files easily accessible everywhere I go and on every device.
Apparently that was a big mistake on my part, because the SkyDrive team at Microsoft has slowly made SkyDrive a piece of crap. Having just set up my laptop with a brand-new installation of Windows 8.1 (which I installed from scratch), I can honestly say that SkyDrive in Windows 8.1 is now a complete failure as far as I am concerned. So unfortunately I'm probably going to have to switch to a third-party cloud storage application - and that sucks.
Before I discuss what's screwed up with SkyDrive in Windows 8.1, I should first mention that Microsoft used to make Windows Live Mesh, which was much better than SkyDrive. Mesh allowed you to choose any folder on your system and synchronize it across any machine that you specified. (In contrast, SkyDrive only synchronizes folders which are directly beneath the parent SkyDrive folder.) What's more, Mesh had a built-in remote desktop feature that was much like the built-in Windows Remote Desktop functionality - except that it actually worked. (If you've ever tried to manage a firewall and get the built-in Windows Remote Desktop functionality working over the Internet through your firewall and across a NAT, you know what I mean.) Unfortunately Microsoft's long-standing policy appears to be the following: if Microsoft has two competing technologies, choose the lesser of the two and ship that, and then deprecate the better technology. (At least that's what happened with SkyDrive and Mesh.)
Anyway - here are just a few of things things that are screwed up about SkyDrive in Windows 8.1:
In Windows 7, you had to manually choose to install the SkyDrive desktop functionality, so this was an opt-in feature. Of course, I installed SkyDrive, and I used it often. Unlike Windows Live Mesh, you had to drop files in the SkyDrive folder, which was really inconvenient. But that's also the way that DropBox works, so I'm sure that's what the engineers who were designing SkyDrive were trying to emulate.
In any event, after I installed SkyDrive on several of my systems, all of my SkyDrive-based files were physically stored on each of my local systems, and they were adequately synchronized across all machines where I installed SkyDrive. If I wanted to temporarily disable SkyDrive on any system, I could right-click on the SkyDrive System Tray icon and choose to close it.
However, once I installed Windows 8.1, everything changed. First of all SkyDrive is not optional - it's just there, and it appears to be always on. What's worse, my files weren't actually on my laptop anymore; they looked like they were locally stored, but they were more like ghost files which would actually download from the Internet whenever I tried to access a file. This was a pain in the butt for the system utilities which I was storing in my SkyDrive - most of them ceased to function because the EXE would download, but none of the supplemental DLL files would. As a direct result, all of my system utilities failed to run.
After some poking around I discovered that I could right-click on the SkyDrive folder and choose to make it available offline, which worked - albeit with hours of waiting for 25GB of files to download over Wi-Fi. But I need to point out that I had to go out of my way to make SkyDrive work the way that it used to; and more importantly, I had to discover on my own how to make something work the way that it always did in the past. This is known as a "Breaking Change," although I prefer to call that "Bad Design."
But today is when everything went from bad to worse. I needed to go to an appointment, so I brought my laptop with me because I thought that I would be able to do some work while I waited for my scheduled appointment time. I had a folder in my SkyDrive with some work-related files in it, so this seemed like something that should just work.
But it didn't work. In fact, it failed miserably.
What happened is this: I arrived at my appointment and booted my laptop, but when I opened my SkyDrive folder, everything was missing. Needless to say, I was more than a little alarmed. I opened Windows Explorer and navigated to the folder for my user profile, where I saw two folders that were both named "SkyDrive." Since Windows does not allow two folders with the same name in the same directory, I knew that this was a display anomaly which was probably caused by identical desktop.ini files in the two SkyDrive directories. I opened a command prompt and changed directories to my user profile folder, and the directory listing showed two folders: "SkyDrive" and SkyDrive (2)".
So I was correct in my assumption, and I verbally expressed my exasperation on the idiocy of this situation. ("What the heck...? Those stupid sons-of-biscuits...") I could immediately tell that Windows 8.1 had screwed something up, and my life was going to suck until I sorted it out.
I will spare you the details for everything that I tried to do, but it involved a lot of copying & renaming of files & folders - and after several hours of troubleshooting I still didn't have it resolved. But just to make things worse, while I was doing my troubleshooting I discovered that I suddenly had three folders under my user profile: "SkyDrive" and SkyDrive (2)," and "SkyDrive.old". I searched the Internet, and I found out that a lot of users have seen this problem.
A... lot... of... users...
There seemed to be two common consensuses: 1) this was clearly a bug in SkyDrive on Windows 8.1, and 2) SkyDrive now sucks for this reason.
One thing became clear to me: SkyDrive was going to continue to make my life miserable until I got it out of the way long enough for me to fix things. If you do some searching on the Internet, you can find ways to disable SkyDrive through Windows group policy, but I didn't want it permanently disabled - I just wanted it out of the way long enough to sort out the problem with multiple folders. Incidentally, logging out as my user account and logging in as the local administrator account did not make this easier since SkyDrive.exe runs at the system level.
Eventually I had to resort to backing up all of my multiple SkyDrive folders to an alternate location, and then running the following batch file while I manually cleaned up the multiple folders:
for %%a in (explorer.exe skydrive.exe) do (
wmic process where name='%%a' call terminate
Note that I had to put these process termination statements in a loop because Windows would keep restarting both executables, thereby thwarting any repairs that I had managed to start.
Yes, this is a lame and prosaic approach to solving this problem, but releasing a major breaking change to a service upon which you hope everyone will depend is pretty darn lame, too. And making the new service so heinously awful that it's barely usable is unforgivably lame.
Eventually I got everything sorted out, and I would love to be able to write something definitive like, "You need to do X and Y and your system will be better." But truth-be-told, I spent so many hours trying so many things that I cannot be certain which specific steps resolved the issue. And I'm not about to attempt setting up a repro environment to test which steps to take. Sorry about that - but I simply don't want to mess with things now that I have SkyDrive working again.