Installing Drupal 8 on Windows and SQL Server

Installing Drupal 8 on Windows and SQL Server

Difficulty: 
Piece of Cake

This post explains how to install Drupal 8 on Internet Information Services (IIS) and MS SQL Server using PHP7 with advanced performance settings. It is aimed at understading the different pieces that compose the environment needed to run Drupal on Windows and intended to audiences that have at least an intermediate level of confidence with Windows, IIS and SQL Server.

It is based on the original (and now outdated) Installind Drupal on Windows and SQL Server post, and has been updated for Drupal 8, PHP7 and other changes in Drupal.

Frequently Asked Questions

Can I run Drupal 8 on Windows with Apache?

  • You can, but this is not production ready. This setup is usually recommened for users developing on Windows but that are going to deploy their applications on Linux machines running Apache (or nginx).
  • The only production ready thing on Windows is IIS (Internet Information Services) - that comes free bundled with any version of Windows, even personal and home editions.

Can I run Drupal 8 on Azure?

  • Azure has multiple flavours of their service. You can perfectly run Drupal 8 on azure on both Windows or Linux based backends, as well as MySQL or MS SQL Server as a storage backend. Currently you can perfectly run Drupal 8 on Azure PaaS offering "Azure Apps" using Azure SQL as a storage backend.

Is deploying/developing on Windows + SQL Server more expensive?

  • Cloud virtual windows machines are about 15% more expensive, but you can easily save that money in operation costs. The best Windows VPS in terms of price per performance is Vultr or Azure. Other providers such as AWS consider supporting Windows not a key part of their business model and thus penalize the use of Windows based software with an over price.
  • SQL Server has a free edition that is full featured but has a 10GB per database limit. You won't even get close to this limit on regular websites. And you get a business ready database engine that is much more powerful, fast and scalable than any other thing on the market.
  • Visual studio is now free.
  • Visual studio has excelent PHP development plugins such as PHP Tools For Visual Studio
  • Visual studio has excelent Web Development extensions such as Web Essentials.

What is the WAMP stack?

  • Something you want to avoid because the only production ready web server on windows is IIS. If you want to use apache (or niginx) I recommend moving to Linux. WAMP is very common between hobbyists because it is usually deployed with one click installer packages.

Drupal is coded in PHP, what is that?

PHP is a server-side scripting language designed for web development but also used as a general-purpose programming language. 

PHP code is usually processed by a PHP interpreter, which is usually implemented as a web server's native module or a Common Gateway Interface (CGI) executable.

Ther official PHP site to get Windows builds is windows.php.net. You can check out new releases and detailed progress in the official changelog for PHP7.

PHP has historically had very bad fame as an inconsistent, broken and unafe programming language. But with the advent of PHP7, everything changed converting PHP7 in a platform ready to support business projects.

The IDE: Visual Studio + PHP Tools

Before you start working on Drupal you will need an IDE. The IDE is the tool that makes working with PHP productive. Autocomplete, quality assurance, sintax highliting, etc...

The best tool to work with PHP on Windows is Visual Studio with the PHP Tools Add-On. You can get Visual Studio for free with the Visual Studio Community Edition. After installing Visual Studio make sure that you install the plugins required for a productive Web Development experience:

You can download a copy of PHP Tools from Devsense

 

How PHP works on Windows (and how to install it)

Important: Stay away from the PHP platform installer.

If you intend to run PHP on Windows take the time to deploy it manually step by step and understand how everything works.

For the scope of this article, you need to know that PHP scripts are interpreted, and that on windows this interpretation is performed by an executable application that you can download from here.

In PHP7 you should stick to x64 Non Thread Safe.

Download the binaries and drop them anywhere in your system (ex. D:\PHP\).

This is the folder where we will stare what is called the PHP runtime.

The binaries folder has all the required DLL's for PHP to work. PHP7 is compiled for Windows using VC14 so you might need to also install Visual C++ Redistributable for Visual Studio 2015.

The behaviour of the PHP runtime settings are managed through the php.ini file. The downloaded package has a demo "php.ini - development", just rename it to "php.ini" so that the PHP runtime can boot.

You are now ready to run PHP scripts! 

Drop these lines in a d:\hello.php file:

<?php
  print phpinfo();
?>

And run your first script with:

d:\PHP\php.exe d:\hello.php

This is not exactly how web page serving works, but is helpful in clarfying the underlying communication setup between IIS and PHP. The function phpinfo returns an HTML formated string that contains information about the current PHP environment: version, settings, what extensions are loaded and their settings, etc. This is not very helpful shown through the console, but will make more sense when we access that script from a web server.

Serving PHP scripts from IIS

Internet Information Services is a Windows feature that will turn any Windows OS into a Web Server. This feature comes turned off by default, and there are plenty of guides on the internet on how to install and enable IIS:

Start by setting up a new empty website in IIS on port 8080 that points to 

d:\inetpub\wwwroot\mydrupal\ 

this is where our web files will be sitting.

Drop in it the hello.php script we made before.

To make your life easier, there is an IIS complement you can install that provides a visual interface to configure basic PHP settings in IIS wen applications, the PHP Manager for IIS. This manager allows for easy registration of the PHP handler, along with other basic PHP settings.

As of the 4th January 2016 the PHP Manager for IIS installer provided officialy by MS does not install on Windows 10. You will find a working installer in this post.

Use this link for IIS 10 and this one for IIS 8.5.

Once installed you will see the PHP Manager icon in the IIS configuration pane for all your sites.

Connecting IIS and PHP is a piece of cake, just open the PHP Manager in the UI and navigate to the php-cgi.exe executable:

Well...it's not actually that easy, having a good PHP deployment that you understand and ready for production requires an article in itself, but for now this will suffice. This article from Microsoft has more in-depth details about how to setup IIS and PHP.

Note that for this to work you must have the FastCgiModule installed in IIS. This is an optional component when you install windows (Add or Remove Features), and it is actually called CGI in the installation UI.

You are now ready to serve your first PHP script, just browse to http://localhost:8080/hello.php, and you should bee seing something like this:

Preparing IIS for clean URL's

Drupal works in such a way that all (well, nearly all) requests are forwarded to the index.php script, and Drupal uses a query string parameter to retrieve the information about what the user is really trying to access.

By default, Drupal uses and generates URLs for your site's pages that look like "http://www.example.com/?q=node/83". With so-called clean URLs this would be displayed without the "?q=" as "http://www.example.com/node/83".

The style of URLs using "?q=" can be hard to read, and may even prevent some search engines from indexing all the pages of your site. In Drupal 7 you can turn clean URL's on and off, but in Drupal 8 clean URL's are enabled by default and cannot be turned off.

The magic behind clean URL's is Microsoft's URL Rewrite Module in IIS. This modules allows the user to define a set of application level URL rewriting rules, so that you can have custom transformations to URL request before they reach your application. The IIS module can be downloaded from here. The download links can be found at the end of the page:

Once installed, rewriting rules are setup in your web.config or through a friendly UI in IIS. In any case, you don't have to bother any futher because the web.config that comes with Drupal Core has already the rewriting rules that Drupal uses in it.

You can read more about the url rewrite module here.

Enabling Wincache and SQL Server PDO extensions

We mentioned before that PHP can be extended by the means of compiled extensions. These extensions are configured through the PHP.ini file.

For a basic setup you will at least need:

The Wincache Extension: This is a Microsoft developed extension that provides platform specific performance boosts. You can download it here. For PHP 7 you need to use version 2.0.0.0 or above.

The SQL Server PDO Extension: Drupal connects to databases by means of PHP PDO drivers. PDO is an acronym for PHP Data Objects. PDO is a lean, consistent way to access databases. This means developers can write portable code much easier. PDO is not an abstraction layer like PearDB. PDO is a more like a data access layer which uses a unified API (Application Programming Interface). Please always use the latest version of the Microsoft PDO driver that matches your environment, you can download the releases from here.

Extensions need to match you current PHP deployment, that is: 

  • PHP Version
  • Thread Safe or Non Thread Safe
  • x86 or x64

First we tell PHP where to look for the Extensions:

# ext folder relative to the php.exe binary
extension_dir = ext

Drop both the Wincache and the SQL Server PDO dll's inside the extension folder (c:\PHP\ext\ if you followed this tutorial) and enable them by adding the following two lines to your PHP.ini:

extension=php_wincache.dll
extension=php_sqlsrv_pdo.dll

If you get lost just follow these instructions on how to enable a PHP extension.

In php.ini, use these standard setting for the Wincache extension:

wincache.enablecli=on
wincache.fcachesize=254
wincache.fcenabled=on
wincache.filecount=8000
wincache.maxfilesize=2048
wincache.reroute_enabled=on
wincache.ttlmax=4000
wincache.ucachesize=128
wincache.ucenabled=on

Important: After making any changes to PHP.ini, if you don't see these changes reflected in PHP, make sure to restart the application pool in IIS. This is not always required.

Another important change to do in php.ini is to enable the Opcode cache and to adjust the realpath_cache:

zend_extension=php_opcache.dll

opcache.enable=on
opcache.enable_cli=on
opcache.max_accelerated_files=12000
opcache.memory_consumption=256

realpath_cache_size=5M
realpath_cache_ttl=1800

You can find most PHP extensions already compiled in the PECL repository

http://windows.php.net/downloads/pecl/releases/

Understanding permissions and authentication

There are several intricate security related settings that you can deal with in PHP.

The open_basedir directive should be left empty (as it is by default). This directive is supposed to limit to the specified path any file system operations done by the PHP process. The problem is that this is difficult to setup and maintain (you can have your temporary, web, and other folders spread through several places), but most important, it has a negative performance impact because it invalidates the realpath cache. You can read more about it here.

#open_basedir=

You can still keep your setup secure and isolated by simply using permission based configurations as we will see now.

Most IIS Drupal tutorials (even the old ones from MS itself) will ask you to these settings:

cgi.fix_pathinfo = 1
fastcgi.impersonate = 1

cgi.fix_pathinfo is straightforward and correct, as it does fixes some specific IIS out-of-the-specification path handling.

But using fastcgi.impersonate=1 is not a good deal at all. If you use the default setting (fastcgi.impersonate) will run using the IIS process identity configured in the application pool, and that is what we are used to having in .Net applications:

When you use fastcgi.impersonate=1 instead of running as the identity defined in the Application Pool, the php process will use the WINDOWS account (yes this has to do with windows based authentication) and will default to IUSR which is a legacy setup that I do not recommend at all.

There related articles will help you better understand this:

This also has an impact on the Load User Profile setting for the application pool:

Sometimes (for example when using COM/.Net assemblies, INTEROP or others) you will need to set Load User Profile to true. What this does is load the complete windows account profile when the php process starts. So the user will get - for example - it's own temporary files folder in c:\users\myapplicationpool\temp instead of using the global c:\windows\temp. Now imagine you set Load User Profile to true, and fastcgi.impersonate=1. You might have the IUSR accountr trying to access the temporary folder in c:\users\myapplicationpool\temp for which it holds no read or write access rights.

My recommended setup is to:

  • Set Load User Profile to true in the application pool
  • Use fastcgi.impersonate=0

You can also use fastcgi.impersonate=1, but then just make sure that the anonymous IIS account uses the application pool identity:

Making SSL Work

In order for Drupal to request external data from SSL services (such as Drupal updates or translations) you need to setup the certificate store that PHP uses. You can see more details about this here.

You need to download the latest certificate file from this link http://curl.haxx.se/ca/cacert.pem and store it somewhere in your system, for example in c:\php\cacert.pem. Then in you php.ini:

curl.cainfo = "[pathtothisfile]\cacert.pem"

Preparing the Database and Installing the SQL Client

I will asume that you already have the knowledge and tools to setup and administer a SQL Server Database. Create a new database named 'mydrupal', and make sure that he database is created using a unicode case-insensitive accent-insensitive collation (for example the default SQL_Latin1_General_CP1_CI_AI).

You can also use Drupal with an Azure SQL database.

You can also find many online tutorials that will guide you through installing an SQL Server engine:

To prevent any future headaches, make sure that you test your connection to the Database (username, password, name, port, etc.) using SQL Server Management Studio from the same box that is hosting the Website, and that the user you will be using to connect to the database has privileges to create/alter/delete database objects such as tables and indexes.

