Automate copying IIS logs to SQL Database using Powershell, Log Parser and Task Scheduler

I decided not to go down the route of writing an SSIS package as mentioned in my previous post

So how else can you do what I wanted to achieve?

  • Remove all copied logs from the Database server
  • Copy yesterdays logs from 9 web servers
  • Import the logs to a SQL Database

This is how I did it:

Step 1 : Create 3 Powershell scripts

Copy IIS files from yesterday:

$Date = Get-Date
$Date = $Date.adddays(-1)
$Date2Str = $Date.ToString("yyyMMdd")

$Files1 = gci "\\server1\c$\inetpub\logs\LogFiles\W3SVC2"
ForEach ($File in $Files1){
     $FileDate = $File.creationtime
     $CTDate2Str = $FileDate.ToString("yyyyMMdd")
     if ($CTDate2Str -eq $Date2Str) {Copy-Item $File.Fullname "C:\\Logs\\1718\\server1"}
}

$Files2 = gci "\\server2\c$\inetpub\logs\LogFiles\W3SVC2"
ForEach ($File in $Files2){
     $FileDate = $File.creationtime
     $CTDate2Str = $FileDate.ToString("yyyyMMdd")
     if ($CTDate2Str -eq $Date2Str) {Copy-Item $File.Fullname "C:\\Logs\\1718\\server2"}
}

$Files3 = gci "\\server3\c$\inetpub\logs\LogFiles\W3SVC2"
ForEach ($File in $Files3){
     $FileDate = $File.creationtime
     $CTDate2Str = $FileDate.ToString("yyyyMMdd")
     if ($CTDate2Str -eq $Date2Str) {Copy-Item $File.Fullname "C:\\Logs\\1718\\server3"}
}

Remove all local iis log files:

$ErrorActionPreference = "Stop"

Import-Module Pscx -EA 0

function RemoveLogFiles
{
    Write-Host "Removing log files..."
    Remove-Item ($httpLogPath1)
	Remove-Item ($httpLogPath2)
	Remove-Item ($httpLogPath3)
	Remove-Item ($httpLogPath4)
	Remove-Item ($httpLogPath5)
	Remove-Item ($httpLogPath6)
	Remove-Item ($httpLogPath7)
	Remove-Item ($httpLogPath8)
	Remove-Item ($httpLogPath9)
}

function Main
{	

	[string] $httpLogPath1 = "C:\Logs\1718\server1\*.log"
	[string] $httpLogPath2 = "C:\Logs\1718\server2\*.log"
	[string] $httpLogPath3 = "C:\Logs\1718\server3\*.log"

	[string] $httpLogPath4 = "C:\Logs\1718\server4\W3SVC1\*.log"
	[string] $httpLogPath5 = "C:\Logs\1718\server5\W3SVC1\*.log"
	[string] $httpLogPath6 = "C:\Logs\1718\server6\W3SVC1\*.log"

	[string] $httpLogPath7 = "C:\Logs\1718\server7\W3SVC2\*.log"
	[string] $httpLogPath8 = "C:\Logs\1718\server8\W3SVC2\*.log"
	[string] $httpLogPath9 = "C:\Logs\1718\server9\W3SVC2\*.log"

    RemoveLogFiles 

    Write-Host -Fore Green "Successfully removed log files."
}

Main

Import Website Logs to Database:

$ErrorActionPreference = "Stop"

Import-Module Pscx -EA 0

function ExtractLogFiles(
    [string] $httpLogPath)
{
    If ([string]::IsNullOrEmpty($httpLogPath) -eq $true)
    {
        Throw "The log path must be specified."
    }

    [string] $httpLogArchive = $httpLogPath + "c:\logs\1718\*.log"

    If ((Test-Path $httpLogArchive) -eq $false)
    {
        Write-Host "Creating archive folder for compressed log files..."
        New-Item -ItemType directory -Path $httpLogArchive | Out-Null
    }

    Write-Host "Extracting compressed log files..."

    Get-ChildItem $httpLogPath -Filter "*.zip" |
        ForEach-Object {
            Expand-Archive $_ -OutputPath $httpLogPath

            Move-Item $_.FullName $httpLogArchive
        }
}

