PROVISIO DevBlog

Using SiteRemote to Change Windows Registry Settings

The SiteRemote job system enables you to make Windows registry changes on your SiteKiosk Windows clients that are registered with your team. This can be used for example to change a Windows setting remotely or add a registry key to make Windows or an application behave differently than before.

The registry changes can be made in Javascript using methods of the Windows Script Host. The scripts can be distributed to the clients by creating a SiteRemote job with the action type 'Execute Script'.

After you selected the 'Execute Script' action type you can copy and paste the following to the script text box:

var gk_WshShell = new ActiveXObject("WScript.Shell");
//Create a test registry key 
gk_WshShell.RegWrite("HKLM\\Software\\SiteRemoteTest\\Test", "SiteRemote generated this registry key for testing purposes", "REG_SZ");

For this example, make sure to not enable the option 'Script requires SiteKiosk Object' as we want to first write to the HKEY_LOCAL_MACHINE (HKLM) part of the registry. If you enable the option, the script is executed with the rights of the user SiteKiosk is running under at the time of the script execution. Depending on the user rights writing to HKLM might not be possible. With the option disabled the script is executed with the full rights of the Local System Windows user.

The result will look like this if you view it with the Windows Registry Editor:

Note that the example uses the Software path, which means that on a 64-Bit system the entry will automatically be created under Wow6432Node as the client application executing the code is running in 32-Bit mode.

If you use the next example script as part of a SiteRemote script job you would change the entry that has been created by the code above:

var gk_WshShell = new ActiveXObject("WScript.Shell");
//Change the test registry key
gk_WshShell.RegWrite("HKLM\\Software\\SiteRemoteTest\\Test", "SiteRemote changed this registry key for testing purposes", "REG_SZ");

The next example would delete the test entry that has been created in the Windows registry:

var gk_WshShell = new ActiveXObject("WScript.Shell");
//Delete the test registry key
gk_WshShell.RegDelete("HKLM\\Software\\SiteRemoteTest\\");

As mentioned above, if you want to write to the registry hive of the user you are running SiteKiosk under, at the moment the job is executed on the client computer, you need to activate the option 'Script requires SiteKiosk Object'. This is normally used for executing SiteKiosk Object Model code, but it also means that the code is not executed with the System user the job would otherwise be running under.

The following example will do the same as the first one with the exception that it will write the key to the registry hive of the user (HKEY_CURRENT_USER or HKCU):

var gk_WshShell = new ActiveXObject("WScript.Shell");
//Create a test registry key 
gk_WshShell.RegWrite("HKCU\\Software\\SiteRemoteTest\\Test", "SiteRemote generated this registry key for testing purposes", "REG_SZ");

If you use HKCU and do not activate the option 'Script requires SiteKiosk Object' the key will be written to the hive of the System user.

Note that contrary to the examples that did not have the checkbox for the SiteKiosk Object enabled this one creates the key directly under the Software path, even on a 64-Bit system, as the client application responsible for executing the code under these circumstances is running in native mode.

Changing Individual SiteKiosk Configuration Elements with a SiteRemote Job

Often you just need to change a single SiteKiosk configuration setting. Even when using a great number of SiteKiosk machines this is not a problem, you can just use the configuration feature of SiteRemote to distribute the changed configuration file to the machines.

But what if your machines all use configurations that differ in parts, for example the configurations are all using a different start page to reflect their individual locations while the rest of the settings are the same. This challenge can be solved by making use of the fact that the SiteKiosk configuration files are built on the XML format. This enables you to create a Javascript file that can access and edit a specific element of the configuration file.

The following script examples do not use the SiteKiosk Object Model. They use common Javascript/JScript techniques as described for example in the Microsoft MSDN library.

The first example will enable the fullscreen mode of SiteKiosk. The script starts by creating the required ActiveX objects to access the Windows registry and to edit an XML document. Next it queries the path of the latest SiteKiosk configuration file from the registry, either of a 32 or a 64 bit system. It then loads the document and assigns the XML node for the fullscreen setting and changes its text. Finally the edited configuration file is being saved. For further information on the methods to work with an XML document see http://msdn.microsoft.com/en-us/library/System.Xml.XmlDocument_methods%28v=vs.110%29.aspx.