You must also install in the box that will be connecting to the database (the one hosting your webserver) the SQL Server Native Client. 

Microsoft has been very bad at making finding the installer for this component easy as it used to be a stand alone element, but is now part of the SQL Server Feature pack. This pack has many files, but the one you are looking for is SPA\x86\sqlncli.msi. (there is also a x64 version of it in the package).

See detailed instructions on how to obtain this component here.

The SNA (Sql Server Native Client) is being deprecated in favour of the Microsoft® ODBC Driver 11 for SQL Server. You should find the latest version of the ODBC driver and install it. The ODBC driver is also used when connecting from Linux.

As of this writing the latest ODBC driver version in 13.1, and you can download it from here.

Composer and GIT for Windows

In order to install and maintain Drupal we are going to need some special tooling.

Composer is a dependency manager for PHP. Composer will manage the dependencies you require on a project by project basis. This means that Composer will pull in all the required libraries, dependencies and manage them all in one place.

To install composer on Windows you need to download and run the Composer-Setup.exe file from the composer website.

Once composer is installed you will be able to call composer commands from your command prompt. For example, to update composer to the latest version run composer self-update:

Other tools that are not necessarily used in this tutorial, but very helpful (and mandatory if you are going to do something serious):

Installing Drupal

Drupal 8 is not just something that you "unzip" into a folder and it's ready to go (like it used to be with Drupal 7). Drupal 8 needs to go through a "build" process. This makes maintenance, upgrades and dependency management much more convenient and reliable.

We recommend to stay away from pre bundled Drupal packages such as Acquia Drupal, or Acquia dev desktop. You don't know/learn and have no control of what happens behind the scenes with those setups. 

To speed up composer dependency loading, install the prestissimo package globally:

composer global require "hirak/prestissimo:^0.3"

The installation and maintenance workflow proposed here is just one of many possible workflows, and is based on drupal-project.Open a command prompt, browse to your data disc and install a composer based Drupal 8 project:

cd /d d:\
composer create-project drupal-composer/drupal-project:8.x-dev

This will pull the latest development version of Drupal 8 into the folder:

d:\drupal-project\

We now need to point our IIS site to the webroot in D:\drupal-project\web:

 

 

After doing so you will be able to browse your local site at http://localhost:8080/ and see the Drupal installer:

We are also now going to setup the temporary directory settings, otherwise Drupal will fail to properly run. You can change this later, but as default, Drupal will try to store temporary files in "sites/default/files/tmp" so we need to make sure we have a valid directory:

mkdir d:\drupal-project\web\sites\default\files\tmp

In order to install on MS SQL Server we need to pull in the Drupal Sql Server module from Drupal.org. Although we could do that manually, it's easier using composer (and that is why we are using composer all along).

Before being able to install drupal contrib projects from Drupal.org you need to tell composer where to look for them using this command:

composer config repositories.drupal composer https://packages.drupal.org/8

Then open a command prompt and run the following commands:

cd /d d:\drupal-project\
composer require drupal/sqlsrv:~2.0

Unfortunately, database drivers have a special category in Drupal and you need some extra step to get the driver detected by Drupal, you need to copy the "drivers" folder that is inside the module to the root of the website:

xcopy /S /I /E %cd%\web\modules\contrib\sqlsrv\drivers %cd%\web\drivers

You can automate this task as part of your build process by modifying your composer.json file and make the post-update-cmd entry look like this one:

        "post-update-cmd": [
            "DrupalProject\\composer\\ScriptHandler::createRequiredFiles",
			"xcopy /S /I /E /Y web\\modules\\contrib\\sqlsrv\\drivers web\\drivers"
        ]

Remember that, whenever you want to update the driver, it is what is in /web/drivers what matters, not the code in /web/modules/contrib/sqlsrv. With the post-update-cmd command we have just added, the latest code will be pulled from the repository and then updated into the right location everytime you run a composer update command.

If you are going to store your project on a git repository, make sure that you do not commit in your vendor directory neither the copied drivers folder, by adding this to your .gitignore file:

# Do not commit database drivers
/web/drivers/lib/Drupal/Driver/Database/sqlsrv

If you now browse to the Drupal install and try to go forward with the installation, you will see the SQL Server option:

If you put your database details and credentials, and try to install you will get the following error:

Failed to connect to your database server. The server reports the following message: The PhpMssql library is not available.

This is because the 8.x-2.x branch of the Drupal SQL Server module needs the PhpMssql component. There is also a community maintained 8.x-1.x branch that you can use and has no external dependencies (AKA free), simply go back a few steps and use 1.0 instead of 2.0 in the composer require command.

The 8.x-2.x is widely tested, actively supported, Linux compatible and with much more better performance and reliability.

You can bring in the PhpMssql library using a fully integrated composer build process, just run the following commands:

# Replace username and password with your gitlab credentials
composer config repositories.1 git https://username:password@gitlab.com/david-garcia-garcia/mssql.git
composer require david/mssql

You can also deploy it manually by following the next steps.

Once you have bought the PhpMssql library login to your gitlab account and look for the mssql project:

Then download the project source:

Then unzip the contents of the file into the following directory:

D:\drupal-project\web\drivers\lib\Drupal\Driver\Database\sqlsrv\mssql

You should see a folder structure such as this:

After this you should be able to go through the Drupal install process (aprox. 30 seconds duration) and access your new Drupal site! (note that using the 8.x-1.x branch of the driver makes the install process take a very long time, be patient as it should be finally able to complete itself):

After install you might be greeted with an unpleasant css-less page:

Don't worry, this is due to a special condition where the Drupal installer is unable to automatically create the temporary files directory. Make sure that you have a "tmp" file inside "web/sites/default/files":

mkdir %cd%\web\sites\default\files\tmp

Navigate to the performance page "http://localhost:8080/admin/config/development/performance" and push the "Clear al caches button".

You can also completely install the Drupal site in a completely unnatended manner using the Drupal Console.

The Drupal Console is already installed as a dependency in our project thanks to the composer-drupal project. The first thing we need to do is create a shortcut for the console command, use the following to do so:

@echo @php "%cd%\vendor\drupal\console\bin\drupal" %* > %cd%/web/drupal.bat

We can now test that the Drupal console works by browsing to the web directory and issuing the Drupal about command:

The Drupal console is a very useful tool to work with your Drupal installation, and to integrate with your Continuous Integration practices.

To install your site with a few commands use the following:

drupal site:install standard --langcode="en" --db-type="sqlsrv" --db-host="127.0.0.1" --db-name="mydrupalsite" --db-user="sa" --db-pass="mypassword" --db-port="1433" --site-name="www.DrupalonWindows.com" --site-mail="admin@example.com" --account-name="admin" --account-mail="admin@example.com" --account-pass="admin" --no-interaction

IMPORTANT: A good practice is NOT to keep your site's files directory, but mount this as a virtual directory. To do so keep reading...

We are going to step back a little, and before installing Drupal setup and properly configure file storage. Your Drupal code should be something volatile - an artifact. But your drupal content (i.e. files uploaded by users) should have a persitent storage. Just like the database does.

Drupal works with 3 directories:

  • Files: defaults to (sites/default/files), used by the "public://" stream.
  • Private: not configured by default. Used by the "private://" stream, must be configured manually and not exposed to the internet (files to be served through Drupal itself).
  • Temp: default to (c:\windows\temp), used by the "temporary://" stream. 

[TODO: Revise directory setup.]

Once the destination directories are ready, issue the following commands to tell Drupal where these directories are:

set "storage=d:\drupal-project-storage"

mkdir %storage%\sites\default\files
mkdir %storage%\sites\default\private
mkdir %storage%\tmp\sites\default\private

# Link the public directory to the web structure
mklink /j "%storage%\sites\default\files" "d:\drupal-project\web\sites\default\files"

drupal config:override system.file path.temporary %storage%\tmp\sites\default\private
drupal config:override system.file path.private %storage%/private
drupal config:override system.file path.public %cd%/sites/default/files

MS SQL Server custom function

In order to minimize the friction between MySQL specific code (usually found in contributed modules) and MS SQL Server the SQL Server driver for Drupal deploys some functions that are MySQL specific (such as SUBSTRING, LPAD, MD5, etc.) and non ANSI compliant so that an implementation of them is available for the Drupal runtime.

Some of these functions are deployed using UDF (User Defined Functions) and are automatically deployed by the driver.

Advanced functions need to be implemented using CLR . This is the case of - for example - the GROUP_CONCAT implementation. Note that Azure has discontinued support for CLR on their cloud offerings.

You can find an implementation of GROUP_CONCAT for SQL Server here: https://groupconcat.codeplex.com/

Do not worry if you are missing any of these functions, they are not critical. But it might ring a bell in the future if any contributed module uses them, and you might need to fix the offending code (offending because it is non ANSI compliant).

Applying patches

Drupal is - after all - open source. That means that you might need to apply patches to the current stable code base to fix bugs that are affecting you, or to deploy custom changes to the code itself.

The composer build Drupal project we have been arranging has the tools to automatically have remote patches applied as part of the build process. You can add patches for core, or even for specific modules or vendor components.

Simply add the URL to the patch and the module it belongs to in your composer.json extras.patches entry:

"extra": {
        "patches": {
            "drupal/address": {
                "Drupal Addess fix default syncing": "https://www.drupal.org/files/issues/address_syncing.patch"     
            },
		    "drupal/drupal": { 
		      "Make PHPUnit work in Simpletest on Windows" : "https://www.drupal.org/files/issues/2294731-39-phpunit-windows.patch",
			  "Make test script properly grab the PHP runtime on Windows" : "https://www.drupal.org/files/issues/use_the_php_binary-2748883-15.patch",
			  "Make simpletest work with contributed database drivers": "https://www.drupal.org/files/issues/simpletest_is_broken_on-2605284-42.patch"
		    }
        }
    }

In this example the patch in "https://www.drupal.org/files/issues/address_syncing.patch" will be automatically applied as part of the build process. If you need to modify or customize any 3d party code (modules, core, etc..) you have two options:

  • For small code modifications, deploy them as patches that are applied as part of the build process
  • For heavy modifications, fork the remote reposiitory with your own version, and use that instead of the original module

The above example will also bring in some patches for Drupal core itself.

High performance Drupal: Wincache

Although we already have the Wincache PHP extension configured and running, it takes the help of the Drupal Wincache module to make the most out of Wincache (the really important performance improvements come from enabling this module).

Open a command prompt in your project's root and run the following:

composer require drupal/wincachedrupal:~1.0

This will pull in the Wincache module with any other module dependencies it has.

Go to /admin/modules and install the Wincache module:

There is one extra setting that needs to be manually configured in sites/default/settings.php to make the FileCache component in Drupal run on top of Wincache:

$settings['file_cache']['default'] = [
    'class' => '\Drupal\Component\FileCache\FileCache',
    'cache_backend_class' => \Drupal\wincachedrupal\Cache\WincacheFileCacheBackend::class,
    'cache_backend_configuration' => [],
 ];

High performance Drupal: Couchbase

For big websites with high traffic it is recommended not to store cache items in the database, but to do so in an alternate backend such as Couchbase.

http://www.drupalonwindows.com/en/blog/drupal-8-couchbase-integration

(needs update and clarification)

High performance Drupal: Tideways

To keep your site fast you need a tool that will tell you exactly what is slow so that you can do something about it. For Windows users that will be Tideways:

http://www.drupalonwindows.com/en/blog/profiling-drupal-xhprof-uprofiler-tideways-php7-linux-and-windows

(needs update and clarification)

NetPhp

After installing the Wincache Module you will see the following messages in the status page:

The Wincache modules has some performance optimizations that rely on the availability of the NetPhp library. Besides these out-of-the-box optimizations, deploying the NetPhp allows you to call .Net libraries (.dll files) from within PHP or even code from the .Net framework itself.

To install NetPhp download the netuilities.dll binary into your php runtime folder:

c:\php\netutilities.dll

Then register it with the following command:

"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe" "c:\php\netutilities.dll" /codebase

In your php.ini enable the com_dotnet extension:

extension=php_com_dotnet.dll

