Automating Configuration of Web Connection with Code
July 26, 2008 •
Every Web Connection application you build will need to be deployed at some point. Among the required tasks are copying files and then configuring the application to create virtuals, scriptmaps, set permissions and register your servers with COM. There are a lot of different approaches that you can take to configure your application, but Web Connection includes the tools to automate this process completely.
Copying Files to the Server
Copying the files to the server is a task that typically can't and shouldn't be automated unless you strictly go through a deployment server where you can completely install an application, test it before getting the files to the server. This process usually varies considerably for the application and can involve copying Web files, Application files and data files all of which may go into different paths. I'm not going to cover this aspect because this is usually a one time process that's handled via manual FTP.
The best 'generic' advice I can give for this aspect is to first create a local directory that has the full directory structure that you will use intact. It's also helpful if your development setup matches the deployment setup, but that's not strictly necessary. Either way I'd recommend the intermediate step of creating a deployment installation and testing that installation before sending files to the server. The reason for this is simple – dev installs tend to include all source files so even if something in your project file is missing and not getting compiled into a final EXE it may still work because the source files are still available. A standalone EXE file may not have this luxury and fail unceremoniously.
One thing that helps is to create your deployment structure something like this:
AppRoot
ApplicationFiles (EXE,Ini files, Web Connection Tools/html/Scripts/Template folders)
Web (the Web Virtual directory where WCSX etc. scripts and templates live)
Data (Optional data directory if you're using VFP data)
Note that in this scenario the web folder is NOT underneath the actual Web root (ie. c:\inetpub\wwwroot), but this works perfectly fine as long as the path is configured properly and permissions are set appropriately specifically for the IIS anonymous user to have access.
The data path is optional – you can also stick data below your application folder, or in some situations your data may be in different paths on the machine or on the network depending on your security policy.
The advantage of the above layout though is that you have a single directory structure that can be sent to the server for your application and you can test this installation independently of your development environment.
Programmatic Configuration of the Application
Once the files have been copied to the server, the next step is to configure your Web site so that it actually becomes a Web application. This means creating the virtual directory, setting up scriptmaps, setting a few permissions and if running in COM mode registering your server for COM and DCOM operation.
The documentation takes you through these steps manually as well as using the Web Connection Configuration Wizard which performs most of these steps for you.
However, in many cases you may want to complete automate the installation process and it's entirely possible to use a small bit of FoxPro code to handle the process of Web Server configuration automatically. The following script is a typical FoxPro install script that configures a Web application completely (note this script is IIS specific and would need changes to work with Apache):
DO WCONNECT
SET CLASSLIB TO WEBSERVER ADDITIVE
*** Hardcoded values - these would normally come
*** from some sort of UI (popup a form?)
*** Deployment Path
lcWebPath = LOWER(FULLPATH("..\web\"))
lcServerType = "IIS6"
*** Name of the virtual Web directory for IIS
lcVirtual = "Netting"
lcServerExe = "netting.exe"
lcTempPath = ADDBS(SYS(2023)) + "wc"
**** COM Configuration
lcProgId = "netting.nettingServer"
lcDCOMUserName = "Interactive User"
lcDCOMPassword = "" && Fill in if you're using a real account
*** End stock parameters
*** Prompt for a few of the main parameters - ideally this should be a form to
*** prompt for all the inputs
lcServerName = "LOCALHOST"
lcServerName = InputForm(lcServerName,"The local IP Address or domain of the server to configure","IIS Configuration - Server Address",,,"")
IF EMPTY(lcServerName)
return
ENDIF
lcServerType = InputForm(lcServerType,"IIS Version (IIS5, IIS6, IIS7)","IIS Configuration - IIS Server Type",,,"")
IF EMPTY(lcServerType)
return
ENDIF
lcWebPath = InputForm(lcWebPath,"Location of the Web Directory","IIS Configuration - Web Directory",,,"")
IF EMPTY(lcWebPath)
return
ENDIF
*** Create Virtual Directory
oIIS = CREATEOBJECT("wwWebServer")
oIIS.cServerType = lcServerType
oIIS.cIISVirtualPath = "IIS://" + lcServerName + "/W3SVC/1/ROOT" && IIS Schema path
oIIS.cApplicationPool = "West Wind Web Connection"
IF ISNULL(GETOBJECT(oIIS.cIIsVirtualPath))
showStatus( "Unable to connect to IIS Administration COM object." )
return
ENDIF
showStatus("creating virtual directory")
IF !oIIS.CreateVirtual(lcVirtual,lcWebPath)
showStatus("Unable to create virtual directory")
RETURN
ENDIF
*** Turn off Anonymous Permissions
loVirtual = GETOBJECT(oIIs.cIISVirtualPath + "/" + lcVirtual)
loVirtual.AuthAnonymous = .F.
loVirtual.SetInfo()
*** Assume wc.dll lives in BIN directory
lcScriptDLL = lcWebPath + 'bin\wc.dll'
showStatus("creating script maps")
lcIISVirtual = oIIS.cIISVirtualPath + "/" + lcVirtual
*** Create script maps to the DLL
oIIS.CreateScriptMap('wc',lcScriptDll, lcIISVirtual)
oIIS.CreateScriptMap('wcsx',lcScriptDll, lcIISVirtual)
oIIS.CreateScriptMap('wwsoap',lcScriptDll, lcIISVirtual)
oIIS.CreateScriptMap('aspx',lcScriptDll, lcIISVirtual)
showStatus("registering ISAPI dll in IIS")
*** In IIS6 and later we have to register any DLLs with IIS
IF LOWER(lcServerType) = "iis" AND LOWER(lcServerType) > "iis5"
*** Add the DLL as a registered
loIIS = CREATEOBJECT("wwIISAdmin")
loIIS.cPath = "IIS://" + lcServerName + "/W3SVC"
loIIS.AddRegisteredExtension(lcScriptDll,"West Wind Web Connection")
loIIS = .f.
ENDIF
*** Create Temp Directory
IF !ISDIR(lcTempPath)
MD (lcTempPath)
ENDIF
*** Set permissions for IUSR_ Virtual
loVirtual = GETOBJECT(oIIS.cIISVirtualPath)
lcAnonymousUserName = loVirtual.AnonymousUserName
loVirtual = .f.
*!* *** Set access on the Web directory
IF !EMPTY(lcWebPath)
*** Read writes - wwUtils.SetAcl()
llResult = SetAcl(lcWebPath,lcAnonymousUserName,"R",.t.)
ENDIF
*** Not required for Web Connection 5.x – wc.dll runs as SYSTEM
*!* IF lcTempPath
*!* *** Full rights in the temp directory
*!* llResult = SetAcl(lcTempPath,lcAnonymousUserName,"F",.t.)
*!* ENDIF
showStatus("Register Com object")
*** Register COM object and configure DCOM programmatically
IF !EMPTY(lcProgId)
wait window "Registering COM server" nowait
lcCommand = "run " + lcServerExe + " /regserver"
&lcCommand
IF ISWinNT()
IF !EMPTY(lcDCOMPassword) AND !FILE("DCOMPermissions.exe")
MESSAGEBOX("DCOMPermissions.exe file is missing" + CHR(13) +;
"Can't configure DCOM settings. Please configure manually.",48,"DCOM Settings")
ELSE
DO DCOMCNFGServer WITH lcProgId, lcDCOMUserName, lcDCOMPassword
IF FILE("DCOMPermissions.exe")
loAPI = CREATE("wwAPI")
lcMachineName = loAPI.GetComputerName()
DCOMLaunchPermissions(lcProgId,"Administrators")
DCOMLaunchPermissions(lcProgId,"SYSTEM")
DCOMLaunchPermissions(lcProgId,"INTERACTIVE")
ENDIF
ENDIF
ENDIF
ENDIF
FUNCTION showStatus(lcMessage)
WAIT WINDOW NOWAIT (lcMessage)
ENDFUNC
This script is not generic obviously, but it can be customized quite easily in a few places for most configurations. You might want to add or remove some some script maps (like ASPX which was used for this particular project) or you might need additional settings applied say to the virtual directory. Note that the code even does some custom ADSI configuration for setting security – in this case it's removing Anonymous user access from the app so that every user is forced to log in with Windows credentials.
The beauty of this sort of script is that once you have your configuration set up it's very easy to run it for a first time config or even to reconfigure if something should get accidentally removed.
If you want to deploy this you can either choose to build an EXE out of this small program by adding to a project and compiling into an EXE, or maybe even easier by adding it to your main server EXE itself with code like the following in the startup program (like wcDemoMain.prg):
************************************************************************
*FUNCTION NettingMain
******************************
*** Created: 06.05.2008
*** Function: Web Connection Mainline program. Responsible for setting
*** up the Web Connection Server and get it ready to
*** receive requests in file messaging mode.
************************************************************************
LPARAMETERS lcAction
IF !EMPTY(lcAction)
IF UPPER(lcAction) == "CONFIG"
DO configurationScript
RETURN
ENDIF
ENDIF
*** This is the file based start up code that gets
*** the server form up and running
#INCLUDE WCONNECT.H
…
With this code the configuration script is now part of the server and you can simply do:
YouServer.exe Config
To run the configuration code. Simple and self contained.
There's no reason to sweat installation of Web Connection applications when you have a good install script and as you can see it's pretty easy to set up – yes there's a fair bit of code to it, but most of it is truly boilerplate and you can just read through it and adjust as needed. If you are using a deployment folder as mentioned above you can actively test your install script to ensure it works on your deployment server (or local machine) first before moving things to the live site.
It's a win win solution to automate this process and well worth the effort. You will thank yourself next time you'll need to move your application to a new server due to hardware upgrades or – gulp – a hardware failure.