try{
	//Wsh Shell Object
	var WshShell = new ActiveXObject("WScript.Shell");

	//XML support
	var xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");

	//Path to the SiteKiosk configuration
	var OsType = WshShell.RegRead("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\\PROCESSOR_ARCHITECTURE");
	if (OsType == "x86")
		var gstr_configpath = WshShell.RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\PROVISIO\\SiteKiosk\\LastCfg"); //you may use an absolute path instead, e.g.: var gstr_configpath = "c:\\program files\\sitekiosk\\config\\myconfig.skcfg"
	else
		var gstr_configpath = WshShell.RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\PROVISIO\\SiteKiosk\\LastCfg"); //you may use an absolute path instead, e.g.: var gstr_configpath = "c:\\program files\\sitekiosk\\config\\myconfig.skcfg"

	if(xmlDoc.load(gstr_configpath)){
		var lk_nodeselection = xmlDoc.documentElement.selectSingleNode("//sitekiosk-configuration/browserbar/hidemode");
		//Changes the node text to 1 which enables permanent fullscreen mode (0 disables fullscreen, 2 enables fullscreen mode for specific URLs only).
		lk_nodeselection.text = "1";
		//Saves the  changes
		xmlDoc.save(gstr_configpath);
	}
	else{
		//Returns an error exit code to SiteRemote 
		ExitResult.Code = 1;
		ExitResult.Description = "Error opening configuration file.";
	}
}
catch(e){
	try	{
		if(e.number != 0)
			ExitResult.Code = e.number;
		else
			ExitResult.Code = 1;
		ExitResult.Description = e.description;
	}
	catch(e){}
}

After running the script the fullscreen setting of the SiteKiosk configuration looks like this:

The second example adds a URL excluded from filtering to the Content Filter of SiteKiosk. Again it starts by creating the required ActiveX objects and finding the path to the latest SiteKiosk configuration file. Next it adds a new XML node to an existing one for the URL that should be excluded from filtering. After that the document is being saved. For further information on the methods to work with an XML document see http://msdn.microsoft.com/en-us/library/System.Xml.XmlDocument_methods%28v=vs.110%29.aspx.

try{
	//Wsh Shell Object
	var WshShell = new ActiveXObject("WScript.Shell");

	//XML support
	var xmlDoc = new ActiveXObject("Msxml2.DOMDocument.3.0");

	//Path to the SiteKiosk configuration
	var OsType = WshShell.RegRead("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\\PROCESSOR_ARCHITECTURE");
	if (OsType == "x86")
		var gstr_configpath = WshShell.RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\PROVISIO\\SiteKiosk\\LastCfg"); //you may use an absolute path instead, e.g.: var gstr_configpath = "c:\\program files\\sitekiosk\\config\\myconfig.skcfg"
	else
		var gstr_configpath = WshShell.RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\PROVISIO\\SiteKiosk\\LastCfg"); //you may use an absolute path instead, e.g.: var gstr_configpath = "c:\\program files\\sitekiosk\\config\\myconfig.skcfg"

	if (xmlDoc.load(gstr_configpath)){
		var lobj_snglnode = xmlDoc.selectSingleNode("//plugin[@name='SiteCoach']");
		var lobj_newelelement,lstr_newtext;
		lobj_newelelement=xmlDoc.createNode(1, "exclude", lobj_snglnode.namespaceURI);
		lstr_newtext=xmlDoc.createTextNode("http://www.provisio.com");
		lobj_newelelement.appendChild(lstr_newtext);
		lobj_snglnode.appendChild(lobj_newelelement);
		//Saves the  changes
		xmlDoc.save(gstr_configpath);
	}
	else{
		//Returns an error exit code to SiteRemote 
		ExitResult.Code = 1;
		ExitResult.Description = "Error opening configuration file.";
	}
}
catch(e){
	try	{
		if(e.number != 0)
			ExitResult.Code = e.number;
		else
			ExitResult.Code = 1;
		ExitResult.Description = e.description;
	}
	catch(e){}
}

After running the script the Content Filter page of the SiteKiosk configuration looks like this:

To run such a script just go to the Jobs section of SiteRemote and create a new job and select Execute Script as action. Copy and paste the code into the text field and assign the job. Do not activate the checkbox Script requires SiteKiosk Object, as it would run the script within the SiteKiosk user context, who for security reasons does not have the necessary rights to edit the configuration.

Note that you should make changes to the configuration file with care and test them first before applying to a great number of terminals. E.g. writing XML incompatible values to the configuration will make the file unreadable, so SiteKiosk will then load the emergency configuration file instead.

In order to let the new configuration file become the active configuration you need to restart SiteKiosk.

LDAP User Mapping in SiteRemote

Note: The following applies to the current release version 5.1.0.2188 and above. For compatibility reasons with OpenLDAP the syntax of the user.config section has been changed from the original release version 5.1.0.2186. The old syntax is no longer supported.

With SiteRemote Server 5.1 we introduced LDAP user mapping for customers running their own SiteRemote server. Now you can use user credentials provided by the directory service of your company's domain (q.v. Active Directory) for authentication in SiteRemote.

LDAP users and normal SiteRemote team users can be used together. At least one SiteRemote team user is required for each team you want to map LDAP users to.