function ImportLogFilesServer1(
    [string] $httpLogPath1)
{
    If ([string]::IsNullOrEmpty($httpLogPath1) -eq $true)
    {
        Throw "The log path must be specified."
    }

    [string] $logParser = "${env:ProgramFiles(x86)}" `
        + "\Log Parser 2.2\LogParser.exe "

    [string] $query = `
        [string] $query = `
        "SELECT" `
            + " LogFilename" `
            + ", RowNumber" `
            + ", TO_TIMESTAMP(date, time) AS EntryTime" `
            + ", s-ip AS sIp" `
            + ", cs-method AS csMethod" `
            + ", cs-uri-stem AS csUriStem" `
            + ", cs-uri-query AS csUriQuery" `
            + ", s-port AS sPort" `
			+ ", TO_STRING(cs-username) AS csUsername" `
            + ", c-ip AS cIp" `
            + ", cs(User-Agent) AS csUserAgent" `
            + ", cs(Referer) AS csReferer" `
            + ", sc-status AS scStatus" `
            + ", sc-substatus AS scSubstatus" `
            + ", sc-win32-status AS scWin32Status" `
            + ", time-taken AS timeTaken" `
        + " INTO IisLogs" `
        + " FROM $httpLogPath1"

    [string] $connectionString = "Driver={SQL Server Native Client 11.0};" `
        + "Server=<SQL Server>;Database=<Database Name>;Trusted_Connection=yes;"

    [string[]] $parameters = @()

	$parameters += $query
    $parameters += "-i:W3C"
	$parameters += "-e:-1"
	#$parameters += "-recurse:-1"
    $parameters += "-o:SQL"
	$parameters += "-createTable:ON"
    $parameters += "-oConnString:$connectionString"

    Write-Debug "Parameters: $parameters"

    Write-Host "Importing log files to database..."
    & $logParser $parameters
}

function ImportLogFilesServer2(
    [string] $httpLogPath2)
{
    If ([string]::IsNullOrEmpty($httpLogPath2) -eq $true)
    {
        Throw "The log path must be specified."
    }

    [string] $logParser = "${env:ProgramFiles(x86)}" `
        + "\Log Parser 2.2\LogParser.exe "

    [string] $query = `
        [string] $query = `
        "SELECT" `
            + " LogFilename" `
            + ", RowNumber" `
            + ", TO_TIMESTAMP(date, time) AS EntryTime" `
            + ", s-ip AS sIp" `
            + ", cs-method AS csMethod" `
            + ", cs-uri-stem AS csUriStem" `
            + ", cs-uri-query AS csUriQuery" `
            + ", s-port AS sPort" `
			+ ", TO_STRING(cs-username) AS csUsername" `
            + ", c-ip AS cIp" `
            + ", cs(User-Agent) AS csUserAgent" `
            + ", cs(Referer) AS csReferer" `
            + ", sc-status AS scStatus" `
            + ", sc-substatus AS scSubstatus" `
            + ", sc-win32-status AS scWin32Status" `
            + ", time-taken AS timeTaken" `
        + " INTO IisLogs" `
        + " FROM $httpLogPath2"

    [string] $connectionString = "Driver={SQL Server Native Client 11.0};" `
        + "Server=<SQL Server>;Database=<Database Name>;Trusted_Connection=yes;"

    [string[]] $parameters = @()

	$parameters += $query
    $parameters += "-i:W3C"
	$parameters += "-e:-1"
	#$parameters += "-recurse:-1"
    $parameters += "-o:SQL"
	$parameters += "-createTable:ON"
    $parameters += "-oConnString:$connectionString"

    Write-Debug "Parameters: $parameters"

    Write-Host "Importing log files to database..."
    & $logParser $parameters
}

function ImportLogFilesServer3(
    [string] $httpLogPath3)
{
    If ([string]::IsNullOrEmpty($httpLogPath3) -eq $true)
    {
        Throw "The log path must be specified."
    }

    [string] $logParser = "${env:ProgramFiles(x86)}" `
        + "\Log Parser 2.2\LogParser.exe "

    [string] $query = `
        [string] $query = `
        "SELECT" `
            + " LogFilename" `
            + ", RowNumber" `
            + ", TO_TIMESTAMP(date, time) AS EntryTime" `
            + ", s-ip AS sIp" `
            + ", cs-method AS csMethod" `
            + ", cs-uri-stem AS csUriStem" `
            + ", cs-uri-query AS csUriQuery" `
            + ", s-port AS sPort" `
			+ ", TO_STRING(cs-username) AS csUsername" `
            + ", c-ip AS cIp" `
            + ", cs(User-Agent) AS csUserAgent" `
            + ", cs(Referer) AS csReferer" `
            + ", sc-status AS scStatus" `
            + ", sc-substatus AS scSubstatus" `
            + ", sc-win32-status AS scWin32Status" `
            + ", time-taken AS timeTaken" `
        + " INTO IisLogs" `
        + " FROM $httpLogPath3"

    [string] $connectionString = "Driver={SQL Server Native Client 11.0};" `
        + "Server=<SQL Server>;Database=<Database Name>;Trusted_Connection=yes;"

    [string[]] $parameters = @()

	$parameters += $query
    $parameters += "-i:W3C"
	$parameters += "-e:-1"
	#$parameters += "-recurse:-1"
    $parameters += "-o:SQL"
	$parameters += "-createTable:ON"
    $parameters += "-oConnString:$connectionString"

    Write-Debug "Parameters: $parameters"

    Write-Host "Importing log files to database..."
    & $logParser $parameters
}