Then download the Ajaxmin.dll binary from the either the installer, nuget or build it yourself and drop it into:

d:\drupal-project\web\libraries\_bin\AjaxMin\AjaxMin.dll
d:\drupal-project\web\libraries\_bin\AjaxMin\AjaxMinTask.dll

After this, rebuild the registry by navigating to /core/rebuild.php. Yor status page should now look something like this:

With this you have achieved 2 things:

  • Drupal is using a faster and better (more compression) asset minification and aggregation algorithm provided by AjaxMin.
  • You now can use the 'netphp' service to consume any .Net binaries

Calling .Net code from PHP

See our Calling .Net from PHP article to:

  • Use any .Net binaries (even without COM Visibility) and for any version of the .Net framework.
  • Iterate over .Net collections directly from PHP
  • Automatic propagation of .Net errors into native PHP exceptions that can be properly handled
  • Acces native enums and static methods
  • Use class constructors with parameters
  • Debug PHP and .Net code at the same time as if it was a single application.
  • Specify the location of you binaries, so there is no need to register anything in the GAC and you can have version control along with your application.

By installing the Wincache module (see previous sections) you get an already available NetPhp runtime to write .Net integrations out of the box. The following code will, for example, take a powerpoint file (ppt or pptx) and convert it to a set of images using the Aspose.slides .Net component:

    /** @var \Drupal\wincachedrupal\NetPhp */
    $netphp = \Drupal::service('netphp');

    \Drupal\envivo\Util\UtilsAspose::RegisterAsposeInPhpRuntime($netphp);

    $runtime = $netphp->getRuntime();
    $runtime->RegisterAssemblyFromFullQualifiedName("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", "System.Drawing");

    $destination = strtr(PresentacionSlide::UPLOAD_LOCATION, ['[envivo_presentacion:id]' => $this->entity->id()]);
    file_prepare_directory($destination, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);

    $sourcefile = drupal_realpath($file['tmppath']);

    $presentation = $runtime->TypeFromName("Aspose.Slides.Presentation")->Instantiate($sourcefile);
    $format = $runtime->TypeFromName("System.Drawing.Imaging.ImageFormat")->Png;

    $x = 0;

    /** @var \NetPhp\Core\NetProxyCollection */
    $slides = $presentation->Slides->AsIterator();

    foreach ($slides as $slide) {
      $x++;
      $bitmap = $slide->GetThumbnail(1, 1);
      $destinationfile = $destination . "/slide_{$x}.png";
      $bitmap->Save(drupal_realpath($destinationfile), $format);
      $slide = PresentacionSlide::fromFile($destinationfile);
      $files[$slide->uuid] = $slide;
    }

    $presentation->Dispose();

A piece of code writen in C# like this:

string javascript = "";
Microsoft.Ajax.Utilities.Minifier m = new Microsoft.Ajax.Utilities.Minifier();
Microsoft.Ajax.Utilities.CodeSettings settings = new Microsoft.Ajax.Utilities.CodeSettings();
settings.OutputMode = Microsoft.Ajax.Utilities.OutputMode.SingleLine;
settings.PreserveFunctionNames = false;
string minified = m.MinifyJavaScript(javascript, settings);

Will look like this on PHP:

$minifier = netMinifier::Minifier_Constructor();
$settings = netCodeSettings::CodeSettings_Constructor();
$csssettings = \ms\Microsoft\Ajax\Utilities\netCssSettings::CssSettings_Constructor();
$settings->OutputMode(\ms\Microsoft\Ajax\Utilities\netOutputMode::SingleLine());
$settings->PreserveFunctionNames(FALSE);
$settings->QuoteObjectLiteralProperties(TRUE);
$result = $minifier->MinifyStyleSheet($css, $csssettings, $settings)->Val();

What to do next

If you properly followed these instructions, you should have a smooth and fast Drupal website and have a basic understanding of how the different components needed to run Drupal on Windows interact, but as your site gets bigger and more complex, you will need more advanced configuration.

Comments

I have fond error "Failed to connect to your database server. The server reports the following message: The PhpMssql library is not available.." while sqldb connecting. I have followed steps as you mentioned. Please do the needful.
and gitlab file also not available.

To get a copy of the PhpMSSQL library use the link in the main navigation menu of this site, or here:

http://www.drupalonwindows.com/en/content/phpmssql

If you want to go 100% free there is a "community supported" (AKA use it at your own risk) branch of the driver (8.x-1.x) that we had been working on before moving to 8.x-2.x. The 8.x-2.x is a full refactor that solves deep core issues of the original driver. Migrations from 8.x-1.x to 8.x-2.x have not been tested and are not supported, so if you start building something on 8.x-1.x make sure to set aside some budget to put off some tough fires. If you are using drupal for brochureware the free version might do the job.

After the installation of AjaxMInifier I still see the warning in the Status Report that :

AjaxMin asset optimizations not available.
NetPhp runtime missing.

In your video, this has been that way either.

What am I missing?

Thank you

When I get to the "Database Configuration" Stage; I enter my SQL Server details, but always get the following message:
I'm sure I'm entering the correct details, and have tried numerous things for the last couple of days to try and get this working, but it just doesn't like something. Its seems odd. If I try different versions of the PDO drivers, it won't even get to this step!

Any help would be really appreciated!

Resolve all issues below to continue the installation. For help configuring your database server, see the installation handbook, or contact your hosting provider.
• Failed to connect to your database server. The server reports the following message: The PhpMssql library is not available..•Is the database server running?
• Does the database exist, and have you entered the correct database name?
• Have you entered the correct username and password?
• Have you entered the correct database hostname?

Kind Regards

The PhpMssql library is not available.

The error is self-explanatory. Please read through the comments.

You can either use the supported PhpMSSQL library or use the old unmaintained 8.x-1.x branch that has no dependencies.

Greetings and good luck.

Thanks for the reply. Perhaps I'm getting the SQL Server DLL and the GitHub download you picked up mixed up.
I can't see the 8.x-1.x branch of the PhpMSSQL driver anywhere. I don't really want to purchase the component at this stage, until I'm sure we are moving ahead with this platform. Can you tell where I can get this?
Kind Regards
Alister