Before you can map LDAP users to SiteRemote you need to create at least one team. You can do that for example on the Teams tab of the SiteRemote Server Administration. Note that while creating the team you need to specify a user, this user must not be an LDAP user but a normal SiteRemote Team user. This is the user responsible for a team and it cannot be deleted when logged in with an LDAP user. You can only delete this user from another SiteRemote team user account within a team (Note: it is planned for future SiteRemote versions to make the primary administration user permanent, so this behaviour might change).

After the team creation you can proceed to prepare your SiteRemote server to use LDAP authentication. You now need to manually edit the configuration file of the server. You will find the SiteRemoteServer.config file under ..\PROVISIO\SiteRemote\Config. Open it with an editor like Notepad and scroll down to the bottom. There you need to change the default User.config section right before the closing configuration tag:

<User.config LdapServerPort="0" LdapSecureSocketLayer="false" />

to something like this:

<?xml version="1.0" encoding="utf-8"?>
<Configuration>
	...
	
	...
	<SiteCaster.config VideoAudioAnalyzerPath="VideoAudioAnalyzer.exe" />
	<User.config>
		<LdapImportFullFilePath>c:\ldapuserlist.csv</LdapImportFullFilePath>
		<LdapServerHost>ldapserver.yourdomain.biz</LdapServerHost>
		<LdapServerPort>389</LdapServerPort>
		<LdapSecureSocketLayer>false</LdapSecureSocketLayer>
		<LdapUserPatterns>yourcompany\{0}</LdapUserPatterns>
	</User.config>
</Configuration>

The User.config section is the parent element for all LDAP related child elements in the SiteRemote configuration.

The LdapImportFullFilePath element must include the full path to the .csv file that includes the domain users you want to map to SiteRemote. More on that file a little later.

LdapServerHost includes the full host name of your LDAP server, you may also use an IP adress.

LdapServerPort specifies the port your LDAP server uses. The default LDAP port is 389 or 636 if using an SSL connection.

LdapSecureSocketLayer is a boolean value. It is true if the server uses SSL.

LdapUserPatterns defines the way SiteRemote queries the user with the LDAP server. There are three supported principal forms: LDAP DN, Kerberos and NTLM. Note that these forms cannot be mixed. {0} is a required part of the pattern and is replaced by SiteRemote to include the user name that is authenticated with the LDAP server. The same user data is also used to perform the LDAP request.
LDAP DN uses the LDAP distinguished name syntax. This is used for example in OpenLDAP installations like Novell eDirectory.

<LdapUserPatterns>cn={0},ou=users,ou=us,o=yourcompany</LdapUserPatterns>

Because that syntax is very specific in regards to the location that is queried within the LDAP structure, you can add more than one pattern. The patterns must be seperated by a semicolon.

<LdapUserPatterns>cn={0},ou=users,ou=california,ou=us,o=yourcompany;cn={0},ou=users,ou=de,o=yourcompany;cn={0},ou=users,ou=gb,o=yourcompany;</LdapUserPatterns>

Kerberos authentication is usually used in Windows Active Directory. This syntax does not require different patterns as it queries the complete LDAP tree.

<LdapUserPatterns>{0}@yourcompany.biz</LdapUserPatterns>

NTLM authentication is also commonly used in Windows Active Directory. This syntax does not require different patterns as it queries the complete LDAP tree.

<LdapUserPatterns>yourcompany\{0}</LdapUserPatterns>

Here is another full example that uses SSL and LDAP DN:

<?xml version="1.0" encoding="utf-8"?>
<Configuration>
	...
	
	...
	<SiteCaster.config VideoAudioAnalyzerPath="VideoAudioAnalyzer.exe" />
	<User.config>
		<LdapImportFullFilePath>c:\ldapuserlist.csv</LdapImportFullFilePath>
		<LdapServerHost>ldapserver.yourdomain.biz</LdapServerHost>
		<LdapServerPort>636</LdapServerPort>
		<LdapSecureSocketLayer>true</LdapSecureSocketLayer>
		<LdapUserPatterns>cn={0},ou=users,ou=california,ou=us,o=yourcompany;cn={0},ou=users,ou=de,o=yourcompany</LdapUserPatterns>
	</User.config>
</Configuration>

After making and saving the changes to the SiteRemoteServer.config file you need to restart the SiteRemote Server service in the Microsoft Management Console for Windows Services (services.msc).

Now its time to create and place the .csv file with your LDAP user list at the location you specified in the SiteRemote configuration file. Note that the file only needs to contain the LDAP users you actually want to use with SiteRemote and not all LDAP users in your domain. Each line of the .csv file represents one LDAP user. The syntax is as follows:

[<oldusername>],<username>,<team>,<role(s)>,[<group(s)>]

oldusername is optional and required if you want to rename a user and keep this user's assignments within a SiteRemote team. This can be useful due to a name change because of marriage for example. oldusername then specifies the existing name of the user and username would contain the new one. Providing a name in this field is optional, if you don't provide a name you still need to write the comma to separate this field from the next. Note that user names must be unique, each user name can only be used once.

username specifies the name of the user. This field is required. Note that user names must be unique, each user name can only be used once.

team specifies the SiteRemote team name you want to assign the user to. This field is required.

role(s) (optional since SiteRemote Server 5.2 or higher) specifies the role or roles that you want to assign to the user. The role names of the default roles are language specific and depend on the language that was assigned at the time the team was created. For example the default roles for English are Administrator, User and Guest, in German they are Administrator, Benutzer and Gast. Other roles can be created and individually named in a SiteRemote team under Administration -> User Roles. If you want to assign more than one role you need to use quotation marks and separate each role by a comma.

group(s) is optional and only available with SiteRemote Server 5.2 or higher. You can assign LDAP users to groups you have created. If you want to assign more than one group you need to use quotation marks and separate each group by a comma. Note that each user will be automatically assigned to the Everyone group of a SiteRemote team.

Generally quotation marks are recommended to be used for each field. Here is an example of how the file can look like:

,"LDAPuser1","team1","Administrator"
,"LDAPuser2","team1","Guest"

,"LDAPuser3","team2","Administrator"
,"LDAPuser4","team2","User,Team2Role1,Team2Role2"
"LDAPuser5","LDAPuser7","team2","Guest"

,"LDAPuser6","team3","Administrator","Admin Group"

Note that the empty lines between the teams are not required, yet they can be used to better visualize assignments for different teams.

Each time you edit and save the .csv file or overwrite the existing file with a new one, the changes are applied.

To remove a user, simply delete the line from the .csv file and save it. The following would remove LDAPuser4 from team2:

,"LDAPuser1","team1","Administrator"
,"LDAPuser2","team1","Guest"

,"LDAPuser3","team2","Administrator"
,"LDAPuser7","team2","Guest"

,"LDAPuser6","team3","Administrator","Admin Group"

To remove all LDAP users from a team, just remove them all from the file. Placing an empty file will remove all LDAP users from all teams. The next example will remove all LDAP users from team2:

,"LDAPuser1","team1","Administrator"
,"LDAPuser2","team1","Guest"

,"LDAPuser6","team3","Administrator","Admin Group"

In case you want to assign a group but no role, the line would look like this:

,"LDAPuser6","team3",,"Admin Group"

Status messages regarding the processing of the file can be found in the SiteRemote server log file. The file SiteRemote.log can be found under ..\PROVISIO\SiteRemote\Log.

For full functionality the LDAP user authentication requires SiteKiosk Android 2.2 or higher or SiteKiosk Windows 8.9 or higher. Older versions cannot be registered with the SiteRemote server using an LDAP user.

In case you are using the TerminalCommander tool please make sure you are using the version that comes with SiteRemote Server 5.1 or higher.

Please note that the AutoRegister tool does not support LDAP users due to technical limitations.

How to Delete HTML5 Web Storage Content

HTML5 Web Storage is intended to store content locally on a PC for longer periods, e.g. for working offline. The web page/web app that stores the content is responsible for deleting it as well, therefore SiteKiosk does not delete Web Storage content by design.

In case you come across a project, where you can't influence the behaviour of a web page that uses Web Storage but need to delete the content nonetheless, you may use the scripting options of SiteKiosk to handle that situation.

The following script makes use of the OnReset and OnScreenSaverBegin events of the SiteKiosk Object Model to trigger deleting the Web Storage content. OnReset fires when a person hits the logout button of SiteKiosk or when a Pay session runs out. OnScreenSaverBegin fires once the screensaver starts. Note that deleting the Web Storage requires a restart of SiteKiosk to also clear the Web Storage content from the currently running instance of the browser. This means that the screensaver will only run for the time we define as the wait time for the content deletion to happen, if we use the OnScreenSaverBegin event. Please consider this fact for your project.

Next we need to wait a few seconds to let SiteKiosk run through the default processes that happen if any of the above events occur. To make SiteKiosk wait, we use the AddDelayedEvent method.

The next step is to actually delete the Web Storage content. For that we use the FileSystemObject of Windows Scripting. Be aware that the location of the folder (C:\Users\[User Name]\AppData\Local\Microsoft\Internet Explorer\DOMStore) that needs to be deleted is user sensitive. Make sure to use the path that is appropriate for the user you run SiteKiosk under. In most cases SiteKiosk will run under the restricted SiteKiosk Windows user, therefore the script we are building uses the path suitable for this environment: C:\Users\SiteKiosk\AppData\Local\Microsoft\Internet Explorer\DOMStore.

The final step is to make a restart of SiteKiosk. Without the restart the current browser instance will still use a cached version of the Web Storage content.

The script looks like this:

//Initializing the events we want to use to delete Web Storage
SiteKiosk.OnReset = WaitBeforeDelete;
SiteKiosk.ScreenSaver.OnScreenSaverBegin = WaitBeforeDelete; //Note that using the screensaver event will basically stop the screensaver from running longer than the wait time defined below, because of the required SiteKiosk restart.

function WaitBeforeDelete()
{
	//Give SiteKiosk some time to run through its default session end/screensaver activation methods
	evtid = SiteKiosk.Scheduler.AddDelayedEvent(5000, DeleteWebStorage);
}

function DeleteWebStorage(eventID)
{  
	try
	{	 
		//Deleting the folder with the help of the FileSystemObject
		var fso = new ActiveXObject("Scripting.FileSystemObject");
 		fso.DeleteFolder("C:\\Users\\SiteKiosk\\AppData\\Local\\Microsoft\\Internet Explorer\\DOMStore", true);
 		SiteKiosk.Logfile.Notification("Deleting the Web Storage content was successful");

		//Required restart to clear the Web Storage from the temporary cache of the current browser instance
		SiteKiosk.Restart();
 	}
	catch (e)
	{
		//Create a SiteKiosk logfile entry in case something goes wrong
		SiteKiosk.Logfile.Notification("There was an error deleting the Web Storage content: " + e.description);
	}
}

Save the script under any name as a javascript file, e.g. DeleteWebStorage.js. Put the file in the ..\SiteKiosk\html folder and then open the SiteKiosk configuration and go to Start Page & Browser, click on Advanced and add the script file as an external script under Execute Script.

If you run the script and monitor the logfiles, a successful deletion of the Web Storage will look like this in the moment of the necessary restart of SiteKiosk:

SiteKiosk and SiteRemote Server not Affected by OpenSSL Heartbleed Bug

SiteKiosk does not use the OpenSSL library.

The OpenSSL library used by SiteRemote is not affected by the heartbleed bug. SiteRemote includes a version of the library that is not vulnerable. This applies to the cloud services provided by PROVISIO, e.g. www.siteremote.net, as well as the installer to setup your own SiteRemote Server.

OpenSSL is part of the XMPP component of SiteRemote Server, used for communication with SiteKiosk Android devices.

Using SiteKiosk to Automate Window and Dialog Handling

SiteKiosk Windows allows you to add external applications to be started from within the secure environment that SiteKiosk provides. As an additional security layer, the configuration of SiteKiosk lets you specify the handling of windows and dialogs. Usually this is intended to prevent users from changing settings in an options dialog or making other undesired changes to external applications and operating system settings. To achieve this, SiteKiosk identifies windows and dialogs based on title and/or class. After the identification SiteKiosk sends a Windows Message Command (WM_COMMAND), in most cases this is the WM_CLOSE command, to close the window or dialog directly, but SiteKiosk supports a complete range of commands that can be send.

Little known is the fact that the mechanisms of the windows and dialogs management can also be used to automate processes. For this purpose the different available commands are useful as they allow to not only close a dialog automatically but also to make a window or dialog execute certain actions offered in their specific context.

Let's look at this in more detail with the help of an example. When you are printing a PDF file from within SiteKiosk, you will see the print dialog of the Acrobat Reader, that needs to be confirmed before the actual printing starts. SiteKiosk can auto-confirm this dialog to make printing more convenient for the user. In order for SiteKiosk to auto-confirm the PDF printing we need to open the configuration of SiteKiosk and go to Access/Security, there we select Block system critical windows & dialog boxes and click the Settings button. In the new configuration dialog we click the Add button and create a new treatment rule. We choose to close the window immediately, then we select to send a WM_COMMAND to close the window. As the command we select OK from the dropdown. Now we set the title, which is Print in this case, and the class, which is #32770 in this case (you can use a tool like AutoIT to find the class). All other settings can be left as is.

With these settings SiteKiosk will automatically confirm the PDF print dialog with OK, which triggers the printing of the document. Note that for this example Acrobat Reader XI was used and besides the above window and dialog settings SiteKiosk was configured to allow printing.

Accessing Local Resources from the SiteKiosk Browser

SiteKiosk is a secure web browser, by default it does not allow the use of WScript and similar coding options, that let you access local resources. As part of the requirements of a kiosk project you still may need to access such local resources, e.g. for querying a logged in user or reading/changing a local file or the Windows registry.

By adding an additional security layer, SiteKiosk allows you to execute such code as part of an external script file, that you need to specifically allow in the configuration of SiteKiosk. This script is started togehter with SiteKiosk. You can either execute all the required code just within the external script or you can access the script from a webpage as described in another post.

