Welcome Back Everyone!
Sorry the post is so late in the evening it has been a more hectic day than usual
We're now jumping into our Composite Level 1 HTC
So without further adieu the code
- Code: Select all
<html xmlns:Ryan>
<?import namespace="Ryan" implementation="ProgressBar.htc">
<public:component tagname="ProgressLineItem">
<Public:method name="Install" />
<public:event name="onInstalled" id="InstalledEventID" />
<public:property name="InstallTitle" put="PutTitle" get="GetTitle" />
<public:property name="InstallValue" put="PutValue" get="GetValue"/>
<public:property name="InstallPath" Put="PutPath" get="GetPath"/>
<public:property name="ProgressLineItemWidth" />
</public:component>
<script language="vbscript" type="text/vbscript">
'----------------------Component HTML objects----------------------
On Error Resume Next
Dim CheckBoxElement
Dim AnimationElement
Dim TextElement
'----------------------Component variables-------------------------
Dim path
Dim CheckInstallationTimerID
Dim Killed
'-----------------------Component "Constructor"-----------------------
Sub InitializeComponent()
Set CheckBoxElement = document.CreateElement("<input type=""checkbox"" id=""CheckBoxElement"" style="" position: absolute; Left: 5px; top: 0px;font-family: verdana; "">")
Set TextElement = document.CreateElement("<input type=""text"" id=""TextElement"" readonly=""readonly"" style="" position : absolute; Left : 25px; top: 1px; width : " + ProgressLineItemWidth + "px" + "; font-size : 9pt; font-family: verdana; border-top-style: none; border-Right-style: none; border-Left-style: none; border-bottom-style: none; color : black"">")
Set AnimationElement = document.CreateElement("<Ryan:ProgressBar id=""AnimationElement"" style=""position: absolute; Left : 25px; top : 1px; width : " + ProgressLineItemWidth + "px" + "; visibility : hidden;""></Ryan:ProgressBar>")
Element.AppendChild(AnimationElement)
Element.AppendChild(CheckBoxElement)
Element.AppendChild(TextElement)
AnimationElement.Speed = 50
CheckBoxElement.AttachEvent "onclick", GetRef("SuppressClicks")
CheckBoxElement.AttachEvent "ondblclick", GetRef("ForceEnd")
Killed = False
End Sub
'---------------Exposed Methods---------------
Sub Install()
If RegistryItemExists("HKLM\SOFTWARE\LM_AMI\" + Split(path,"\")(UBound(Split(path,"\")) - 1) + "\") Then CreateObject("WScript.Shell").RegDelete("HKLM\SOFTWARE\LM_AMI\" + Split(path,"\")(UBound(Split(path,"\")) - 1) + "\") 'If there is already info In the applications hive delete the hive
TextElement.style.pixelleft = TextElement.style.pixelleft + TextElement.style.pixelwidth
AnimationElement.style.visibility = "visible"
SwapTextColors()
AnimationElement.Animate()
StartInstallationMonitor()
CheckAndLaunchScript(Path)
End Sub
'----------------Internal Methods----------------
Function RegistryItemExists(RegistryItem)
On Error Resume Next 'Disable Error handling
CreateObject("WScript.Shell").RegRead RegistryItem 'Try And read In the value
RegistryItemExists = (Err = 0) 'The key exists If we get back a 0
If ((Err = &H80070002) And (Right(RegistryItem, 1) = "\")) Then 'Check To see If we get a specific Error back And the value passed In was a key Not a value
TheErrDescription = Replace(Err.description, RegistryItem, "") 'Get the description
Err.Clear() 'Clear the old Error
CreateObject("WScript.Shell").RegRead "HKEY_ERROR\" 'Read In from the Error key
RegistryItemExists = (TheErrDescription <> Replace(Err.description, "HKEY_ERROR\", "")) 'Check against the Error key And our original errpr description
End If
End Function 'Function RegistryItemExists(RegistryItem)
Function Shr(Num, X)
If X >= 32 Then Exit Function 'If we try To shift Right more than 32 Exit the Function
If X = 0 Then Shr = Num : Exit Function 'If we try To shift Right 0 times return the Num passed In And Exit the Function
Shr = (((Num And &H7FFFFFFF) And (Not (Pwr2(X) - 1))) \ Pwr2(X)) Or (Num < 0) And Pwr2(31 - X)
End Function 'Function Shr(Num, X)
Function Pwr2(Exponent)
Dim Res(31) 'Local variable declarations
Dim Counter
If Exponent < 0 Or Exponent > 31 Then Err.Raise 5 'If we don't have an acceptable range of exponent raise an Error
If Res(0) = 0 Then 'If we are starting With zero
Res(0) = 1 'Set the first number To 1
For Counter = 1 To 30 'Count To 30
Res(Counter) = Res(Counter - 1) * 2 'Set up the numbers
Next
Res(31) = &H80000000 'Create the final binary value
End If
Pwr2 = Res(Exponent) 'Return the value of the exponent
End Function ' Function Power2(Exponent)
Sub CheckAndLaunchScript(Script)
Dim CRCTable
Dim CaculatedCRC
Dim Temp
Dim fso
Dim File
Dim FileName
Dim Character
CRCTable = _
Split("&h0,&h77073096,&hEE0E612C,&h990951BA,&h076DC419,&h706AF48F,&hE963A535,&h9E6495A3,&h0EDB8832,&h79DCB8A4," + _
"&hE0D5E91E,&h97D2D988,&h09B64C2B,&h7EB17CBD,&hE7B82D07,&h90BF1D91,&h1DB71064,&h6AB020F2,&hF3B97148," + _
"&h84BE41DE,&h1ADAD47D,&h6DDDE4EB,&hF4D4B551,&h83D385C7,&h136C9856,&h646BA8C0,&hFD62F97A,&h8A65C9EC," + _
"&h14015C4F,&h63066CD9,&hFA0F3D63,&h8D080DF5,&h3B6E20C8,&h4C69105E,&hD56041E4,&hA2677172,&h3C03E4D1," + _
"&h4B04D447,&hD20D85FD,&hA50AB56B,&h35B5A8FA,&h42B2986C,&hDBBBC9D6,&hACBCF940,&h32D86CE3,&h45DF5C75," + _
"&hDCD60DCF,&hABD13D59,&h26D930AC,&h51DE003A,&hC8D75180,&hBFD06116,&h21B4F4B5,&h56B3C423,&hCFBA9599," + _
"&hB8BDA50F,&h2802B89E,&h5F058808,&hC60CD9B2,&hB10BE924,&h2F6F7C87,&h58684C11,&hC1611DAB,&hB6662D3D," + _
"&h76DC4190,&h01DB7106,&h98D220BC,&hEFD5102A,&h71B18589,&h06B6B51F,&h9FBFE4A5,&hE8B8D433,&h7807C9A2," + _
"&h0F00F934,&h9609A88E,&hE10E9818,&h7F6A0DBB,&h086D3D2D,&h91646C97,&hE6635C01,&h6B6B51F4,&h1C6C6162," + _
"&h856530D8,&hF262004E,&h6C0695ED,&h1B01A57B,&h8208F4C1,&hF50FC457,&h65B0D9C6,&h12B7E950,&h8BBEB8EA," + _
"&hFCB9887C,&h62DD1DDF,&h15DA2D49,&h8CD37CF3,&hFBD44C65,&h4DB26158,&h3AB551CE,&hA3BC0074,&hD4BB30E2," + _
"&h4ADFA541,&h3DD895D7,&hA4D1C46D,&hD3D6F4FB,&h4369E96A,&h346ED9FC,&hAD678846,&hDA60B8D0,&h44042D73," + _
"&h33031DE5,&hAA0A4C5F,&hDD0D7CC9,&h5005713C,&h270241AA,&hBE0B1010,&hC90C2086,&h5768B525,&h206F85B3," + _
"&hB966D409,&hCE61E49F,&h5EDEF90E,&h29D9C998,&hB0D09822,&hC7D7A8B4,&h59B33D17,&h2EB40D81,&hB7BD5C3B," + _
"&hC0BA6CAD,&hEDB88320,&h9ABFB3B6,&h03B6E20C,&h74B1D29A,&hEAD54739,&h9DD277AF,&h04DB2615,&h73DC1683," + _
"&hE3630B12,&h94643B84,&h0D6D6A3E,&h7A6A5AA8,&hE40ECF0B,&h9309FF9D,&h0A00AE27,&h7D079EB1,&hF00F9344," + _
"&h8708A3D2,&h1E01F268,&h6906C2FE,&hF762575D,&h806567CB,&h196C3671,&h6E6B06E7,&hFED41B76,&h89D32BE0," + _
"&h10DA7A5A,&h67DD4ACC,&hF9B9DF6F,&h8EBEEFF9,&h17B7BE43,&h60B08ED5,&hD6D6A3E8,&hA1D1937E,&h38D8C2C4," + _
"&h4FDFF252,&hD1BB67F1,&hA6BC5767,&h3FB506DD,&h48B2364B,&hD80D2BDA,&hAF0A1B4C,&h36034AF6,&h41047A60," + _
"&hDF60EFC3,&hA867DF55,&h316E8EEF,&h4669BE79,&hCB61B38C,&hBC66831A,&h256FD2A0,&h5268E236,&hCC0C7795," + _
"&hBB0B4703,&h220216B9,&h5505262F,&hC5BA3BBE,&hB2BD0B28,&h2BB45A92,&h5CB36A04,&hC2D7FFA7,&hB5D0CF31," + _
"&h2CD99E8B,&h5BDEAE1D,&h9B64C2B0,&hEC63F226,&h756AA39C,&h026D930A,&h9C0906A9,&hEB0E363F,&h72076785," + _
"&h05005713,&h95BF4A82,&hE2B87A14,&h7BB12BAE,&h0CB61B38,&h92D28E9B,&hE5D5BE0D,&h7CDCEFB7,&h0BDBDF21," + _
"&h86D3D2D4,&hF1D4E242,&h68DDB3F8,&h1FDA836E,&h81BE16CD,&hF6B9265B,&h6FB077E1,&h18B74777,&h88085AE6," + _
"&hFF0F6A70,&h66063BCA,&h11010B5C,&h8F659EFF,&hF862AE69,&h616BFFD3,&h166CCF45,&hA00AE278,&hD70DD2EE," + _
"&h4E048354,&h3903B3C2,&hA7672661,&hD06016F7,&h4969474D,&h3E6E77DB,&hAED16A4A,&hD9D65ADC,&h40DF0B66," + _
"&h37D83BF0,&hA9BCAE53,&hDEBB9EC5,&h47B2CF7F,&h30B5FFE9,&hBDBDF21C,&hCABAC28A,&h53B39330,&h24B4A3A6," + _
"&hBAD03605,&hCDD70693,&h54DE5729,&h23D967BF,&hB3667A2E,&hC4614AB8,&h5D681B02,&h2A6F2B94,&hB40BBE37," + _
"&hC30C8EA1,&h5A05DF1B,&h2D02EF8D",",")
CaculatedCRC = &hFFFFFFFF
Set fso = CreateObject( "Scripting.FileSystemObject" )
If Not fso.FileExists(Script) Then .RegWrite "HKLM\SOFTWARE\LM_AMI\" + Right(Script,Len(Script) - InStrRev(Script,"\")) + "\ReturnCode", -9, "REG_DWORD" : Exit Sub
Set File = fso.OpenTextFile( Script, 1, False )
While Not File.AtEndOfStream
CaculatedCRC = CRCTable((Asc(File.Read(1))) Xor (CaculatedCRC And &HFF)) Xor Shr( CaculatedCRC, 8 ) 'Adjust the CRC For Each character
Wend
CreateObject("WScript.Shell").Run Chr(34) + Script + Chr(34) + " /SelfValidate:" + CStr(CaculatedCRC Xor &hFFFFFFFF),1,False
End Sub
Sub SwapTextColors() : If TextElement.style.Color = "black" Then : TextElement.style.color = "red" : Else : TextElement.style.color = "black" : End If : End Sub
Sub StartInstallationMonitor() : CheckInstallationTimerID = window.setinterval(GetRef("CheckInstallation"),50) : End Sub
Sub StopInstallationMonitor() : window.clearInterval(CheckInstallationTimerID) : End Sub
Sub CheckInstallation() : If RegistryItemExists("HKLM\SOFTWARE\LM_AMI\" + Split(path,"\")(UBound(Split(path,"\")) - 1) + "\ReturnCode") Then FireInstalled(CreateObject("WScript.Shell").RegRead("HKLM\SOFTWARE\LM_AMI\" + Split(path,"\")(UBound(Split(path,"\")) - 1) + "\ReturnCode")) : End If : End Sub
Sub KillProcess(ProcessName)
On Error Resume Next
For Each objProcess In GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2").ExecQuery("Select * FROM Win32_Process WHERE CommandLine LIKE '%" + processName + "%'")
objProcess.Terminate()
Next
End Sub
'-----------------------Internal Event Handlers-----------------------
Sub SuppressClicks() : CheckBoxElement.checked = Not CheckBoxElement.checked : End Sub
Sub ForceEnd()
If Not Killed then
KillProcess("setup.vbs"" /SelfValidate:")
FireInstalled(-99)
End If
End Sub
'--------------------Event Firing Methods--------------------
Sub FireInstalled(OutReturnCode)
StopInstallationMonitor()
If OutReturnCode = 3010 Or OutReturnCode = 0 Then CheckBoxElement.Checked = True
AnimationElement.StopAnimation()
TextElement.style.pixelleft = TextElement.style.pixelleft - TextElement.style.pixelwidth
AnimationElement.style.visibility = "hidden"
If OutReturnCode = 3010 or OutReturnCode = 0 Then SwapTextColors()
Dim InstalledEventObject
Set InstalledEventObject = window.document.CreateEventObject()
InstalledEventObject.ReturnValue = OutReturnCode
Killed = True
InstalledEventID.Fire(InstalledEventObject)
End Sub
'----------------------Property Put's & Get's-----------------------
Sub PutTitle(InTitle) : TextElement.title = InTitle : End Sub
Function GetTitle() : GetTitle = TextElement.title : End Function
Sub PutValue(InValue) : TextElement.value = InValue : End Sub
Function GetValue() : GetValue = TextElement.Value : End Function
Sub PutPath(InPath) : Path = InPath : End Sub
Function GetPath() : GetPath = Path : End Function
InitializeComponent()
</script>
</html>
185 lines for us to analyze this evening
So let’s start with our Declaration Section
- Code: Select all
<html xmlns:Ryan>
<?import namespace="Ryan" implementation="ProgressBar.htc">
<public:component tagname="ProgressLineItem">
<Public:method name="Install" />
<public:event name="onInstalled" id="InstalledEventID" />
<public:property name="InstallTitle" put="PutTitle" get="GetTitle" />
<public:property name="InstallValue" put="PutValue" get="GetValue"/>
<public:property name="InstallPath" Put="PutPath" get="GetPath"/>
<public:property name="ProgressLineItemWidth" />
</public:component>
Ok we're back to using Composite HTCs so we have our standard xmlns being set we are importing our required HTC(s) and we have several properties and 1 method and 1 event being exposed to the parent element by this HTC
Next up we have our variables, objects and constants sections
- Code: Select all
'----------------------Component HTML objects----------------------
On Error Resume Next
Dim CheckBoxElement
Dim AnimationElement
Dim TextElement
'----------------------Component variables-------------------------
Dim path
Dim CheckInstallationTimerID
Dim Killed
We will be using a checkbox element a Textbox element and an Animation element (our ProgressBar HTC) in addition we have a variable for the Path a timer ID and a Killed variable
On to the Component Constructor
- Code: Select all
'-----------------------Component "Constructor"-----------------------
Sub InitializeComponent()
Set CheckBoxElement = document.CreateElement("<input type=""checkbox"" id=""CheckBoxElement"" style="" position: absolute; Left: 5px; top: 0px;font-family: verdana; "">")
Set TextElement = document.CreateElement("<input type=""text"" id=""TextElement"" readonly=""readonly"" style="" position : absolute; Left : 25px; top: 1px; width : " + ProgressLineItemWidth + "px" + "; font-size : 9pt; font-family: verdana; border-top-style: none; border-Right-style: none; border-Left-style: none; border-bottom-style: none; color : black"">")
Set AnimationElement = document.CreateElement("<Ryan:ProgressBar id=""AnimationElement"" style=""position: absolute; Left : 25px; top : 1px; width : " + ProgressLineItemWidth + "px" + "; visibility : hidden;""></Ryan:ProgressBar>")
Element.AppendChild(AnimationElement)
Element.AppendChild(CheckBoxElement)
Element.AppendChild(TextElement)
AnimationElement.Speed = 50
CheckBoxElement.AttachEvent "onclick", GetRef("SuppressClicks")
CheckBoxElement.AttachEvent "ondblclick", GetRef("ForceEnd")
Killed = False
End Sub
Fairly standard fan-fare so far we are creating 3 elements and appending them to the HTC you will notice that box the TextElement and AnimationElement have their width property of their style set to the ProgressLineItemWidth property of the HTC also the Animation Element’s visibility is set to hidden to begin. In addition the Checkbox element has both an onclick and ondblclick events wired to two internal event handlers.
Lastly we are setting the Animation Element’s speed property to 50 milliseconds and setting Killed to false
Over to the Exposed Methods Section for our only Exposed Method
- Code: Select all
Sub Install()
If RegistryItemExists("HKLM\SOFTWARE\LM_AMI\" + Split(path,"\")(UBound(Split(path,"\")) - 1) + "\") Then CreateObject("WScript.Shell").RegDelete("HKLM\SOFTWARE\LM_AMI\" + Split(path,"\")(UBound(Split(path,"\")) - 1) + "\") 'If there is already info In the applications hive delete the hive
TextElement.style.pixelleft = TextElement.style.pixelleft + TextElement.style.pixelwidth
AnimationElement.style.visibility = "visible"
SwapTextColors()
AnimationElement.Animate()
StartInstallationMonitor()
CheckAndLaunchScript(Path)
End Sub
The AMI controls its logging and installations through the registry in a common Hive the system first checks to see if the packages hive currently exists and if so it deletes it to start fresh
Then we move the TextElement over so the left side now begins where the right side used to end
Then we turn on the Animation Element’s visibility and call SwapTextColors()
Finally we Call the ProgressBar HTC's Animate() method followed with a call to StartInstallationMonitor() Finally CheckAndLaunchScript()
Now we come to the Internal Methods Section
Quite a lot going on in here for this post
- Code: Select all
Function RegistryItemExists(RegistryItem)
On Error Resume Next 'Disable Error handling
CreateObject("WScript.Shell").RegRead RegistryItem 'Try And read In the value
RegistryItemExists = (Err = 0) 'The key exists If we get back a 0
If ((Err = &H80070002) And (Right(RegistryItem, 1) = "\")) Then 'Check To see If we get a specific Error back And the value passed In was a key Not a value
TheErrDescription = Replace(Err.description, RegistryItem, "") 'Get the description
Err.Clear() 'Clear the old Error
CreateObject("WScript.Shell").RegRead "HKEY_ERROR\" 'Read In from the Error key
RegistryItemExists = (TheErrDescription <> Replace(Err.description, "HKEY_ERROR\", "")) 'Check against the Error key And our original errpr description
End If
End Function 'Function RegistryItemExists(RegistryItem)
This method if you have been following along from a year ago when I first posted about the AMI back when it was in version 1.0 will recognize it from the Package Template VBScript file
Basically this method allows you to verify if a registry key OR value exists in the registry (to search for key end string with \ omit \ to search for a value)
- Code: Select all
Function Shr(Num, X)
If X >= 32 Then Exit Function 'If we try To shift Right more than 32 Exit the Function
If X = 0 Then Shr = Num : Exit Function 'If we try To shift Right 0 times return the Num passed In And Exit the Function
Shr = (((Num And &H7FFFFFFF) And (Not (Pwr2(X) - 1))) \ Pwr2(X)) Or (Num < 0) And Pwr2(31 - X)
End Function 'Function Shr(Num, X)
This little method emulates the >> (Shift Right) operator of languages like C++
- Code: Select all
Function Pwr2(Exponent)
Dim Res(31) 'Local variable declarations
Dim Counter
If Exponent < 0 Or Exponent > 31 Then Err.Raise 5 'If we don't have an acceptable range of exponent raise an Error
If Res(0) = 0 Then 'If we are starting With zero
Res(0) = 1 'Set the first number To 1
For Counter = 1 To 30 'Count To 30
Res(Counter) = Res(Counter - 1) * 2 'Set up the numbers
Next
Res(31) = &H80000000 'Create the final binary value
End If
Pwr2 = Res(Exponent) 'Return the value of the exponent
End Function ' Function Power2(Exponent)
This method raises an Exponent by the Power of 2
- Code: Select all
Sub CheckAndLaunchScript(Script)
Dim CRCTable
Dim CaculatedCRC
Dim Temp
Dim fso
Dim File
Dim FileName
Dim Character
CRCTable = _
Split("&h0,&h77073096,&hEE0E612C,&h990951BA,&h076DC419,&h706AF48F,&hE963A535,&h9E6495A3,&h0EDB8832,&h79DCB8A4," + _
"&hE0D5E91E,&h97D2D988,&h09B64C2B,&h7EB17CBD,&hE7B82D07,&h90BF1D91,&h1DB71064,&h6AB020F2,&hF3B97148," + _
"&h84BE41DE,&h1ADAD47D,&h6DDDE4EB,&hF4D4B551,&h83D385C7,&h136C9856,&h646BA8C0,&hFD62F97A,&h8A65C9EC," + _
"&h14015C4F,&h63066CD9,&hFA0F3D63,&h8D080DF5,&h3B6E20C8,&h4C69105E,&hD56041E4,&hA2677172,&h3C03E4D1," + _
"&h4B04D447,&hD20D85FD,&hA50AB56B,&h35B5A8FA,&h42B2986C,&hDBBBC9D6,&hACBCF940,&h32D86CE3,&h45DF5C75," + _
"&hDCD60DCF,&hABD13D59,&h26D930AC,&h51DE003A,&hC8D75180,&hBFD06116,&h21B4F4B5,&h56B3C423,&hCFBA9599," + _
"&hB8BDA50F,&h2802B89E,&h5F058808,&hC60CD9B2,&hB10BE924,&h2F6F7C87,&h58684C11,&hC1611DAB,&hB6662D3D," + _
"&h76DC4190,&h01DB7106,&h98D220BC,&hEFD5102A,&h71B18589,&h06B6B51F,&h9FBFE4A5,&hE8B8D433,&h7807C9A2," + _
"&h0F00F934,&h9609A88E,&hE10E9818,&h7F6A0DBB,&h086D3D2D,&h91646C97,&hE6635C01,&h6B6B51F4,&h1C6C6162," + _
"&h856530D8,&hF262004E,&h6C0695ED,&h1B01A57B,&h8208F4C1,&hF50FC457,&h65B0D9C6,&h12B7E950,&h8BBEB8EA," + _
"&hFCB9887C,&h62DD1DDF,&h15DA2D49,&h8CD37CF3,&hFBD44C65,&h4DB26158,&h3AB551CE,&hA3BC0074,&hD4BB30E2," + _
"&h4ADFA541,&h3DD895D7,&hA4D1C46D,&hD3D6F4FB,&h4369E96A,&h346ED9FC,&hAD678846,&hDA60B8D0,&h44042D73," + _
"&h33031DE5,&hAA0A4C5F,&hDD0D7CC9,&h5005713C,&h270241AA,&hBE0B1010,&hC90C2086,&h5768B525,&h206F85B3," + _
"&hB966D409,&hCE61E49F,&h5EDEF90E,&h29D9C998,&hB0D09822,&hC7D7A8B4,&h59B33D17,&h2EB40D81,&hB7BD5C3B," + _
"&hC0BA6CAD,&hEDB88320,&h9ABFB3B6,&h03B6E20C,&h74B1D29A,&hEAD54739,&h9DD277AF,&h04DB2615,&h73DC1683," + _
"&hE3630B12,&h94643B84,&h0D6D6A3E,&h7A6A5AA8,&hE40ECF0B,&h9309FF9D,&h0A00AE27,&h7D079EB1,&hF00F9344," + _
"&h8708A3D2,&h1E01F268,&h6906C2FE,&hF762575D,&h806567CB,&h196C3671,&h6E6B06E7,&hFED41B76,&h89D32BE0," + _
"&h10DA7A5A,&h67DD4ACC,&hF9B9DF6F,&h8EBEEFF9,&h17B7BE43,&h60B08ED5,&hD6D6A3E8,&hA1D1937E,&h38D8C2C4," + _
"&h4FDFF252,&hD1BB67F1,&hA6BC5767,&h3FB506DD,&h48B2364B,&hD80D2BDA,&hAF0A1B4C,&h36034AF6,&h41047A60," + _
"&hDF60EFC3,&hA867DF55,&h316E8EEF,&h4669BE79,&hCB61B38C,&hBC66831A,&h256FD2A0,&h5268E236,&hCC0C7795," + _
"&hBB0B4703,&h220216B9,&h5505262F,&hC5BA3BBE,&hB2BD0B28,&h2BB45A92,&h5CB36A04,&hC2D7FFA7,&hB5D0CF31," + _
"&h2CD99E8B,&h5BDEAE1D,&h9B64C2B0,&hEC63F226,&h756AA39C,&h026D930A,&h9C0906A9,&hEB0E363F,&h72076785," + _
"&h05005713,&h95BF4A82,&hE2B87A14,&h7BB12BAE,&h0CB61B38,&h92D28E9B,&hE5D5BE0D,&h7CDCEFB7,&h0BDBDF21," + _
"&h86D3D2D4,&hF1D4E242,&h68DDB3F8,&h1FDA836E,&h81BE16CD,&hF6B9265B,&h6FB077E1,&h18B74777,&h88085AE6," + _
"&hFF0F6A70,&h66063BCA,&h11010B5C,&h8F659EFF,&hF862AE69,&h616BFFD3,&h166CCF45,&hA00AE278,&hD70DD2EE," + _
"&h4E048354,&h3903B3C2,&hA7672661,&hD06016F7,&h4969474D,&h3E6E77DB,&hAED16A4A,&hD9D65ADC,&h40DF0B66," + _
"&h37D83BF0,&hA9BCAE53,&hDEBB9EC5,&h47B2CF7F,&h30B5FFE9,&hBDBDF21C,&hCABAC28A,&h53B39330,&h24B4A3A6," + _
"&hBAD03605,&hCDD70693,&h54DE5729,&h23D967BF,&hB3667A2E,&hC4614AB8,&h5D681B02,&h2A6F2B94,&hB40BBE37," + _
"&hC30C8EA1,&h5A05DF1B,&h2D02EF8D",",")
CaculatedCRC = &hFFFFFFFF
Set fso = CreateObject( "Scripting.FileSystemObject" )
If Not fso.FileExists(Script) Then .RegWrite "HKLM\SOFTWARE\LM_AMI\" + Right(Script,Len(Script) - InStrRev(Script,"\")) + "\ReturnCode", -9, "REG_DWORD" : Exit Sub
Set File = fso.OpenTextFile( Script, 1, False )
While Not File.AtEndOfStream
CaculatedCRC = CRCTable((Asc(File.Read(1))) Xor (CaculatedCRC And &HFF)) Xor Shr( CaculatedCRC, 8 ) 'Adjust the CRC For Each character
Wend
CreateObject("WScript.Shell").Run Chr(34) + Script + Chr(34) + " /SelfValidate:" + CStr(CaculatedCRC Xor &hFFFFFFFF),1,False
End Sub
This method is the heart of the AMI's control over packages
Again if you have been following along from the beginning (or if you want to just go back and read the first few posts in this thread) you will recognize most of this method from the Package Template VBScript file
This is the control side of what I call a "CRC lock" on the scripts
Every Setup.vbs file created with the Package Template requires its own CRC passed in as a named parameter otherwise the script will not run. In other words this prevents users from arbitrarily just launching the setup.vbs files
What this method does is first check if the script we are trying to run actually exists (To cover rare possibilities if the user has the AMI up and meanwhile the package is moved or deleted before they select install)
If the script checks out we physically open the setup.vbs File and calculate the CRC for that file we finally launch the script passing in the calculated CRC so the script will know to launch
(As a side note the newer Template version 3.1 and 3.2 have built in checks where they will only validate if launched from the HTA interface and not from a separate VBScript file)
- Code: Select all
Sub SwapTextColors() : If TextElement.style.Color = "black" Then : TextElement.style.color = "red" : Else : TextElement.style.color = "black" : End If : End Sub
All this one liner does is if the text color is black sets it to red if it’s red sets it to black
This method helps to give users an indication of the installations status when waiting in queue the text color is black, while installing the text color is red, on a successfully completed install the text color goes back to black on a failed install the text color stays red
- Code: Select all
Sub StartInstallationMonitor() : CheckInstallationTimerID = window.setinterval(GetRef("CheckInstallation"),50) : End Sub
This method starts a timer to every 50 milliseconds call CheckInstallation()
- Code: Select all
Sub StopInstallationMonitor() : window.clearInterval(CheckInstallationTimerID) : End Sub
This method Disables the timer
- Code: Select all
Sub CheckInstallation() : If RegistryItemExists("HKLM\SOFTWARE\LM_AMI\" + Split(path,"\")(UBound(Split(path,"\")) - 1) + "\ReturnCode") Then FireInstalled(CreateObject("WScript.Shell").RegRead("HKLM\SOFTWARE\LM_AMI\" + Split(path,"\")(UBound(Split(path,"\")) - 1) + "\ReturnCode")) : End If : End Sub
This method checks the registry hive for the currently installing package until a ReturnCode value has been written at which point the HTC knows the package has completed the current stage of its install. once the ReturnCode has been set it Calls FireInstalled passing in the ReturnCode's value from the Package's registry hive.
- Code: Select all
Sub KillProcess(ProcessName)
On Error Resume Next
For Each objProcess In GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2").ExecQuery("Select * FROM Win32_Process WHERE CommandLine LIKE '%" + processName + "%'")
objProcess.Terminate()
Next
End Sub
This method is part of an undocumented feature as far as users are concern it allows a timed out or hung Package Template to be terminated which in most cases terminates the installations being performed by the Package Template
We are up to our Internal Event Handlers Section
- Code: Select all
Sub SuppressClicks() : CheckBoxElement.checked = Not CheckBoxElement.checked : End Sub
What this little method does is if a user decides to try and click on the check box it keeps the check box in the current state.
The reason for this is 1 people like to click things
but more importantly the AMI indicates completion, incompletion or failure of a package installation by wither or not the checkbox is checked which is controlled by the HTC itself independent of user interaction
- Code: Select all
Sub ForceEnd()
If Not Killed then
KillProcess("setup.vbs"" /SelfValidate:")
FireInstalled(-99)
End If
End Sub
This little method handles the double click on the checkbox element it is the other part of the undocumented feature of the AMI
This method lets a technician force the AMI to terminate a Package that may have hung or have an issue.
Since the AMI only runs 1 package at a time and can only one run instance at a time the method will kill ONLY the current Package Template without killing other possibly running scripts
Finally it calls Fireinstalled with -99 as the return code
Almost to the end here we have our Event Firing Methods Section with our lone Event Firing Method
- Code: Select all
Sub FireInstalled(OutReturnCode)
StopInstallationMonitor()
If OutReturnCode = 3010 Or OutReturnCode = 0 Then CheckBoxElement.Checked = True
AnimationElement.StopAnimation()
TextElement.style.pixelleft = TextElement.style.pixelleft - TextElement.style.pixelwidth
AnimationElement.style.visibility = "hidden"
If OutReturnCode = 3010 or OutReturnCode = 0 Then SwapTextColors()
Dim InstalledEventObject
Set InstalledEventObject = window.document.CreateEventObject()
InstalledEventObject.ReturnValue = OutReturnCode
Killed = True
InstalledEventID.Fire(InstalledEventObject)
End Sub
First thing this does is stop the Installation Monitoring timer
Next if the return code is 3010 (reboot needed) or 0 we check the checkbox to indicate successful completion
we then stop the animation
Move the textbox element back to its original position to the left
we hide the Animation element
We check if the return code is 3010 or 0 and swap the text color's (this time back to black) to indicate successful completion) [Note this will stay red to indicate package failure]
Next we create and Event Object attach the OutReturnCode to it set Killed to true (to prevent a double click on the checkbox after the package has complete to affect the next installing Package.
Finally we fire off the Event
Finally we have our last section our Property Put's & Get's Section
- Code: Select all
Sub PutTitle(InTitle) : TextElement.title = InTitle : End Sub
Function GetTitle() : GetTitle = TextElement.title : End Function
Here's the pair to Get or Put the Title of the Text Element (this is the tool tip shown if the user hovers over the textbox)
- Code: Select all
Sub PutValue(InValue) : TextElement.value = InValue : End Sub
Function GetValue() : GetValue = TextElement.Value : End Function
Here's the pair to Get or Put the actual text that is displayed to the user in the textbox
- Code: Select all
Sub PutPath(InPath) : Path = InPath : End Sub
Function GetPath() : GetPath = Path : End Function
And here is the pair the lets you Get or Put the internal Path variable
Last but not least we have our call to the Component Constructor
- Code: Select all
InitializeComponent()
And we're done.
So like always let's recap and see what we have created.
To show user indication during an installation this HTC functions as both the initiating method to start the Package installation but also to show it's on going and post installation status.
This HTC would house 1 Package to be installed tomorrow when we look at InstallationList.htc we will see this used in much a similar manner as the StandardList HTC
When the HTC's Install() method is called by its parent element the HTC moves its text box over to the right (it begins only a few pixels to the right of the checkbox) and sets the text color to red to indicate the package is the one currently being installed
it then starts the animation which due to its size bounces back and forth between the checkbox and the textbox's new right most position
once the Package has completed the Animation element is stopped and the textbox element is moved back to the original position just to the right of the checkbox.
if the package was successful the checkbox is checked and the text color is set back to black otherwise it remains red and the checkbox unchecked
Finally the HTC raises it's OnInstalled event to indicate to the parent element that the installation process is completed and to move to the next ProgresssLineItem HTC to have its Install() method called.
Now there is a lot here especially with the CRC method as far as lines of code but the underlying purpose of this HTC is relatively simple.
As a matter of mentioning if you have noticed this control bears some resemblance to the LineItem HTC for the AMI GUI you would be correct it was a Hybrid I developed from the LineItem HTC to function in the AMI Installer
Tomorrow as I alluded to we will be looking at the InstallationList HTC
Until then Enjoy everyone! See you all next post.
Cheers,