The download is on the project page itself: https://www.drupal.org/project/sqlsrv

Look for the 8.x-1.0-rc1 download. Be warned that this is an "experimental" driver that was only tested on very early development stage. Yet, it quite works for the basic things. If you plan on doing low traffic brochureware it might serve you well.

Greetings,

David

Hello David

It appears that the netphp-user-guide has been revised from the version of the guide that you show in your video and the download link for the binary is no longer available. Can you please provide the correct download link for the netutilities.dll?
Thank you.

Hello David

After successfully registering the netutilities.dll on Windows 2012 R2, there are only three libraries listed in the OLE/COM object viewer:
netutilities.MagicWrapper
netutilities.NetPhpRuntime
netutilities.TypeGenerator.TypeDumper
Also, when I try to open the branch for (NetPhpRuntime, TypeGenerator.TypeDumper), I receive an error display box "IClassFactory::Create Instance Failed". Any thoughts on what the issue is here?

The NetPhp library can be downloaded from: http://www.drupalonwindows.com/en/content/netphp

The error you are seeing is only affecting the evaluation version and has been fixed in release 2.0.0.6.

To upgrade the library completely unregister the old binary before registering the new one. Greetings,

Hi David

I'm experiencing an issue with the netutilities.dll, it appears to be registered successfully on Windows 2012R2 x64 (.NET FW 4.5.2). However, when I try to open the branch for the netutilities.NetPhpRuntime from the OLE/COM Object Viewer, I'm receiving the following error: IClassFactory::CreateInstance failed, <No system message defined>, <Unknown Facility> (80131500). I tried registering the following versions of netutilities (2.0.0.4, 2.0.0.5, 2.0.0.6), but received the same error for each. What do you think the problem is?

The evaluation version is designed to stop working the first monday of every month. What was fixed in 2.0.0.6 is that the error message shoud be friendly, instead of receiving the weird error you are seeing. And I also fixed the fact that the crash should not be showing through OleView, only when using the library to do stuff.

If you still see this error, that means that the system is still trying to load the old binary. You should ALWAYS unregister the old binaries before registering the new ones, otherwise you will run into the commonly known as "registry hell".

A quick workaround for this is to change your system date and time to a day different than today, so that the evaluation protection does not trigger. You will then be able to use OleView and see what libraries and versions you have effectively registered. Sorry for this annoying behaviour, a few users complained today already and this has been fixed in 2.0.0.6.

Hi David

I really appreciate your quick reply. That did the trick. I'm now using the 2.0.0.6 version and everything is working fine. Thank you for your help.

Robert

Hi David

I'm having an issue with the Drupal 8.0.5 install. The following error is displayed during the database configuration:
The PhpMssql library is not available..
I confirmed this is definitely a Drupal install issue.
I was able to successfully test the PHP PDO_SQLSRV driver for SQL Server and it's working.
Please refer to the following link:
https://msdn.microsoft.com/en-us/library/ff754357.aspx

Also, I believe I followed the installation and setup instructions correctly from your video.
Any help or suggestions would be greatly appreciated. Thanks for your help.

The PhpMssql library is not available.

Have you purchased, downloaded and deployed the PhpMssql library? The 8.x-2.x branch (that I maintain) of the Sql Server for Drupal depends on that component. If you want to evaluate the Drupal/SQL Server integration without buying any component you can use the 8.x-1.x branch of the driver, it has no dependencies whatsoever.

Hi David

I was able to complete the Drupal 8.0.5 install. However, I now receiving the error "The website encountered an unexpected error. Please try again later."
when I click on the following Report links:
Recent Log Messages
Status Report
Any ideas on what is causing this problem and how to troubleshoot? Thanks for your help.

Hi David

I was able to complete the Drupal 8.0.5 install. However, I'm now receiving the error "The website encountered an unexpected error. Please try again later." when I click on the Reports link "Status Report".
I see the following error "CouchbaseException: Expected bucket name as string in _CouchbaseBucket->__construct() (line 74 of [CouchbaseNative]/CouchbaseBucket.class.php) in the Recent Log Messages report.
Any ideas on what is causing this problem? Thanks for your help.

I rolled an update for the Couchbase module a couple of days ago, updating the module might do the work. To get started with Drupal 8 just don't enable the Couchbase module. The module is there just for scaling and performance purposes, and if you couchbase instance goes down or is not properly setup your whole site is down.

Hello David

I'm see the following warning in my status report:
Wincache AjaxMin asset optimization - AjaxMin assset optimizations not available.
NetPhp runtime missing.

I saw the previous comment. However, I did confirm that I installed and registered the NetPhp runtime successfully. I'm able to successfully open the branch for netutilities.NetPhpRuntime from the OLE/COM Object Viewer and display the CLSID info from the Registry tab. Are there any other configuration settings that I need to make? I'm using the 2.0.0.6 version. I appreciate your help. Thank you.

You need to copy the AjaxMin dll library to libraries/_bin/AjaxMin/AjaxMin.dll

There are several ways to get these binaries, the easiest is to run the installer form codeplex:

http://ajaxmin.codeplex.com/releases/view/611118

And then look for the binary files in:

C:\Program Files (x86)\Microsoft\Microsoft Ajax Minifier\net35

Make sure that - if you are using GIT to deploy - add .dll files as binary files to .gitattributes:

*.dll binary

 

Hi David

I really appreciate your quick reply. However, I did follow all the steps in your install video, but I still see the two warnings in the status report ("NetPhp runtime" missing for Wincache AjaxMin and "NetPhpRuntime class not found for WinCache NetPhp). Another point, there was no "libraries" directory under the drupal root for the version of drupal (8.0.5) that I installed. I had to create the following folder path myself: "C:\inetpub\wwwroot\drupal\libraries\_bin\AjaxMin". What do you think the problem is? I'm looking forward to your reply. Thank you for your help.

I completely forgot to cover composer manager in the Video.... I missed that. You are probably missing the NetPhp PHP classes:

https://packagist.org/packages/drupalonwindows/netphp

These should be pulled in automatically when you build Drupal 8.

Drupal 8 requires you to go through a build process in order to pull composer dependencies declared by contrib modules and core itself.

You can find instructions on that here:

https://www.drupal.org/node/2405811

Once you have set it up you can run custom composer commands such as "composer drupal-update" or "composer drupal-rebuild" to pull these dependencies. 

Hi David

I see the following warning in my status report: Composer Manager "Not initialized; Run the module's init.php script on the command line". Do you recommend initializing it, and if so, can you please provide an example of doing it from the command line in Windows? Thank you for your help.

Hi David

The composer drupal-update is failing with the following error:
C:\inetpub\wwwroot\drupal>composer drupal-update
> Drupal\composer_manager\Composer\Command::update
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Removing behat/mink (v1.7.0)
- Installing behat/mink (v1.7.1)
Loading from cache

> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
Script Drupal\Core\Composer\Composer::vendorTestCodeCleanup handling the post-pa
ckage-update event terminated with an exception

[RuntimeException]
The directory 'tests' in package 'behat/mink' does not exist.

What do think the issue is here or is there a way to skip this? Thanks for your help.

Hi David

Good news! I was able to initialize Composer and get all the dependencies updated successfully. Using composer drupal-rebuild followed by the update command did the trick. Now the status report shows that Wincache AjaxMin and WinCache NetPhp is up and running. Thanks for steering me in the right direction.

I would love to know what steps you took to do this. Do you have anything you can send me?

Hi,

I've manage to get drupal 8 to install however, I am having issues trying to enable wincache, more specifically enabling supercache which is a required dependency of wincachedrupal.

When the sqlsrv module (version 8.x-1.0-rc1) is manually enabled. I am get warnings regarding MSSQL Server Wincache integration and module in Status report. In order to enable the wincachedrupal module I have to first enable supercache and it is at this step that I am running in to issues.

As soon as I try to enable supercache I get the following error:

PDOException: SQLSTATE[HY010]: [Microsoft][ODBC Driver Manager] Function sequence error in C:\inetpub\wwwroot\drupal\drupal-8\core\modules\views\src\Plugin\views\display\DisplayPluginBase.php on line 192

Any subsequent page requests on the site will result with the error:

Uncaught PHP Exception PDOException: "SQLSTATE[HY010]: [Microsoft][ODBC Driver Manager] Function sequence error" at C:\inetpub\wwwroot\drupal\drupal-8\core\lib\Drupal\Core\Cache\DatabaseBackend.php line 95

Any idea what I may have done wrong?

Does the paid version of sqlsrv fix this issue?

Also, I'm a bit confused about whether it is necessary to enable the sqlsrv module in drupal 8. The site seem to work with or without it being specifically enabled. What is the difference?

PDOException: SQLSTATE[HY010]: [Microsoft][ODBC Driver Manager] Function sequence error in C:\inetpub\wwwroot\drupal\drupal-8\core\modules\views\src\Plugin\views\display\DisplayPluginBase.php on line 192

I have given a test drive - and updated because it was broken - the 8.x-1.x branch. I can confirm that this "function sequence error" does occur. I was unable to determine the causes because it did not seem to happen consistently. If you are able to reproduce the issue on a simple test script the guys from the PHP MSSQL driver will be happy to look into it:

https://github.com/Azure/msphpsql/issues

I can confirm that this problem is not happening in the "paid" version of the driver - we are using that on production sites -, but I as previously said I was unable to determine what the cause of the error is.

Looks like the issue starts happening when you enable the Wincache/Supercache module pair. It is probably triggering some weird situation that is uncovering a bug in the PHP PDO driver for SQL Server.

I am having trouble installing Drupal 8 on IIS7. I have installed the following:

* Windows 2008 Server R2
* Internet Information Server IIS 7.5
* SQL Server 2008
* Microsoft Drivers for PHP for SQL Server 3.2
* php-5.6.21-nts-Win32-VC11-x86
* php_pdo_sql_srv_56_nts.dll
* sqlsrv-8.x-1.x-dev
* wincachedrupal-7.x-1.10
* php_couchbase-2.1.0.5.6-zts-vc11-x64

I cannot get through the initial install, as I cannot connect to my MSSQL server, which is installed locally. I does not give me any error beyond the generic "Failed to connect to your database server."

Hi David,
I am constantly getting error from "php_wincache.dll". I downloaded from : http://windows.php.net/downloads/pecl/releases/wincache/1.3.6.1/

Error log gives following message:

[22-Jul-2016 21:03:03 UTC] PHP Warning: PHP Startup: Unable to load dynamic library 'C:\xampp\php\ext\php_wincache.dll' - %1 is not a valid Win32 application.
in Unknown on line 0

My system configuration :
PHP : 5.5.34
OS: Windows 7, 64-bits
IIS : version 7.5.x

Thank you.

I am constantly getting error from "php_wincache.dll". I downloaded from : http://windows.php.net/downloads/pecl/releases/wincache/1.3.6.1/

Error log gives following message:

[22-Jul-2016 21:03:03 UTC] PHP Warning: PHP Startup: Unable to load dynamic library 'C:\xampp\php\ext\php_wincache.dll' - %1 is not a valid Win32 application.
in Unknown on line 0

Apache on Windows with PHP is unsupported. The Wincache PHP extensions is designed for IIS support. 

Error MSSQL Server Custom Functions SUBSTRING:YES | SUBSTRING_INDEX:YES | GREATEST:YES | MD5:YES | LPAD:YES | GROUP_CONCAT:NO | IF:YES | CONNECTION_ID:YES | CLREnabled:YES
Some custom functions are not available. Make sure you deploy them.

Hi,

While i am connecting Azure sql error will come and root folder cached.

Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[HY010]: [Microsoft][ODBC Driver Manager] Function sequence error: MERGE INTO [cache_bootstrap] _target USING (SELECT T.* FROM (values(:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6)) as T([cid], [expire], [created], [tags], [checksum], [data], [serialized])) _source ON _target.[cid] = _source.[cid] WHEN MATCHED THEN UPDATE SET _target.[expire] = _source.[expire], _target.[created] = _source.[created], _target.[tags] = _source.[tags], _target.[checksum] = _source.[checksum], _target.[data] = _source.[data], _target.[serialized] = _source.[serialized] WHEN NOT MATCHED THEN INSERT ([cid], [expire], [created], [tags], [checksum], [data], [serialized]) VALUES (_source.[cid], _source.[expire], _source.[created], _source.[tags], _source.[checksum], _source.[data], _source.[serialized]) OUTPUT $action;; Array ( [:db_insert_placeholder_0] => Array ( [value] => hook_info [datatype] => 2 ) [:db_insert_placeholder_1] => Array ( [value] => -1 [datatype] => 2 ) [:db_insert_placeholder_2] => Array ( [value] => 1478954355.995 [datatype] => 2 ) [:db_insert_placeholder_3] => Array ( [value] => [datatype] => 2 ) [:db_insert_placeholder_4] => Array ( [value] => 0 [datatype] => 2 ) [:db_insert_placeholder_5] => Array ( [value] => Resource id #548 [datatype] => 3 ) [:db_insert_placeholder_6] => Array ( [value] => 1 [datatype] => 2 ) ) in Drupal\Core\Extension\ModuleHandler->getHookInfo() (line 296 of C:\inetpub\wwwroot\drupal\core\lib\Drupal\Core\Extension\ModuleHandler.php).

This error is due to a bug in the PDO driver itself: https://github.com/Microsoft/msphpsql/issues/167

The 8.x-2.x branch has workarounds for this issue in it, so you won't be seeing the error there. You can either wait for MS to push a fix to the PDO driver or upgrade to the 8.x-2.x version of the drupal driver.

Hi, everything works well for me except one thing. That is seeing MSSQL option in the installation. I have completed the step in which I pasted the "drivers" file within the drupal file. I still do not see the MSSQL as an installation option, is it because I do not have NetPhp library installed?

As a test to ensure that the Drupal files were set up proper I successfully installed and activated Drupal within My SQL. However, MSSQL is the only one that does not proceed in the installation process.

Thanks

Make sure that the drivers folder is in it's place, that the SQL Server PDO extension is showing up in your phpinfo() and that you have deployed the Mssql library. If all of those are in place and sql server still not shows as an install option, please get in touch using the contact form in this site. Greetings.

Thank you! I solved it. What happened was that in the php.ini file, the code was extension=php_sqlsrv_pdo.dll while the PDO file was php_pdo_sqlsrv.dll. So I changed the code in the php.ini file into the name of the PDO file (using same order): extension=php_pdo_sqlsrv.dll. Now the file targets the MSSQL allowing me to select MSSQL in the installation process. Thanks!

I know that you stated there are two ways to obtain NetPhp (purchase from DrupalWindows.com and the other can be a site that does not provide as much support). Is there another way I can obtain PhpMssql library? Or is purchasing it the only official way to do it? I just want to ensure that there is no file on Drupal.com that has a similar file.

Thank you!

You can't get PhPMssql from anywhere else other than this site. But you can use the 8.x-1.x branch of the driver which does not need PhpMssl and is 100% free.

Thank you very much for the explanation.

Where is the 8.x-1.x branch of the driver located at? Is it within the website https://www.drupal.org/project/sqlsrv (Drupal driver for SQL Server and SQL Azure)? If that is the site, I downloaded the 8.x-1.x-dev zip file, and pasted the src file within the mssql folder in Drupal. However the installation still states that a PhpMssql library is unavailable.

Thank you, Ricky

Please disregard last message, I just found out the process

Thanks. This is great.

When I try and install though I get the following error:

Drupal requires you to enable the PHP extensions in the following list (see the system requirements page for more information):
•gd

I have gd extension enabled: extension=php_gd2.dll in php.ini and php_gd2.dll is in ext directory.

I have checked that it is enabled and working. I am using PHP 7.1.

Any thoughts?

Hi David,

I found the community version and istalled 8.x-1.x but still facing the phpMssql library not available error. As mentioned below
sorry I am sending multiple issues
Please provide your help in resolving it.

Thank you,
Jyothsna.

Database configuration
Error message
Resolve all issues below to continue the installation. For help configuring your database server, see the installation handbook, or contact your hosting provider.
Failed to connect to your database server. The server reports the following message: The PhpMssql library is not available..
Is the database server running?
Does the database exist, and have you entered the correct database name?
Have you entered the correct username and password?
Have you entered the correct database hostname?
Database type
SQLServer
Database name

Database username

Leave username (and password) blank to use Windows authentication.
Database password

Show
Advanced options

I am getting an error on the database connection page of Drupal. I am using the sqlsrv 8.x-1.0-rc1 so I can demo this to a client to get approved to purchase the current version. The error message returned is blank. Is there a way to get the really error message? I can connect to the DB using SMSS using SQL Server Authentication.

Resolve all issues below to continue the installation. For help configuring your database server, see the installation handbook, or contact your hosting provider.
Failed to connect to your database server. The server reports the following message: .
Is the database server running?
Does the database exist, and have you entered the correct database name?
Have you entered the correct username and password?
Have you entered the correct database hostname?

Any help is greatly appreciated.

David,
First of all I wanted to say this is a great article, easy to follow, and well thought out. I am new to the Drupal world and I am trying to evaluate how Drupal stacks up against some of the other CMS systems our company has worked with in the past years. I have been able to get to the step in your tutorial where Drupal is ready to be configured. I currently have it setup to use require the 1.0 version of Drupal SQL Server module since we are just evaluating the feasibility of possibly transitioning to Drupal. I see the browser page in the Drupal configuration process where it is now asking me to enter the MS SQL information for the database I setup for my Drupal site. However, when I enter in this info, I keep getting the same screen with an the following message:

Failed to connect to your database server. The server reports the following message: .
Is the database server running?
Does the database exist, and have you entered the correct database name?
Have you entered the correct username and password?
Have you entered the correct database hostname?

I have triple checked all of this info and it is correct. I have also ran SQL Profiler, Fiddler, and checked the event logs to see if they could give me any indication what might be going on behind the scenes. There was nothing of any interest to be found. It is almost as if Drupal and PHP have no visibility to MS SQL. That it isn't even getting to MS SQL to actually try and authenticate and start creating the tables it needs. Any idea what I should be looking at to see how to get past this step?

Thanks in advance for any help.

Add new comment

By: root Thursday, January 14, 2016 - 15:42