The first example just reads a registry setting and writes its value to the SiteKiosk log files:

//Wsh Shell Object
var WshShell = new ActiveXObject("WScript.Shell");

//This example reads the type of the operating system
var OsType = WshShell.RegRead("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment\\PROCESSOR_ARCHITECTURE");

//Write the gathered information to the SiteKiosk log file
SiteKiosk.Logfile.Notification("Detected OS type: " + OsType);

Just copy the above code into a .js file with whatever name you like and add it as an external script to test for yourself.

The second example queries the user that SiteKiosk currently runs under on the press of a button in a web page. For that we need two files. The html page, that you can put locally or on a web server, and the external script that runs the code that accesses local resources.

First is the external script that will tell us which local user SiteKiosk is running under:

//Initialize the required WScript object
var WshNetwork = new ActiveXObject("WScript.Network");

//Simple method that returns the user name
function QueryUser(){
	return WshNetwork.UserName;
}

Again, just copy the above code into a .js file with whatever name you like and add it as an external script.

Next is the html code that communicates with the external script. Please have a look at this post for more information on that topic.

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<title>What user is SiteKiosk running under?</title>
<SCRIPT TYPE="text/javascript">
    //Initializing the SiteKiosk Object Model
    window.external.InitScriptInterface();
     
    function QueryUserExt(){
        //Query the user by using the external script file
        var str_user = SiteKiosk.ScriptDispatch.QueryUser();
		window.alert("User Name: " + str_user);
    }
     
//-->
</script>
<body>
    <input type="button" value="What user is SiteKiosk running under?" onclick="QueryUserExt()">
</body>
</html>

Copy the above code into an .html file that you name to your liking and either place it locally (e.g. in the ..\SiteKiosk\html\ folder) or on a web server. If you are not using the ..\SiteKiosk\html\ folder please make sure that the html file has script allowance in the SiteKiosk configuration.

The result of this little experiment will look similar to this:

Be aware that the code is executed with the user rights of the user you run SiteKiosk under, which may limit you options, e.g. you may only be capable of writing in the HKCU branch of the Windows registry and not in HKLM.

Use SiteKiosk to Accept Payment for any kind of Service

The SiteKiosk Pay version allows you to charge a kiosk user for a variety of basic services right out of the box. You can take a fee for surfing the web, making a download, sending a multimedia email, using an application or printing.

By a little bit of code you can use the payment options of SiteKiosk to allow payment directly at the kiosk for whatever service you desire. This can be for goods in a webshop, concert tickets or even fines, e.g. paying a parking violation ticket. This code can even be added to an existing project to add payment by SiteKiosk as an additional feature. You may then use browser detection to execute the SiteKiosk code only within the SiteKiosk browser.

The following code makes use of the SiteKiosk Object Model. It uses the Dispatch object to access the SiteCashScript.js file that implements the StartPullRequest method that we will be using. The file SiteCashScript.js is loaded automatically when you launch SiteKiosk. So to kick off our request for payment we use the following line:

SiteKiosk.Plugins("SiteCash").Script.Dispatch.StartPullRequest("Text to show in the pullmode dialog that states the reason for requesting payment", 0.5, OnPullRequestCompleted, 30);

The first parameter of the StartPullRequest method is a string that states the reason for requesting payment. It will be displayed in the payment request dialog that is triggered by calling the StartPullRequest method. The second parameter is the amount to be requested. The third parameter is the method that is being called once the pull request completes. The fourth and last parameter is the time in seconds that the request dialog will wait for an inpayment.

When the pull request is complete it will call the method you named as the third parameter. This is how it needs to be added to your code:

function OnPullRequestCompleted(bool_success){
    if (bool_success){
        //your code for a successful payment
	}
	else{
		//your code if the payment failed
	}
}

The parameter passed to the method is a boolean value that states whether the requested amount has been paid or not. Depending on the outcome you can add your own code for either of the two scenarios.

A simple implementation of the above could look like this:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<title>Pullmode Example</title>
<SCRIPT TYPE="text/javascript">
    //Initializing the SiteKiosk Object Model
    window.external.InitScriptInterface();
     
    function OnPullRequestCompleted(bool_success){
		if (bool_success){
			document.getElementById("result").innerHTML = "Thank you. The payment was successful.";
		}
		else{
			document.getElementById("result").innerHTML = "Payment has not been made.";
		}
	} 
//-->
</script>
<body>
    Please click the button and pay the requested amount 
	<input type="button" value="Make your payment" onclick="SiteKiosk.Plugins('SiteCash').Script.Dispatch.StartPullRequest('Please make your payment! This service', 0.5, OnPullRequestCompleted, 30); ">
    <br />
    <span id="result"></span>
</body>
</html>

When you use the example in SiteKiosk you will see this:

You can even influence the whole process further by editing the StartPullRequest method. We have learned above that the StartPullRequest method is implemented in the file ..\SiteKiosk\SiteCash\SiteCashScript.js and it can be modified to fit your special requirements, e.g. you can change the design of the payment request dialog.

Please make sure to allow scripting for your HTML pages that you use the SiteKiosk Object Model on. To do so, enter the page and the path to the page in the SiteKiosk configuration under ACCESS-> URLs with script permission.

Accessing an External SiteKiosk Script from a Webpage

SiteKiosk offers you the option to run an external script in the background each time SiteKiosk is executed. This is useful to place more general SiteKiosk Object Model code and it can also be used to place variables and functions you want to use in between different web pages.

A simple external script file to illustrate the above can look like this:

var gstr_testvalue = "Default value";
 
function setTestValue(lstr_newvalue){
	gstr_testvalue = lstr_newvalue;
}
 
function retrieveTestValue(){
	return gstr_testvalue;
}

You can save this into a .js-file and add it to your SiteKiosk configuration as an external script.

To continue with our example we create an html page that changes the value of the gstr_testvalue variable. To demonstrate how to access a variable or a function of the external script the example page changes the value both directly and by using the setTestValue function that has been defined in the external script. To actually access the members defined in the external script the ScriptDispatch Object of the SiteKiosk Object Model is used.

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<title>Page that sets a new value</title>
<SCRIPT TYPE="text/javascript">
	//Initializing the SiteKiosk Object Model
	window.external.InitScriptInterface();
	
	function directVariableAccess(){
		//set the value 1 for the variable in the external script, this overwrites the existing value
		SiteKiosk.ScriptDispatch.gstr_testvalue = "Value created using direct access";
	}
	
	function functionBasedVariableAccess(){
		//set the value 1 for the variable in the external script, this overwrites the existing value
		SiteKiosk.ScriptDispatch.setTestValue("Value created using function-based access");
	}
	
//-->
</script>
<body>
	<input type="button" value="Direct Variable Write Access" onclick="directVariableAccess()">
	<br />
	<input type="button" value="Function-based Variable Write Access" onclick="functionBasedVariableAccess()">
</body>
</html>

Next we create an additional html page that retrieves the value from the external script. Again using a direct and a function-based method.

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<title>Page that reads the value</title>
<SCRIPT TYPE="text/javascript">
	//Initializing the SiteKiosk Object Model
	window.external.InitScriptInterface();
	
	function directVariableAccess(){
		//set the value 1 for the variable in the external script, this overwrites the existing value
		alert("Current value retrieved using direct access method: " + SiteKiosk.ScriptDispatch.gstr_testvalue);
	}
	
	function functionBasedVariableAccess(){
		//set the value 1 for the variable in the external script, this overwrites the existing value
		alert("Current value retrieved using function-based access method: " + SiteKiosk.ScriptDispatch.retrieveTestValue());
	}
	
//-->
</script>
<body>
	<input type="button" value="Direct Variable Read Access" onclick="directVariableAccess()">
	<br />
	<input type="button" value="Function-based Variable Read Access" onclick="functionBasedVariableAccess()">
</body>
</html>

The two html files can be placed locally on a SiteKiosk computer (e.g. in the html subfolder of the SiteKiosk installation folder) or on a web server. Just make sure that the location you placed the files under is allowed to execute the SiteKiosk Object Model.

Using Multitouch Gestures in SiteKiosk

Some may have noticed that a great number of multitouch gestures are not working in SiteKiosk by default. This is due to a limitation of the public part of the Microsoft WebBrowser control for which Microsoft only offers very basic touch gesture support. Since the release of SiteKiosk 8.8 this limitation can be lifted by using a little bit of scripting.

SiteKiosk works around the multitouch limitations of the WebBrowser control by using script injection to emulate multitouch events for a page. Because of the possible side effects of script injection this feature of SiteKiosk can be dynamically turned off and on using the SiteKiosk Object Model.

Note that you need a multitouch capable device, Internet Explorer 10 or higher, a website that uses a multitouch framework (e.g. hammer.js) and SiteKiosk 8.8 or higher.

To make your website that supports multitouch ready to be used with SiteKiosk you need to add a few lines of SiteKiosk Object Model Code. In case the website is not only intended to be used with SiteKiosk you may want to have a look at this article to make use of browser detection.

You basically need two SiteKiosk Object Model properties to get going. The first is IsMultitouchCapable which checks whether the device you are using SiteKiosk on is capable of handling multitouch. The second is MultitouchEnabled which lets you retrieve and set the support of multitouch in SiteKiosk. So the lines of code you have to use would look like this:

//Initialize the SiteKiosk Object Model
window.external.InitScriptInterface();
			
