Category Archives: Programming

Two ways to check if a Registry Key exists using VBScript

The first one is using the method RegRead from WScript.Shell.

If the given key is not found, it will rise an error, so we need to use an On Error Resume Next (which I don’t really like).

We would need to pass to the function a string like HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\ (note the trailing \) if we are looking for a Registry Key (those that look like a folder). If we want to check if a value inside a key exists, we would remove the trailing \, like HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3\CurrentLevel.

Function RegKeyExists(Key)
  Dim oShell, entry
  On Error Resume Next
 
  Set oShell = CreateObject("WScript.Shell")
  entry = oShell.RegRead(Key)
  If Err.Number <> 0 Then
    Err.Clear
    RegKeyExists = False
  Else
    Err.Clear
    RegKeyExists = True
  End If
End Function

The second method uses WMI.

In this case, we would need to pass the Key Hive (Current User, Local Machine, etc) in the form of hex numbers (I declared them as constants). The KeyPath would be something like SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings.

Const HKCR = &H80000000 'HKEY_CLASSES_ROOT
Const HKCU = &H80000001 'HKEY_CURRENT_USER
Const HKLM = &H80000002 'HKEY_LOCAL_MACHINE
Const HKUS = &H80000003 'HKEY_USERS
Const HKCC = &H80000005 'HKEY_CURRENT_CONFIG
 
Function KeyExists(Key, KeyPath)
  Dim oReg: Set oReg = GetObject("winmgmts:!root/default:StdRegProv")
  If oReg.EnumKey(Key, KeyPath, arrSubKeys) = 0 Then
    KeyExists = True
  Else
    KeyExists = False
  EndIf
EndFunction

The difference with this function is that will only check for Registry Keys and not for values.

Change timezone on PHP

There are some methods that allows you to change the timezone of the PHP (5.1+) scripts (ie, when the date is not shown due to a different timezone of the server).

The first one is by modifying the php.ini file of the web server (if you are allowed to). We just need to add the following line:

date.timezone = "America/Lima"

Other method is using the ini_set() function directly on your script (at the beginning of it), this way:

ini_set('date.timezone', 'America/Lima');

And the third method consist on the use of the function date_default_timezone_set() (also, directly on your script):

date_default_timezone_set('America/Lima');

The list of the available timezones is here.

Sources: SiteGround, The Electric Toolbox

Remove duplicated whitespaces on C#

The Trim method on C# only removes whitespaces at the beginning and at the end of a string, but it does not remote duplicated whitespaces inside the string (like the Trim function on VB for Apps), which is very handy sometimes.

One of the ways to do it on C#, is using Regular Expressions. This method will not only remove whitespaces but also tabs and line breaks, and will replace them with one whitespace.

string s1 = "He saw   a cute\tdog.\nThere\n\twas another sentence.";
Regex r = new Regex(@"\s+");
string s2 = r.Replace(s1, @" ");
// The result would be: He saw a cute dog. There was another sentence.

You will need to add the reference to System.Text.RegularExpressions to your namespace.
Source: Dot Net Perls

Concatenate text on NVelocity

There is no operator to concatenate two strings in NVelocity (the .Net version of Velocity) like we can do on other languages like C# or PHP, with the plus (+) operator for the first one and dot (.) for the second one. For example, in C# we would do:

string strHello = "Hello " + "World";

And in PHP:

$hello = "Hello " . "World";

But in NVelocity, what we must do if we need to do this same thing would be:

#set ($str1 = "Hello ")
#set ($str2 = "World")
The concatenated string would be: $str1$str2

Source: Velocity User Guide

Call a WebService from VBScript

While I was writing some code on VBScript to avoid manual tasks that we currently do with a bunch of files, I needed to automatically upload some information extracted from all these files to a SQL database. One way to do it is using a Web Service that receives the data and store it into the database.

Our Web Service is able to receive the following protocols: SOAP 1.1, SOAP 1.2 and HTTP POST. For simplicity, we are going to use HTTP POST, which receive the parameters in the query string format (param1=value1&param2=value2&…). In the other protocols (SOAP) we would need to send the parameters in a XML way (which is more powerful but a little more extensive to implement).

The expected HTTP request will be:

POST /WebService.asmx/WebMethod HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: length

param=string

And the response (in XML format):

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://tempuri.org/">string</string>

So, to call the Web Service directly from the VBScript, we can use the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
'The object that will make the call to the WS
Set oXMLHTTP = CreateObject("Microsoft.XMLHTTP")
'The object that will receive the answer from the WS
Set oXMLDoc = CreateObject("Microsoft.XMLDOM")
 
strParam = "string to pass"
 
'Tell the name of the subroutine that will handle the response
oXMLHTTP.onreadystatechange = getRef("HandleStateChange")
'Initializes the request (the last parameter, False in this case, tells if the call is asynchronous or not
oXMLHTTP.open "POST", "http://localhost/WebService.asmx/WebMethod", False
'This is the content type that is expected by the WS using the HTTP POST protocol
oXMLHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
 
'Now we send the request to the WS
oXMLHTTP.send "parameter=" & strParam
 
Sub HandleStateChange()
	Dim szResponse
	'When the call has been completed (ready state 4)
	If oXMLHTTP.readyState = 4 Then
		szResponse = oXMLHTTP.responseText
		oXMLDoc.loadXML szResponse
		'If the WS response is not in XML format, there is a problem
		If oXMLDoc.parseError.errorCode <> 0 Then
			WScript.Echo "ERROR:"
			WScript.Echo oXMLHTTP.responseText
			WScript.Echo oXMLDoc.parseError.reason
		Else
			WScript.Echo "Result: " & oXMLDoc.getElementsByTagName("string")(0).childNodes(0).Text
		End If
	End If
End Sub

The ready state tells us about the connection with the Web Service:

  • 0: Uninitialized – open() has not been called yet.
  • 1: Loading – send() has not been called yet.
  • 2: Loaded – send() has been called, headers and status are available.
  • 3: Interactive – Downloading, responseText holds the partial data.
  • 4: Completed – Finished with all operations.

Convert a String to a Stream

In C#, to convert a String into a Stream object, we need to use the GetBytes method (from the Encoding.ASCII package), this way:

byte[] bytes = Encoding.ASCII.GetBytes(xmlContent);

And then, use that byte array when instantiate a Stream (for example, MemoryStream or FileStream):

MemoryStream stream = new MemoryStream(bytes);

Convertir un IList en un Array

Existen algunas formas de hacerlo, acá les dejo un par.

Primera forma:

//list es del tipo IList
ArrayList arr = new ArrayList(list);
Item[] items = (Item[])arr.ToArray(typeof(Item));

Otra forma:

Item[] items = new Item[list.Count];
list.CopyTo(items, 0);

SQL Server’s nvarchar(max) on Castle ActiveRecord

I’m using the new SQL Server 2005’s data type nvarchar(max) on a .Net project (ntext has been deprecated in this version) in conjuction with Castle ActiveRecord. For a complete integration (including schema creation), ActiveRecord property should looks like this:

[Property("description", ColumnType = "StringClob", SqlType = "nvarchar(MAX)")]

ColumnType = “StringClob” avoids text to be truncated if it gets too long. SqlType = “nvarchar(MAX)” forces the field to be created as that data type, otherwise, it will be created as nvarchar(255).

A more detailed explanation can be found here and here.

Diferencia entre ICollection e IList en C#

Los elementos dentro de un ICollection (para ser más exactos, los elementos dentro de una clase que implemente una interfaz ICollection) no tienen un orden específico. En un momento pueden estar ordenados de una manera, y en otro, sin alguna razón aparente, ordenados de otra forma.

En cambio, los elementos de un IList si tienen un orden establecido y relevante, como un arreglo. Esto permite agregar elementos en una ubicación específica. Además, los elementos van a permanecer en la posición asignada hasta que decidamos moverlos.

Además de estas dos interfaces, existe también IDictionary, que exitiende a ICollection. Este permite almacenar parejas de elementos (clave, valor), similar a como lo hace un diccionario de palabras (cada palabra tiene un significado). Al igual que en el ICollection, estos elementos no tienen un orden específico.