Tuesday, January 13, 2009

Script Code: Bridging Another Divide

One of the issues I had to address at a previous job was to combine a few features which required using multiple scripting "tools" to accomplish. For example, a logon script that scans for some particular condition, and then opens a web page to alert the user, while simultaneously recording the event somewhere and alerting the IT department. Yes, there are retail products that do this, but it's actually quite simple to do for FREE using tools you already have on hand or can get easily.

This example illustrates a simplified form of a system I built and supported years ago at a former employer. This uses a logon script to do various things (in KiXtart), and would launch a web browser to alert the user if a particular condition was encountered. The URL was to an intranet ASP page that performed additional tasks. The intent of this example is to leverage what works in each toolset, rather than trying to make a hammer out of a screwdriver. You can do this with almost any mix of language tools obviously. This example uses KiXtart 4.6 with ASP and ADO along with a server-side database (MS SQL 2005 in this example).

Logon Script (KiXtart) - Note: I imposed some VBScript-like variables to help non-Kix folks understand the code better. There are no explicit "True", "False", or "Nothing" constant objects in KiXtart like there are in VBScript, so I define those for a little clarity. You don't need to do that of course. You could use the numbers 0 and 1 instead.

;------------------------------------------------------------------
; function.....: OpenWebPage()
; description..: use IE to open specified URL visible or hidden
; arguments....: URL-string, boolean-show
; returns......: nothing
; example......: $=OpenWebPage("http://www.msn.com", 1, $hgt, $wid, $fixed-window)
;------------------------------------------------------------------
Function OpenWebPage($url, $show, Optional $height, $width, $fixed)
    $True = 1
    $False = 0
    $Nothing = 0
    If $url <> ""
        $ie = CreateObject("InternetExplorer.Application")
        If $ie <> $False and @ERROR = 0
            ; opening visible web page in internet explorer
            $ie.Navigate($url)
            If $show = $True
                If $height > 0
                    $ie.Height = $height
                EndIf
                If $width > 0
                    $ie.Width = $width
                EndIf
                If $fixed = $True
                    $ie.Resizable = $False
                    $ie.StatusBar = $False
                    $ie.Toolbar = $False
                EndIf
                $ie.Visible = $True
                Sleep 1
            Else
                ; opening silent web page in internet explorer
                Sleep 1
                $ie.Quit
                $ie = $Nothing
            EndIf
        Else
            ; error - unable to launch internet explorer object
        EndIf
    Else
        ; error - no url was specified to open
    EndIf
EndFunction

; now we would have some code to check for something and set a variable
; such as $someCondition to 1 if the result is positive or true.
; In this example, I will check to see if the current user has admin rights:

If @ADMIN = 1
    $someCondition = 1
EndIf

; next, we would check to see if the variable was set to 1 and open
; the desired web page to show an alert using a fixed-size IE window

If $someCondition = 1
    $result = "true"
    $showForm = 1
Else
    $result = "false"
    $showForm = 0
EndIf
$weblink = "http://intranet/is/services/alertpage.asp?report=admin&result=$result&userid=@userid&client=@wksta"
$=OpenWebPage($weblink, $showForm, 300, 500, 1)

Next comes the ASP web page source code. This example will check the incoming QueryString parameter values and perform some sort of action based on those values. QueryString values in ASP are simply the web address (URL) string values following a question mark "?". Any string information which trails a question is parsed into paired items using the ampersand "&" character. Note that there are KiXtart macros embedded into the $weblink string. The @userid macro will automatically substitute the sAMAccountName username value, such as "davestein", while the @wksta macro will substitute the computer NetBIOS name, such as "DesktopPC1".

Using the $weblink value above, the QueryString value would be:

"report=admin&result=true&userid=davestein&client=DesktopPC1"

Furthermore, this string is automatically parsed by ASP using each ampersand to generate an array containing (variablename, value) pairs. But you fetch them by name, so it's very simple to fetch and read them as you would with passed form values:

reportType = Trim(Request.QueryString("report"))
resultValue = Trim(Request.QueryString("result"))
username = Trim(Request.QueryString("userid"))
computerName = Trim(Request.QueryString("client"))

To illustrate this, we can display the value assigned to the userName variable:

Response.Write "username is " & userName

Which would show "username is davestein"

Because ASP is typically written with VBScript, it can do most of what Windows Scripting Host allows it to do (except for some things like WMI queries and registry manipulation). It can invoke COM interfaces very well, which is a common use for ASP. In this case, I will pass the information into a remote MS SQL Server database table, and then display something in the web page to the user.

To invoke a COM interface, you often find it helpful to import or define a list of constant variables to simplify things. You can "include" or simply define them within the ASP page. There are arguments for and against using includes like adovbs.inc. In this example I will define the constants for simplicity, which appear in purple:

reportType = Trim(Request.QueryString("report"))
resultValue = Trim(Request.QueryString("result"))
username = Trim(Request.QueryString("userid"))
computerName = Trim(Request.QueryString("client"))

If resultValue = "true" Then
    isAdmin = 1
Else
    isAdmin = 0
End If

Const adOpenDynamic = 2
Const adLockOptimistic = 3
Const adCmdTable = &H0002

Const dsn = "driver=SQL Server;server=SQL1;database=ITstuff;uid=User1;pwd=P@ssW0rd1;"

Set objRS = Server.CreateObject("ADODB.Recordset")

On Error Resume Next
objRS.Open "pcAdmins", dsn, adOpenDynamic, adLockOptimistic, adCmdTable

If err.Number <> 0 Then
    objRS.Close
    Set objRS = Nothing
    Response.Write "Error (" & err.Number & "): " & err.Description
    err.Clear
    Response.End
End If

objRS.AddNew
objRS.Fields("computer").Value = computerName
objRS.Fields("username").Value = userName
objRS.Fields("isAdmin").Value = isAdmin
objRS.Fields("dateReported").Value = Now
objRS.Update
objRS.Close
Set objRS = Nothing

Below this code, you could enter some HTML code to display a formatted message. You could also invoke the CDOSys object, to prepare and send an SMTP email message if you want to. There are no rules here. Whatever works for you is fine.

Again, this is just one example of the kinds of things you can do by gluing together parts from different scripting languages. To me, this is all like a big Lego kit.

No comments: