Reporting Installation Result in Active Directory

Home
Up
Software
Articles

Reporting Installation Result in Active Directory Deployment

One of the major drawbacks of deploying by GPO is complete lack of any centralized reporting. After the deployment, there are two ways to find out if it was successful – by looking into event log, and by looking into the log of the installation itself, provided that it was enabled by group policy. Obviously, this is a major drawback.

Deployment systems like SMS provide reporting by means of their agent deployed at each workstation. The agent launches the installation, watches it, and then reports return code to the central server where it can be then analyzed.

There is however another way to provide the reporting – by inserting custom actions in the installation script. In this article, we will show how to build such reporting system using transform applied to the installation package

The actions will be reporting state of the installation to our database. We will need 3 actions – one in the beginning will be reporting installation start; two in the end will be reporting installation success or failure.

For starters, we will need the database table to report to. In this article, we will be using SQL Server, but of course it can be any database – just the matter of connection string.

CREATE TABLE [dbo].[_GPOInstallations]

(id] [int] IDENTITY (1, 1) NOT NULL ,

            [machine] [varchar] (50) NOT NULL ,

            [username] [varchar] (50) NOT NULL ,

            [product] [varchar] (50) NOT NULL ,

            [version] [varchar] (50) NOT NULL ,

            [started] [datetime] NULL ,

            [finished] [datetime] NULL ,

            [commited] [bit] NULL ,

            [rolledback] [bit] NULL ,

            [ResultingState] [tinyint] NULL

)

Here’s the plan. Our first custom action will create new record in the database; we will get back newly created record id and store it in a property. In the end of deferred execution, we will place two more custom actions – one will run in case of commit, reporting success, another in case of rollback, reporting the failure.

 Here’s the code in vbscript of the whole script. 

function dbRegStart()
  On Error Resume Next
  If Session.Property("REMOVE") = "ALL" Then
    State = 0
  else
    State = 1
  end if
  Set cn=createobject("adodb.connection")
  cn.open "Provider=SQLOLEDB;Integrated Security=SSPI;Initial Catalog=MYDB;" & _
      "Data Source=MYSERVER"
  ProductName = Session.Property("ProductName")
  ProductVersion = Session.Property("ProductVersion")
 
  Set rs= cn.execute("insert into _GPOInstallations(product,version,Started, ResultingState) " &  _
     "  ; select " & ProductName & "','" & ProductVersion & "',getdate(), " & state & _
      " ; select scope_identity()")
  Set rs=rs.nextrecordset
  NewId=cstr(rs(0))
  rs.close
  cn.close
  set cn=nothing
  Session.Property("DBNewID") = NewId
  Session.Property("DBRegCommit") = NewId
  Session.Property("DBRegRollback") = NewId
end function
 
Function DBRegCommit()
  On Error Resume Next
  NewId = Session.Property("CustomActionData")
  If isnumeric(NewId) Then
    Set cn=createobject("adodb.connection")
    cn.open "Provider=SQLOLEDB;Integrated Security=SSPI;Initial Catalog=MYDB;" & _
         "Data Source=MYSERVER"
    cn.execute "update _GPOInstallations set Finished=getdate(), commited=1 where id=" & newid
    cn.close
    Set cn=Nothing
  End If
end function
 
Function DBRegRollback()
  On Error Resume Next
  NewId = Session.Property("CustomActionData")
  If isnumeric(NewId) Then
      Set cn=createobject("adodb.connection")
      cn.open "Provider=SQLOLEDB;Integrated Security=SSPI;Initial Catalog=MYDB;" &  _
          "Data Source=MYSERVER"
      If Session.Property("REMOVE") = "ALL" Then
        State = 0
      else
        State = 1
      End If
      cn.execute "update _GPOInstallations set Finished=getdate(), rolledback=1 " & _
            "where id=" & Session.Property("CustomActionData")
      cn.close
      Set cn=Nothing
  End If
end function 

The first function, dbRegStart, will be called in the beginning of the execute sequence; functions dbRegCommit and dbRegRollback in the end of the deferred execution - because only then it becomes known whether the installation was committed or rolled back.

Here’s how to insert custom actions in ORCA.

First, we save the text of the above vbscript in a text file, for example c:\dbReg.vbs.

We open the original MSI, and start new transform; we then go to the table Binary, and add new row; give it any name, for instance, dbreg1. Then focus the row “Data” and specify filename of the saved script, c:\dbreg.vbs . ORCA will read the file contents into the table.

Now we go to the table CustomAction. Here, we create three custom actions:

All 3 refer in the column Source to the Name we gave in the Binary table; type 6 indicated regular custom action; type 1542 and 1286 respectively specify execution on Commit and on Rollback in the deferred phase. Column Target points to the respective function within our vbscript.

Finally, we insert out custom actions into the right places in the script.

Assuming that the very first action in the original execute sequence had sequence number 100, we place “DBRegStart” before it, i.e. 90; we place DBRegCommit and DBRegRollback right before InstallFinalize.

Then we generate new transform in ORCA, and apply it to the original MSI when deploying (tab  “Modifications” in the package dialog in the group policy). Once the package is installed or uninstalled, new record will appear in our database with the name of the machine, product, version, and result of the installation. Using trivial SQL query against the database, it’s then easy to spot workstations where the installation has failed:

Select machine from _gpoinstallations

Where

Product = ‘MyProduct’ and version = ‘1.0.0’

And isnull(rolledback,0) = 0

Home

This site was last updated 12/31/12