function Main
{
	[string] $httpLogPath1 = "C:\Logs\1718\Server1\*.log"
	[string] $httpLogPath2 = "C:\Logs\1718\Server2\*.log"
	[string] $httpLogPath3 = "C:\Logs\1718\Server3\*.log"

#Repeat above for all other server

    ImportLogFilesServer1 $httpLogPath1
    ImportLogFilesServer2 $httpLogPath2
    ImportLogFilesServer3 $httpLogPath3	

#Repeat above for all other server

    Write-Host -Fore Green "Successfully imported log files."
}

Main

Finally you need to setup some scheduled tasks:

There’s a few little bits here which wouldn’t work for me without the following arguments:

Powershell.exe in Program/script:

-ExecutionPolicy Bypass -file “C:\powershell iis scripts\remove all iis log files.ps1” in Add arguments (optional):

task

The ‘Copy IIS files from yesterday’ script required some work with our server and storage team to add a service account to be able to run batch scripts without being logged on, this is in the Local Group Policy, This was due to being on a domain and the policy was set to not allow me to set this for my user. More details to come on this, its time consuming to explain in great detail.

 

 

 

Advertisements

IIS Logs to SQL Database using Powershell and Log Parser

Our IIS logs are ridiculously large, every time I am asked to find out some stats it takes me ages copying the files to my machine and running some log parser SQL on it.

So I thought it’s time to insert them into a SQL Database. I adapted a script which I mostly found here and used the following to do the import. At first I was getting the following error which I couldn’t figure out how to solve SQL table column “csUsername” date type is not compatible with SELECT clause item “csUsername” (type INTEGER)

PowershellSqlerror

This was being caused because some of the log files had the username as +12345678 or 12345678+ therefore no longer being an INTEGER and not being able to be imported.

To fix this look at line 27 of the following Powershell script to force csUsername to be a VARCHAR rather than an INTEGER

$ErrorActionPreference = "Stop"

Import-Module Pscx -EA 0

function ImportLogFiles(
    [string] $httpLogPath)
{
    If ([string]::IsNullOrEmpty($httpLogPath) -eq $true)
    {
        Throw "The log path must be specified."
    }

    [string] $logParser = "${env:ProgramFiles(x86)}" `
        + "\Log Parser 2.2\LogParser.exe"

    [string] $query = `
        [string] $query = `
        "SELECT" `
            + " LogFilename" `
            + ", RowNumber" `
            + ", TO_TIMESTAMP(date, time) AS EntryTime" `
            + ", s-ip AS sIp" `
            + ", cs-method AS csMethod" `
            + ", cs-uri-stem AS csUriStem" `
            + ", cs-uri-query AS csUriQuery" `
            + ", s-port AS sPort" `
            + ", TO_STRING(cs-username) AS csUsername" `
            + ", c-ip AS cIp" `
            + ", cs(User-Agent) AS csUserAgent" `
            + ", cs(Referer) AS csReferer" `
            + ", sc-status AS scStatus" `
            + ", sc-substatus AS scSubstatus" `
            + ", sc-win32-status AS scWin32Status" `
            + ", time-taken AS timeTaken" `
        + " INTO IisLogs" `
        + " FROM $httpLogPath"

    [string] $connectionString = "Driver={SQL Server Native Client 11.0};" `
        + "Server=&amp;amp;amp;lt;Database Server&amp;amp;amp;gt;;Database=&amp;amp;amp;lt;Database&amp;amp;amp;gt;;Trusted_Connection=yes;"

    [string[]] $parameters = @()

    $parameters += $query
    $parameters += "-i:W3C"
    $parameters += "-e:-1"
    $parameters += "-o:SQL"
    $parameters += "-createTable:ON"
    $parameters += "-oConnString:$connectionString"

    Write-Debug "Parameters: $parameters"

    Write-Host "Importing log files to database..."
    &amp;amp;amp;amp; $logParser $parameters
}

function Main
{
    $httpLogPath = "&amp;amp;amp;lt;Path to your logs&amp;amp;amp;gt;\*.log"

    ImportLogFiles $httpLogPath

    Write-Host -Fore Green "Successfully imported log files."
}

Main

Now I just need to write an SSIS package which will update the database with the IIS log files from 3 server and two sites (daily), so I’ll be back to update you on how I got along.

Okay Automate copying IIS logs to SQL Database using Powershell, Log Parser and Task Scheduler post is now written, continue reading to find out how

Migrating Oracle VB.net application from Windows 2003 to 2012

Lessons learnt whilst migrating a VB.net application from a Windows 2003 server to a Load balanced Windows 2012 server stack. Unfortunately it wasn’t as easy as deploying the old code on a new version of IIS.

One of the first issue that I had to solve was that the Oracle System.Data.OracleClient is now deprecated, therefore I needed to use oracle managed data access client Oracle.DataAccess.Client in order to connect to an Oracle DB using IIS 8.5

My web.config now looks something like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
<section name="oracle.manageddataaccess.client"       type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
  </configSections>
  <connectionStrings>
    <add name="*****" connectionString="Data Source=DataSource;User Id=******;PASSWORD=*******;"/>
  </connectionStrings>
  <appSettings/>
  <system.web>
    <sessionState mode="InProc" cookieless="false" timeout="30"/>
    <compilation strict="false" explicit="true" debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Extensions.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
        <add assembly="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
      </assemblies>
    </compilation>
    <customErrors mode="Off"/>
    <!--
   <customErrors mode="On" defaultRedirect="~/Error.aspx"/>
-->
    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
    <!--<httpRuntime requestValidationMode="2.0" />-->
  </system.web>
  <oracle.manageddataaccess.client>
    <version number="*">
      <dataSources>
        <dataSource alias="DataSource"           descriptor="(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = database.google.com)(PORT = 3426))) (CONNECT_DATA = (SERVICE_NAME = DBTEST)))"/>
      </dataSources>
    </version>
  </oracle.manageddataaccess.client>
  <system.webServer>
    <defaultDocument>
      <files>
        <add value="login.aspx"/>
      </files>
    </defaultDocument>
  </system.webServer>
  <system.data>
    <DbProviderFactories>
      <remove invariant="Oracle.ManagedDataAccess.Client"/>
      <add name="ODP.NET, Managed Driver" invariant="Oracle.ManagedDataAccess.Client" description="Oracle Data Provider for .NET, Managed Driver"         type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342"/>
    </DbProviderFactories>
  </system.data>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <publisherPolicy apply="no"/>
        <assemblyIdentity name="Oracle.ManagedDataAccess" publicKeyToken="89b483f429c47342" culture="neutral"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

The next task was to figure out where the oracle database would randomly drop its connection, I did this by debugging the code to VS2017,  I then had to open oracle datareader at several points, although the connection remained open at that same point when using the old oracle client.

A potentially dangerous Request.QueryString value was detected from the client. The application in question was creating one parameter in a report URL which was being formed using the ID from radio buttons selected. The HTML which was formed for the page changed between deploying and running the code on 2003 to how it appeared when it was being ran on a 2012 server. On the new server I was seeing that the parameter was passing in the wrong part of the HTML. Therefore it put in **** as a URL parameter. If at any point IIS or your browser sees this type of behavior it throws the above error.

How to fix this?

Two ways the easy way and the hard.

The easy way, which is not recommended

insert ValidationRequest=false into the page header for each ASP page as well as like this in your web.config, this shuts off the security feature and will leave your site open to scripting attacks:

<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpRuntime requestValidationMode="2.0" />
</system.web>

The hard way, figure out why the code is inserting a piece of HTML in as a parameter within a URL. It was doing this in my code due to the way that the HTML removed spaces, my code needed to determine where it was to grab the id of the radio button so was trying to locate a set point by reading in the ID of the radio button, because that was after value=2 > and it was looking for ‘value=’ + ID + ” “. Which it couldn’t find. as that was now written as value=2>.

But this won’t mean anything to you, as your code won’t be throwing an error because of the same reasons as above! Or at least for your sake I hope not!!

SSL for BI Publisher 10.1.3.4 Standalone

We have a old installation of Oracle Business Intelligence 10.1.3.4 which somehow has not been kept up to date – This happens through all businesses throughout the planet, the rule: If it works don’t touch it, applies to it.

So this server isn’t still running as HTTP, we needed to get it secured ASAP – 9 years late is better than never.

So how do you go about it?

Create a Java Keystore

For this you need to use the Keytool utility which comes with Java JDK / JRE on your server. See notes about this later on as this is a very outdated version of the Keytool utility.

Command to create a Java Keystore:

keytool -genkey -keyalg RSA -alias mykey -keystore mykeystore.jks

Enter a keystore password and remember it, I recommend that you use  Password Safe to generate and remember the password.

Create and Update secure-web-site.xml file

Make a copy of your existing file default-web-site.xml and name it secure-web-site.xml edit the new file and add secure=”true” to the end of the line as well as change your port, 9704 is HTTP as 9706 is the standard BI HTTPS port:

<web-site xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/web-site-10_0.xsd" port="9706" display-name="OC4J 10g (10.1.3) Default Web Site" schema-major-version="10" schema-minor-version="0" secure="true">

Now add the line:

<ssl-config keystore="full_path_to_your_keystore.jks" keystore-password="your_keystore_password" />

Before the closing tag

Register secure-web-site.xml file in server.xml

Towards the bottom of your server.xml file add:

<web-site default="true" path="./secure-web-site.xml" />

Remove the line referencing the ./default-web-site.xml you no longer need HTTP access once you have HTTPS enabled. You’ll need to do something which I didn’t to have both HTTP and HTTPS URL’s accessible on a reboot the server will automatically delete the second

Add a local firewall rule for the new 9706 port

Use ‘Windows Firewall’ and look for an existing Inbound rule for 9704, copy this rule and change the port number to 9706.

Test if HTTPS URL is working

Save the changes and restart ‘Oracle BI EE OC4J‘ server in ‘Services’ to reflect the changes, that or reboot the server.

Browse to : https://:9706/xmlpserver/ using the servers available web browser or your local machine, as there could be corporate firewalls in the way still, these will not know about you new port 9706 so will need to be enabled.

A quick test from a command prompt on your local machine to see is:

Telnet YourServer 9706

Secure your new address with a certificate

Go back to where you created your mykeystore.jks file and delete the mykey from within it:

keytool -delete -alias mykey -keystore mykeystore.jks

Now follow the following steps:

  • Request your certificate from your certification authority
  • Complete your certificate request in IIS or elsewhere
  • Export your your certificate as a .PFX file
  • Extract from the PFX your Key and Pem files
openssl pkcs12 -in yourCertificate.pfx -out yourCertificate.pem
  • Convert yourCertificate.pem to .pkcs12 file
openssl pkcs12 -export -in yourCertificate.pem -out yourCertificate.pkcs12
  • Now and very importantly move the yourCertificate.pkcs12 file away from your Oracle BI server as this will have a very old version of Java Keytool on it, which does not support the -importkeystore command, mine was running JRE 1.4.2.
  • Also move the empty mykeystore.jks file to the same directory as the yourCertificate.pkcs12
  • Check your mykeystore.jks to check it is empty
keytool -v -list -keystore mykeystore.jks
  • On the server with JRE / JDK 1.6 or above, I ran this using JRE 1.8, run the following command to import yourCertificate.pkcs12 to the mykeystore.jks
"C:\Program Files (x86)\Java\jre1.8.0_131\bin\keytool.exe" -v -importkeystore -srckeystore yourCertificate.pkcs12 -srcstoretype PKCS12 -destkeystore mykeystore.jks -deststoretype JKS
  • Now check your mykeystore.jks again and you should now have the imported certificate
  • Move this mykeystore.jks to the Oracle BI server

Restart ‘Oracle BI EE OC4J‘ server in ‘Services’ to reload the application with the new certificate or reboot the server.

You should now have a lovely secured server, if at first it doesn’t show check it on a browser that you haven’t used yet or clear your cache.

Migrating Classic ASP websites from Windows 2003 IIS 6 to 2012 R2 IIS 8

I have recently been working on getting some major applications off a Windows 2003 platform, as this platform no longer meets security requirements, as we all know Microsoft stopped supporting the servers in July 2015.

To do this process I started by using Windows Server 2003 Migration Planning Assistant and Atlassian’s JIRA to map out the key steps and outcomes. I then worked with our Service / Storage and Networks teams to get the new servers spin up in VMware and get them to open oh’so important firewalls so the new servers have the same access as the old one.