//Enable multitouch for the SiteKiosk browser if it is currently not enabled and the device, represented by the currently active SiteKiosk browser window, is capable of multitouch.
if (SiteKiosk.WindowList.ActiveWindow.SiteKioskWindow.IsMultitouchCapable && !SiteKiosk.WindowList.ActiveWindow.SiteKioskWindow.MultitouchEnabled) {
	SiteKiosk.WindowList.ActiveWindow.SiteKioskWindow.MultitouchEnabled = true;
}

Because writing an article about multitouch without showing an actual example would be a litte dull, the following is the code of a simple example page that uses jquery, hammer.js and of course the SiteKiosk Object Model (note that the example also works in Internet Explorer, so feel free to compare):

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="IE=edge" ><!--Required only if for whatever reason the web server may be configured to deliver pages in older IE compatibility modes-->
    <title>SiteKiosk Multitouch Test Page</title>
    <script type="text/jscript" src="Scripts/jquery-1.7.1.js"></script>
    <script type="text/JScript" src="Scripts/hammer.js"></script>
    <script type="text/JScript" src="Scripts/jquery.hammer.js"></script>
     
    <script type="text/javascript">
        //Write debug log messages to the SiteKiosk log files
        function Log(msg) {
            try {
                SiteKiosk.Logfile.Notification(msg);
            }
            catch(ex) {
                console.log(msg);
            }
        }
         
        try {
            //Initialize the SiteKiosk Object Model
            window.external.InitScriptInterface();
             
            //Enable multitouch for the SiteKiosk browser if it is currently not enabled and the device, represented by the currently active SiteKiosk browser window, is capable of multitouch.
            if (SiteKiosk.WindowList.ActiveWindow.SiteKioskWindow.IsMultitouchCapable && !SiteKiosk.WindowList.ActiveWindow.SiteKioskWindow.MultitouchEnabled) {
                SiteKiosk.WindowList.ActiveWindow.SiteKioskWindow.MultitouchEnabled = true;
            }
            else {
                if (!SiteKiosk.WindowList.ActiveWindow.SiteKioskWindow.IsMultitouchCapable)
                    Log("Device is not capable of multitouch.");
            }
        }
        catch(ex) {
            Log("Exception: " + ex.message);
        }
 
		function DisableMultitouch(){ //Disabling multitouch when leaving the page
			try{
				SiteKiosk.WindowList.ActiveWindow.SiteKioskWindow.MultitouchEnabled = false;
			}
			catch(ex) {
				Log("Exception: " + ex.message);       
			}
		}  
 
		//Using only jquery, hammer.js and javascript from here on
        var rotation = 1, last_rotation,
            scale=1, last_scale, posX = 0, posY = 0;
 
        $(document).ready(function () {
            $('html').on("contextmenu", function (ev) { ev.preventDefault(); }).
            on("click", function (e) { Log("x: " + e.clientX + " y: "+ e.clientY + " " + document.elementFromPoint(e.clientX,e.clientY))});
             
            $('#testimg').hammer().on("touch", function (ev) {
                last_rotation = rotation;
                last_scale = scale;
            }).on("transform", function (ev) {
                rotation = last_rotation + ev.gesture.rotation;
                scale = Math.max(1, Math.min(last_scale * ev.gesture.scale, 10));
                $('#testimg').css("transform", "translate3d(" + posX + "px," + posY + "px,0) rotate(" + rotation + "deg) scale(" + scale + ")");
            }).on("pinch", function (ev) {
                //add code for pinch if desired
            }).on("drag", function (ev) {
                posX = ev.gesture.deltaX;
                posY = ev.gesture.deltaY;
                $('#testimg').css("transform", "translate3d(" + posX + "px," + posY + "px,0) rotate(" + rotation + "deg) scale(" + scale + ")");
            });
        });
    </script>
    <style type="text/css">
        #testimg
        {
            display: inline-block;
            width: 595px;
            height: 838px;
            margin-top: 25px;
            margin-left: 25px;
            background-image: url(sitekiosk.png);
        }
         
        body
        {
            overflow: hidden;
            text-align: center;
            font-family: Arial;
            font-size: 10px;
        }
    </style>
</head>
<body onunload="DisableMultitouch()">
    <div>This SiteKiosk multitouch test page requires SiteKiosk 8.8 or higher. The page uses SiteKiosk Object Model, jquery and hammer.js. Please have a look at the accompanying <a href="http://devblog.provisio.com/post/2013/12/13/Using-Multitouch-Gestures-in-SiteKiosk.aspx" target="_blank">PROVISIO Developer blog article.</a></div>
    <div id="testimg"></div>
</body>
</html>

The page can be accessed under http://www.provisio.com/download/beta/test/sk_multitouch_test/skmultitouchtest.html and added to SiteKiosk as the start page to test it. What you get will look like this: