http://learn.iis.net/page.aspx/563/using-classic-asp-with-microsoft-access-databases-on-iis-70-and-iis-75/
Note: Microsoft Access databases have been popular for many years with developers who use Active Server Pages (ASP) for small-scale applications, but Microsoft Access databases are not designed for scalability, therefore Access databases should only be used where performance is not a factor, and it is best not to host large-scale data-driven applications with Microsoft Access databases.
In IIS 7.0 and 7.5, several security changes were made that may affect how classic ASP applications will function. For example, if you were to copy a classic ASP application that uses an Access database that is within the Web site's content area to a server that uses IIS 7.0, you may receive the following error message:
Microsoft JET Database Engine error '80004005'Unspecified error./example.asp, line 100
This is a generic error triggered by the Access driver that may occur for a variety of reasons, but incorrect permissions is a common cause. More specifically, the ability to work with Microsoft Access databases is implemented through the Microsoft JET Database Engine, which creates various temporary and lock files when it connects to an Access database. The following sections will discuss some of the reasons why this may occur and how to resolve those situations.
Working with User Access Control
You need to make sure that you follow the steps in this document by using an account that has full administrative permissions. This is best accomplished by using one of two methods:
Log in to your computer by using the local administrator account.
If you are logged in using an account that administrative permissions but that is not the local administrator account, open all applications and all command prompt sessions by using the "Run as Administrator" option.
These above conditions are required because the User Account Control (UAC) security component in Windows Vista and Windows Server 2008 will prevent administrative access to IIS 7.0’s configuration settings. For more information about UAC, see the following documentation:
User Account Control
Initial Troubleshooting Investigation
If you have some form of tracing or debugging enabled, the trace or debug information may show the error occurring when the database connection is opened. For example, the following lines of ASP code :
strCN = "DRIVER={Microsoft Access Driver (*.mdb)};" & _ "DBQ=C:\Inetpub\wwwroot\App_Data\example.mdb"Set objCN = Server.CreateObject("ADODB.Connection")objCN.Open strCN ' <-- Note: ASP Error Occurs HerestrSQL = "SELECT * FROM TableName"Set objRS = objCN.Execute(strSQL)
Using Failed Request Tracing in IIS 7.0
If you have IIS 7.0's Failed Request Tracing configured to capture trace logs from HTTP 500 errors, you will see something that resembles the following illustration when you examine a trace log from the failure:
Although this error indicates that the failure occurred opening the database opened, it does not give any additional information to assist you with narrowing the problem to a specific area.
Using Process Monitor to gather more information
The Microsoft Windows Sysinternals Process Monitor utility is a great resource for tracking permissions-related problems. To use Process Monitor to trace the IIS issues in this topic, configure Process Monitor to filter tracing for only those events that are created by W3wp.exe processes, as shown in the following illustration:
Once you have configured the Process Monitor filter settings, configure Process Monitor to capture events and then reproduce your error. After you have reproduced your error, look through the Process Monitor capture log for any errors in the Result column of logs, as shown in the following illustration:
By analyzing the information in the Process Monitor logs, you can pinpoint any permissions-related issues. This will be illustrated in the following examples.
Permissions on the Temporary Folders
If you are using the Process Monitor utility on a computer that has a default installation of IIS 7.0 on Windows Server 2008 and Windows Vista SP1, you may receive an error that resembles the following when ASP connects to an Access database:
Process Name:
w3wp.exe
Operation:
CreateFile
Path:
C:\Windows\Temp\JET5150.tmp
Result:
ACCESS DENIED
Detail:
Desired Access:
Generic Read/Write, Delete
Disposition:
Create
Options:
Synchronous IO Non-Alert, Non-Directory File, Random Access, Delete On Close, Open No Recall
Attributes:
NT
ShareMode:
None
AllocationSize:
0
Impersonating:
NT AUTHORITY\IUSR
This error shows that the JET database engine cannot create a temporary file as the impersonated Application Pool identity in the default Windows temporary directory. This occurs when you use default settings for the release version of IIS 7.0 on Windows Server 2008 and Windows Vista SP1, where IIS does not load the user profile for the Application Pool identity's profile by default. To resolve this issue, you could change the permissions on the %SystemDrive%\Windows\Temp directory to allow read/write permission for the impersonated user.
If you are using the original release version of Windows Vista you may see an error that resembles the following when when ASP connects to an Access database:
Process Name:
w3wp.exe
Operation:
CreateFile
Path:
C:\Windows\ServiceProfiles\NetworkService\AppData\Local\Temp
Result:
ACCESS DENIED
Detail:
Desired Access:
Read Attributes
Disposition:
Open
Options:
Open Reparse Point
Attributes:
n/a
ShareMode:
Read, Write, Delete
AllocationSize:
n/a
Impersonating:
NT AUTHORITY\IUSR
This error indicates that the JET database engine cannot access the temporary directory for the Network Service user profile that uses the impersonated Application Pool identity. In this particular example, the Application Pool identity is configured to use the Network Service account and IIS is configured to load the user profile for the impersonated Application Pool identity. The error occurs because the impersonated Application Pool identity cannot access the temporary folder for the Network Service account. To resolve this specific issue, you can change the permissions on the %SystemDrive%\Windows\ServiceProfiles\NetworkService\AppData\Local\Temp directory to allow read/write permission for the impersonated user, or you can configure IIS to not load the user profile, which will change the temporary folder that the JET database engine will use.
The configuration setting that governs whether the user profile is loaded for the Application Pool identity is loadUserProfile, which is set to false, by default. You can configure this setting by changing the value of the Load User Profile attribute in the Advanced Settings dialog box for an application pool.
You can also configure this setting by using the command-line tool AppCmd.exe with the following syntax:
appcmd.exe set config -section:system.applicationHost/applicationPools /[name='DefaultAppPool'].processModel.loadUserProfile:"False" /commit:apphost
Permissions on Content Folders
When you are deploying a classic ASP application that uses an Access database you may see this error because the lock file for the Access database cannot be created. To further explain this scenario: Access databases are kept in files that use an .MDB file name extension. When you try to add to the database or update the data, the Microsoft JET database engine attempts to create a lock file with that uses an .LDB file name extension. If the Access database is stored within the content area of your Web site, by default the JET database engine will not have sufficient access permissions to update the database and you will see the following error message displayed in a Web browser:
Microsoft JET Database Engine error '80004005'Operation must use an updateable query./example.asp, line 100
If you were using the Process Monitor utility when you reproduced the error, the following information would be logged for the failure:
Process Name:
w3wp.exe
Operation:
CreateFile
Path:
C:\Inetpub\wwwroot\App_Data\example.ldb
Result:
ACCESS DENIED
Detail:
Desired Access:
Generic Read/Write
Disposition:
OpenIf
Options:
Synchronous IO Non-Alert, Non-Directory File, Random Access, Open No Recall
Attributes:
N
ShareMode:
Read, Write
AllocationSize:
0
Impersonating:
NT AUTHORITY\IUSR
This error clearly lists the lock file as the cause of the failure. To resolve the issue, you can grant the application pool's impersonated identity read/write permission to the folder where the Access database is located, but that poses a security risk for your Web site. A better solution would be to move the Access database out of your Web site's content area to a folder where the application pool's impersonated identity has read/write permission, then create a System Data Source Name (DSN) that points to the database location. Your ASP code would then reference the System DSN in the connection string instead of the physical path of the database, which is also better for security. If you must store the database in the content area, you should always store the database in a folder that is blocked by default by IIS 7.0's request-filtering features, such as the App_Data folder.
More Information
For additional information about the loadUserProfile and other application pool attributes, see the following pages on the Microsoft Support and IIS.net Web sites:
http://www.iis.net/ConfigReference/system.applicationHost/applicationPools/add/processModel
Error message when you request an ASP page that connects to an Access database in IIS 7.0: "Microsoft JET Database Engine error '80004005'"
http://learn.iis.net/page.aspx/565/using-failed-request-tracing-to-troubleshoot-classic-asp-errors/
February 21, 2009
Tips for Classic ASP developers on IIS7
http://blogs.iis.net/bills/archive/2007/05/21/tips-for-classic-asp-developers-on-iis7.aspx
I was reminded the other day just how many classic ASP applications and developers there are out there! The original ASP rocks, I remember experiencing it for the first time back in 1996/97 when it first came out with IIS3, and being amazed at how programmable it was compared to ColdFusion. I built many an application using Classic ASP, and there will always be a soft spot in my heart for it. :)
There are a few changes in IIS7 which Classic ASP developers should be aware of.
ASP not installed by default
First things first! If you're moving from XP to Windows Vista / Longhorn Server, you may be getting this error:
--------------------------------------------------------------------------------------------------------------------
HTTP Error 404.3 - Not Found
Description: The page you are requesting cannot be served because of the Multipurpose Internet Mail Extensions (MIME) map policy that is configured on the Web server. The page you requested has a file name extension that is not recognized, and is not allowed.
--------------------------------------------------------------------------------------------------------------------
this is usually the case when you haven't installed the ASP component. Go to where you installed IIS and look under IIS/WWW Services/Application Development/ASP and install it. :)
Access and Classic ASP
A lot of people use Access as a database - because it is small, can be copied around, and is easy to manage. One of the changes we made in IIS7 in Vista broke using ASP and Access by default. I described this change in more detail in this post, but essentially it has to do with the fact that Application Pools now use the Application Pool identity's profile and temporary directory, rather than \windows\temp by default. And since the only one that can write to Network Service's temp directory is the Network Service, anonymous or authenticated ASP applications break, since ASP uses the impersonated identity to access the database. If you use ASP and Access on IIS7, you've probably seen this error, or a variation of it:
--------------------------------------------------------------------------------------------------------------------
Microsoft JET Database Engine error '80004005' Unspecified error
--------------------------------------------------------------------------------------------------------------------
The answer is pretty straight forward: turn off loadUserProfile, or ACL the temp directory to allow writes. As a result of this and other compatibility issues, we're considering reverting this change in Longhorn Server / Vista SP1. In the mean time, you can work around it by doing either of the following:
This appcmd command will turn off loadUserProfile for the Default Application Pool. if your application runs in a different AppPool, make the corresponding change:
%windir%\system32\inetsrv\appcmd set config /section:applicationPools /[name='DefaultAppPool'].processModel.loadUserProfile:false
This command will ACL the Network Service temp directory to allow creator write / read privledges. If you run your Application Pool under a different identity, you'll need to ACL that owner's temp directory:
icacls %windir%\serviceprofiles\networkservice\AppData\Local\Temp /grant Users:(CI)(S,WD,AD,X)
icacls %windir%\serviceprofiles\networkservice\AppData\Local\Temp /grant "CREATOR OWNER":(OI)(CI)(IO)(F)
**Update 2/19/2009** if you are having issues with Access and ASP you might want to read this terrific guide recently posted on IIS.NET: http://learn.iis.net/page.aspx/563/using-classic-asp-with-microsoft-access-databases-on-iis-70-and-iis-75/
Script errors no longer shown in browser by default
As a result of our security paranoia, we turned off ASP's default behavior of sending script errors (including line number and code snippet to the browser. So instead of seeing the typical error you would see ASP throw, you will now see this:
--------------------------------------------------------------------------------------------------------------------
An error occurred on the server when processing the URL. Please contact the system administrator
--------------------------------------------------------------------------------------------------------------------
To revert back to IIS6- behavior, simply run the following command:
%windir%\system32\inetsrv\appcmd set config -section:asp -scriptErrorSentToBrowser:true
Or you can find it in the UI here:
then you'll be back to seeing this style of error instead:
--------------------------------------------------------------------------------------------------------------------
Microsoft VBScript compilation error '800a03ea'
Syntax error
/test.asp, line 4Response.Write("I love classic ASP" && foo)
-------------------------------------^
--------------------------------------------------------------------------------------------------------------------
Parents paths disabled by default (redux)
We disabled parent paths by default with IIS6, but I've seen this hit people on Vista coming from XP, where it is still enabled by default in IIS5.1 The enableParentPaths setting determines where ASP "includes" should be allowed to escape the parent directory (eg. ../../../includeFile.inc). You'll see this error by default if you try to escape the current directory:
--------------------------------------------------------------------------------------------------------------------
Active Server Pages error 'ASP 0131'
Disallowed Parent Path
/test.asp, line 1
The Include file '../bad.inc' cannot contain '..' to indicate the parent directory.
--------------------------------------------------------------------------------------------------------------------
or you may see this error if you are using a path with ../ in it and your ADODB code
--------------------------------------------------------------------------------------------------------------------
Server.MapPath() error 'ASP 0175 : 80004005'
Disallowed Path Characters
/testdir/test.asp, line 9
The '..' characters are not allowed in the Path parameter for the MapPath method.
--------------------------------------------------------------------------------------------------------------------
To revert back to IIS 5.x behavior, simply run the following command:
%windir%\system32\inetsrv\appcmd set config -section:asp -enableParentPaths:true
or you can find the UI setting here:
APPL_PHYSICAL_PATH no longer returns "\" with path
If you use Request.ServerVariables("APPL_PHYSICAL_PATH") to get at the physical path for your application, you may notice that the physical path no longer returns with a trailing slash. In previous releases of IIS, we returned this value as stored in the metabase. In IIS7, we calculate this value based on the configuration store, and we never return a trailing slash. You'll need to account for this especially if you are the return value with some other part of the path in your application.
Session_OnEnd not firing
If you find that Session_onEnd event in your global.asa is not firing, check out this blog post from Lou on the issue and the fix.
Summary
I browsed through the IIS7 Classic ASP Forums, and these tips seemed to cover nearly all of the issues people were having. if you are having a problem with ASP on IIS7, check out the forums or leave a comment for me here. If I find the answer, I'll add it to this post! Thanks!
I was reminded the other day just how many classic ASP applications and developers there are out there! The original ASP rocks, I remember experiencing it for the first time back in 1996/97 when it first came out with IIS3, and being amazed at how programmable it was compared to ColdFusion. I built many an application using Classic ASP, and there will always be a soft spot in my heart for it. :)
There are a few changes in IIS7 which Classic ASP developers should be aware of.
ASP not installed by default
First things first! If you're moving from XP to Windows Vista / Longhorn Server, you may be getting this error:
--------------------------------------------------------------------------------------------------------------------
HTTP Error 404.3 - Not Found
Description: The page you are requesting cannot be served because of the Multipurpose Internet Mail Extensions (MIME) map policy that is configured on the Web server. The page you requested has a file name extension that is not recognized, and is not allowed.
--------------------------------------------------------------------------------------------------------------------
this is usually the case when you haven't installed the ASP component. Go to where you installed IIS and look under IIS/WWW Services/Application Development/ASP and install it. :)
Access and Classic ASP
A lot of people use Access as a database - because it is small, can be copied around, and is easy to manage. One of the changes we made in IIS7 in Vista broke using ASP and Access by default. I described this change in more detail in this post, but essentially it has to do with the fact that Application Pools now use the Application Pool identity's profile and temporary directory, rather than \windows\temp by default. And since the only one that can write to Network Service's temp directory is the Network Service, anonymous or authenticated ASP applications break, since ASP uses the impersonated identity to access the database. If you use ASP and Access on IIS7, you've probably seen this error, or a variation of it:
--------------------------------------------------------------------------------------------------------------------
Microsoft JET Database Engine error '80004005' Unspecified error
--------------------------------------------------------------------------------------------------------------------
The answer is pretty straight forward: turn off loadUserProfile, or ACL the temp directory to allow writes. As a result of this and other compatibility issues, we're considering reverting this change in Longhorn Server / Vista SP1. In the mean time, you can work around it by doing either of the following:
This appcmd command will turn off loadUserProfile for the Default Application Pool. if your application runs in a different AppPool, make the corresponding change:
%windir%\system32\inetsrv\appcmd set config /section:applicationPools /[name='DefaultAppPool'].processModel.loadUserProfile:false
This command will ACL the Network Service temp directory to allow creator write / read privledges. If you run your Application Pool under a different identity, you'll need to ACL that owner's temp directory:
icacls %windir%\serviceprofiles\networkservice\AppData\Local\Temp /grant Users:(CI)(S,WD,AD,X)
icacls %windir%\serviceprofiles\networkservice\AppData\Local\Temp /grant "CREATOR OWNER":(OI)(CI)(IO)(F)
**Update 2/19/2009** if you are having issues with Access and ASP you might want to read this terrific guide recently posted on IIS.NET: http://learn.iis.net/page.aspx/563/using-classic-asp-with-microsoft-access-databases-on-iis-70-and-iis-75/
Script errors no longer shown in browser by default
As a result of our security paranoia, we turned off ASP's default behavior of sending script errors (including line number and code snippet to the browser. So instead of seeing the typical error you would see ASP throw, you will now see this:
--------------------------------------------------------------------------------------------------------------------
An error occurred on the server when processing the URL. Please contact the system administrator
--------------------------------------------------------------------------------------------------------------------
To revert back to IIS6- behavior, simply run the following command:
%windir%\system32\inetsrv\appcmd set config -section:asp -scriptErrorSentToBrowser:true
Or you can find it in the UI here:
then you'll be back to seeing this style of error instead:
--------------------------------------------------------------------------------------------------------------------
Microsoft VBScript compilation error '800a03ea'
Syntax error
/test.asp, line 4Response.Write("I love classic ASP" && foo)
-------------------------------------^
--------------------------------------------------------------------------------------------------------------------
Parents paths disabled by default (redux)
We disabled parent paths by default with IIS6, but I've seen this hit people on Vista coming from XP, where it is still enabled by default in IIS5.1 The enableParentPaths setting determines where ASP "includes" should be allowed to escape the parent directory (eg. ../../../includeFile.inc). You'll see this error by default if you try to escape the current directory:
--------------------------------------------------------------------------------------------------------------------
Active Server Pages error 'ASP 0131'
Disallowed Parent Path
/test.asp, line 1
The Include file '../bad.inc' cannot contain '..' to indicate the parent directory.
--------------------------------------------------------------------------------------------------------------------
or you may see this error if you are using a path with ../ in it and your ADODB code
--------------------------------------------------------------------------------------------------------------------
Server.MapPath() error 'ASP 0175 : 80004005'
Disallowed Path Characters
/testdir/test.asp, line 9
The '..' characters are not allowed in the Path parameter for the MapPath method.
--------------------------------------------------------------------------------------------------------------------
To revert back to IIS 5.x behavior, simply run the following command:
%windir%\system32\inetsrv\appcmd set config -section:asp -enableParentPaths:true
or you can find the UI setting here:
APPL_PHYSICAL_PATH no longer returns "\" with path
If you use Request.ServerVariables("APPL_PHYSICAL_PATH") to get at the physical path for your application, you may notice that the physical path no longer returns with a trailing slash. In previous releases of IIS, we returned this value as stored in the metabase. In IIS7, we calculate this value based on the configuration store, and we never return a trailing slash. You'll need to account for this especially if you are the return value with some other part of the path in your application.
Session_OnEnd not firing
If you find that Session_onEnd event in your global.asa is not firing, check out this blog post from Lou on the issue and the fix.
Summary
I browsed through the IIS7 Classic ASP Forums, and these tips seemed to cover nearly all of the issues people were having. if you are having a problem with ASP on IIS7, check out the forums or leave a comment for me here. If I find the answer, I'll add it to this post! Thanks!
Running classic ASP on IIS 7
http://www.alexthissen.nl/blogs/main/archive/2008/02/18/running-classic-asp-on-iis-7.aspx
Running classic ASP on IIS 7
It's not really difficult to run classic ASP on Internet Information Server 7, but there are some bumps down the road. Here's a little help to get you started:
First of all, check whether you have the Windows feature for ASP installed. Go to Programs and Features in Control Panel and click Turn Windows features on and off. Navigate down the tree of features and make sure ASP is checked.
Next, go to Internet Information Server (IIS) Manager (run inetmgr from the Start Search box to get there fast) and create a new application pool for ASP.
This should be a "No managed code" and "Classic" app pool if you do not intend to mix and match the .NET Framework and ASP.NET in the same pool. The Integrated pipeline would not make sense, because it only applies to integrating HTTP modules that are either native or managed .NET implementations.
I had some difficulties setting the identity of the application pool to the new built-in IUSR account. This account replaces the former computer account called IUSR_machinename. Same goes for the IIS_WPG group for application pools that is replaced by the builtin group IIS_IUSRS. Read more about it here. Under the Advanced Settings of the "ASP" application pool you will find the Identity property under Process Model. The default value is NetworkService. I found no way to set this to the BUILTIN\IUSR by choosing SpecificUser and setting BUILTIN\USR under Identity SpecificUser Credentials. I guess that you shouldn't be running ASP sites under IUSR anymore. It is used for anonymous users automatically.
To easy the administration effort, there is a way to turn off the IUSR account without turning off anonymous identification:
appcmd set config -section:anonymousAuthentication -userName:"" --password
And lastly, create your new web application. For example, copy the ASP site folder under C:\inetpub\wwwroot, where the default installation location of "Default Web Site" of IIS. Convert the folder (or virtual directory) to an application and choose "ASP" as the application pool. Check whether the .asp extension is mapped to the correct handler and whether it is enabled. Also make sure that the identity of your application pool has sufficient rights (and no more than that) to access the files in the web site's folder.
One final note: whenever there is a error in the ASP website, and you get this error message: "An error occurred on the server when processing the URL. Please contact the system administrator",
it's probably because by default no error messages are sent to the client in IIS7. Change the setting "Send Errors To Browser" of your web application under the ASP icon to reveal such errors.
Side note: if you get the nice Internet Explorer 500 error message and no particular details at all, remember to uncheck the "Show friendly HTTP error messages" checkbox under Internet Options, Advanced of IE.
Running classic ASP on IIS 7
It's not really difficult to run classic ASP on Internet Information Server 7, but there are some bumps down the road. Here's a little help to get you started:
First of all, check whether you have the Windows feature for ASP installed. Go to Programs and Features in Control Panel and click Turn Windows features on and off. Navigate down the tree of features and make sure ASP is checked.
Next, go to Internet Information Server (IIS) Manager (run inetmgr from the Start Search box to get there fast) and create a new application pool for ASP.
This should be a "No managed code" and "Classic" app pool if you do not intend to mix and match the .NET Framework and ASP.NET in the same pool. The Integrated pipeline would not make sense, because it only applies to integrating HTTP modules that are either native or managed .NET implementations.
I had some difficulties setting the identity of the application pool to the new built-in IUSR account. This account replaces the former computer account called IUSR_machinename. Same goes for the IIS_WPG group for application pools that is replaced by the builtin group IIS_IUSRS. Read more about it here. Under the Advanced Settings of the "ASP" application pool you will find the Identity property under Process Model. The default value is NetworkService. I found no way to set this to the BUILTIN\IUSR by choosing SpecificUser and setting BUILTIN\USR under Identity SpecificUser Credentials. I guess that you shouldn't be running ASP sites under IUSR anymore. It is used for anonymous users automatically.
To easy the administration effort, there is a way to turn off the IUSR account without turning off anonymous identification:
appcmd set config -section:anonymousAuthentication -userName:"" --password
And lastly, create your new web application. For example, copy the ASP site folder under C:\inetpub\wwwroot, where the default installation location of "Default Web Site" of IIS. Convert the folder (or virtual directory) to an application and choose "ASP" as the application pool. Check whether the .asp extension is mapped to the correct handler and whether it is enabled. Also make sure that the identity of your application pool has sufficient rights (and no more than that) to access the files in the web site's folder.
One final note: whenever there is a error in the ASP website, and you get this error message: "An error occurred on the server when processing the URL. Please contact the system administrator",
it's probably because by default no error messages are sent to the client in IIS7. Change the setting "Send Errors To Browser" of your web application under the ASP icon to reveal such errors.
Side note: if you get the nice Internet Explorer 500 error message and no particular details at all, remember to uncheck the "Show friendly HTTP error messages" checkbox under Internet Options, Advanced of IE.
Subscribe to:
Posts (Atom)