It was then a case of modelling the structure on my local installation of IIS (Internet Information Services) there were some parts that weren’t straight forward as it seems this I will explain here. I hope for your sake that your company has already migrated away from Classic ASP code.

  • Global.asa – This file now needs to be in each application, rather than just one on your top level website.
  • In your AppPools – Make sure that you’ve set ‘Enable 32-bit applications’ to True.
  • Oracle – You still need to be install the Oracle 32-bit client, if of course your website is connecting to oracle databases using Microsoft ODBC for Oracle.
  • WebDeploy – Use WebDeploy from Visual Studio to the server to deploy your code, much easier than using a FTP server also saves having to deploy to each individual server, you can write a PowerShell script which will deploy to all your servers in one go.

Install the ASP roles and features:

    1. On the taskbar, click Server Manager.
    2. In Server Manager, click the Manage menu, and then click Add Roles and Features.
    3. In the Add Roles and Features wizard, click Next. Select the installation type and click Next. Select the destination server and click Next.
    4. On the Server Roles page, expand Web Server (IIS), expand Web Server, and then expand Application Development.Server role
    5. On the Server Roles page, select ASP.
    6. If the Add features that are required by ASP? dialog box appears, click Add Features. (This page appears only if you have not already installed ISAPI Extensions on your server.)Windows features
    7. On the Server Roles page, ASP and ISAPI Extensions should be selected. Click Next.Server role
    8. On the Features page, click Next.
    9. On the Confirmation page, click Install.
    10. On the Results page, click Close.

How to show your debug messages on screen… I’ll come back to this in a few days, it late at night and I’m too tired to continue explaining.

The above should get you started. Good Luck!

Right, I’m back to finish off the post.

Within IIS click the server name in the left hand tree, double click ASP within the IIS panel, open up the ‘Debugging Properties‘ and change ‘Send Errors To Browser‘ to True. You can do this as described above for the whole site and all it’s web applications or a application basis. To do this, select the application name on the left before double clicking on ASP.

ASP-IIS-Debug

You might also need to switch on Detailed errors for a particular error page. Let say your page is reporting 500 not found and you know that the page is there, a index.html file in the root displays correctly (a good test of sanity). To turn these on, Double click on Error Pages within IIS panel on the site or the application as above, then select the error code on the left and click ‘Edit Feature Settings…‘ on the right.

DetailedErrors

This then shows the following dialog box, where you click ‘Detailed errors‘.

DetailedErrors2

This process creates or appends a web.config file in the root of your site or application which contains the following:

&lt;?xml version="1.0" encoding="UTF-8"&gt;
&lt;configuration&gt;
    &lt;system.webServer&gt;
        &lt;httpErrors errorMode="Detailed"&gt;
    &lt;/system.webServer&gt;
&lt;/configuration&gt;

Microsoft OLE DB Provider for ODBC Drivers error ‘80004005’

If you’re getting this in a Classic ASP application and you’ve done all the above steps, then your Global.asa file has the wrong connection, maybe your oracle client doesnt have it in its tnsnames.ora file

Microsoft OLE DB Provider for ODBC Drivers error '80004005'

[Microsoft][ODBC driver for Oracle][Oracle]ORA-12154: TNS:could not resolve the connect identifier specified

/blah/blah.asp, line 26

 

Mailto subject / body in Android email client broken?

The following section of mailto: code wasn’t working on the default Android email client and Gmail client.

<div class="panel-body">
Please contact the <a href="mailto:it.helpline@random.com?Subject=No%20Tiles%20within%20Application&amp;Body=Please%20could%20you%20check%20my%20account%20@(Model.LoggedInUser.Id)%0D%0A%0D%0AMany%20Thanks" target="_top">IT Helpline</a></div>

The reason is down to a simple issue ?Subject and &Body both started with capital letters, replace these to be lowercase ?subject and &body and the following code works across all clients on all platforms.

<div class="panel-body">
Please contact the <a href="mailto:it.helpline@random.com?subject=No%20Tiles%20within%20Application&amp;body=Please%20could%20you%20check%20my%20account%20@(Model.LoggedInUser.Id)%0D%0A%0D%0AMany%20Thanks" target="_top">IT Helpline</a></div>

I’ve tested on :

Android : Default mail, Gmail, Nine

iOS : Safari, Gmail

Windows : Outlook, Gmail