Scripting Task Scheduler in Vista


I found the need to check several thousand machines on a regular basis to make sure BitLocker was installed and running.
I decided to run a script every time the machine booted up and for that I needed the Task Scheduler.

After some fumbeling around I gat this to work:

<------------------ Begin Script --------------------------->

Const TASK_ACTION_EXEC = 0 
Const TASK_CREATE = 2
Const TASK_Trigger_Boot = 8
Const TASK_RUNLEVEL_HIGHEST = 1
Const TASK_LOGON_PASSWORD = 1
Dim strUser, strPassword
strUser = "domainsvc-account"
strPassword = "Password"

Set objService = CreateObject("Schedule.Service")
objService.Connect()
Set objFolder = objService.GetFolder("")
Set objTaskDefinition = objService.NewTask(0)
Dim principal
Set principal = objTaskDefinition.Principal
' Set the logon type to TASK_LOGON_PASSWORD
principal.LogonType = 1
' RUNLEVEL = 1 Tasks will be run with the highest privileges.
' RUNLEVEL = 0 Tasks will be run with the least privileges (LUA).
principal.RunLevel = 1
Set colTasks = objTaskDefinition.Triggers
Set objTrigger = colTasks.Create(TASK_Trigger_Boot)
objTrigger.StartBoundary = "2009-05-27T08:00:00-00:00"
objTrigger.ExecutionTimeLimit = "PT5M" 'Five minutes
Set colActions = objTaskDefinition.Actions
Set objAction = colActions.Create(TASK_ACTION_EXEC)
objAction.ID = "BitLocker Check"
objAction.Path = "cscript.exe" ' <----- This could be powershell.exe
objAction.WorkingDirectory = "c:\scripts"
objAction.Arguments = "/nologo c:\scripts\chkBL.vbs" '<---Put your script here
'(or for PowerShell -noprofile -command "Path to .PS1 script" )
Set objInfo = objTaskDefinition.RegistrationInfo
objInfo.Author = "Author" <--- Put your name here
objInfo.Description = "Task that checks BitLocker status at every boot." '<--- Put a brief description here.
Set objSettings = objTaskDefinition.Settings
objSettings.Enabled = True
objSettings.Hidden = False
objSettings.StartWhenAvailable = True

objFolder.RegisterTaskDefinition "Check BitLocker Status", objTaskDefinition, TASK_CREATE, strUser, strPassword, 1

'<------------------ End Of Script --------------------------->

Have fun and may the force be with you.

Advertisements

Enable the Trusted Platform Module (TPM)

So in my never ending quest to do obscure stuff, I.E. Script BitLocker
I found that I had to make sure the TPM (Trusted Platform Module)
was:
1. Enabled
2. Activated
3. Owned (this is handled in another script)
Here is the script I came up with to do just that.
‘< —– Start vbScript —————————>
‘On Error Resume Next
Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20
Set oSystemSet = GetObject(“winmgmts:{impersonationLevel=impersonate,” _
& “(Shutdown)}”).InstancesOf(“Win32_OperatingSystem”)
arrComputers = Array(“.”)
For Each strComputer In arrComputers
   WScript.Echo
   WScript.Echo “==========================================”
   WScript.Echo “Computer: ” & strComputer
   WScript.Echo “==========================================”
TPMOn = False
Set objWMIService = GetObject(“WinMgmts:{impersonationLevel=impersonate,AuthenticationLevel=pktprivacy}//” _
& “.” & “rootCIMV2SecurityMicrosoftTpm”)
Set objItems = objWMIService.InstancesOf(“Win32_Tpm”)
For Each objItem in objItems
  rvaluea = objItem.IsEnabled(A)
  rvalueb = objItem.IsActivated(B)
  rvaluec = objItem.IsOwned(C)
  TPMOn = True
WScript.Echo “TPM Is Enabled: ” & A
WScript.Echo “TPM Is Activated: ” & B
WScript.Echo “TPM Is Owned: ” & C
If A AND B AND C Then
  WScript.Echo “The TPM Is Enabled, Activated and Owned”
Else
   objItem.SetPhysicalPresenceRequest(14)  ‘<—- see note below
   If Err.Number <> 0 Then
         WScript.Echo “Enabling Trusted Platform Module failed.”
   End If
        MsgBox “Will Reboot in 10 seconds”
       WScript.Sleep 10000
       Reboot
  End If
Next
If (TPMOn = False) Then
   WScript.Echo “Trusted Platform Module may be turned off”
End If
Next
Sub Reboot
For Each oSystem In oSystemSet
        oSystem.Win32Shutdown 6
Next
End Sub
‘< —– end vbScript —————————>
I also had to verify that the TPM was SpecVersion 1.2 or else it won’t work with BitLocker.

 

On Error Resume Next

Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20

arrComputers = Array(“.”)
For Each strComputer In arrComputers
WScript.Echo
WScript.Echo “==========================================”
WScript.Echo “Computer: ” & strComputer
WScript.Echo “==========================================”

   Set objWMIService = GetObject(“winmgmts:\.rootCIMV2SecurityMicrosoftTpm”)
Set colItems = objWMIService.ExecQuery(“SELECT * FROM Win32_Tpm”, “WQL”, _
wbemFlagReturnImmediately + wbemFlagForwardOnly)
For Each objItem In colItems
WScript.Echo “SpecVersion: ” & objItem.SpecVersion
SpecVersion = CStr(objItem.SpecVersion)
Next
If Left(SpecVersion,3) = 1.2 Then
WScript.Echo “TPM is version 1.2”
Else
WScript.Echo “TPM is NOT version 1.2.”
WScript.Quit
End If

Next

BitLocker Encryption Progress Bar

It can take an hour or two to encrypt your hard drive. I wanted a visual aide to tell me how it was doing.
This vbScript creates a web page and a simple graph that will tell you how far along the encryption process is;
On Error Resume Next
Set objExplorer = CreateObject("InternetExplorer.Application")
objExplorer.Navigate "about:blank"  
objExplorer.ToolBar = 0
objExplorer.StatusBar = 0
objExplorer.Width=200
objExplorer.Height = 450
objExplorer.Left = 0
objExplorer.Top = 0
Do While (objExplorer.Busy)
    Wscript.Sleep 200
Loop   
objExplorer.Document.Title = "BitLocker Conversion Progress"
objExplorer.Visible = 1    
arrComputers = Array("10", "20", "30", "40", "50", "60", "70", "80", "90", "100")
strHTML = "<h2>BitLocker Conversion Progress</h2>"
strHTML = strHTML & "<table id=’ComputerList’ width=’100%’ border>"
For Each strComputer in arrComputers
    strHTML = strHTML & "  <tr>"
    strHTML = strHTML & "  <td width=’100%’>" & strComputer & "%</td>"
    strHTML = strHTML & "  </tr>"
Next
strHTML = strHTML & "</table>"
objExplorer.Document.Body.InnerHTML = strHTML
Wscript.Sleep 2000
    strComputer = arrComputers(i)
 Set objWMIService = GetObject("winmgmts:\" & "." _
    & "rootCIMV2SecurityMicrosoftVolumeEncryption")
 If Err = 0 Then
  Set volumes = objWMIService.InstancesOf("Win32_EncryptableVolume")
  cs = 2
  For Each volume in volumes
   If volume.DriveLetter = "C:" Then 
    retval = volume.GetEncryptionMethod(em)    
    retval1 = volume.GetConversionStatus(cs,ep)
   If (cs = 1) And (em = 1) Then 
         objExplorer.Quit
         Wscript.Echo "Ready for EFS decryption!!!!!!!"
         wscript.quit  ‘ Put decrypt here !!!!!!!
‘  Loop until Conversion complete 
   ElseIf (cs = 2) Then
          Do While cs = 2
       retval = volume.GetEncryptionMethod(em)    
    retval1 = volume.GetConversionStatus(cs,ep)
    Wscript.Echo em & vbTab & cs & vbTab & ep
        If ep >=10 Then
        i = 0
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "lightgreen"
       ElseIf ep >=1 And ep < 10 Then
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "yellow"
       End If
       
       If ep > 20 Then
     i = 1
     objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "lightgreen"
       ElseIf ep > 10 And ep < 20 Then
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "yellow"
     End If
     
     If ep > 30 Then
       i = 2
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "lightgreen"
     ElseIf ep > 20 And ep < 30 Then
     objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "yellow"
       End If
       
       If ep > 40  Then
       i = 3
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "lightgreen"
       ElseIf ep > 30 And ep < 40 Then
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "yellow"
       End If
     
     If ep > 50 Then
       i = 4
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "lightgreen"
     ElseIf ep >= 40 And ep < 50 Then
     objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "yellow"
       End If
       
       If ep > 60 Then
       i = 5
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "lightgreen"   
       ElseIf ep >= 50 And ep < 60 Then
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "yellow"
       End If
       
       If ep > 70 Then
       i = 6
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "lightgreen"
       ElseIf ep >= 60 And ep < 70  Then
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "yellow"
       End If
       
       If ep > 80 Then
       i = 7
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "lightgreen"
       ElseIf ep >= 70 And ep < 80 Then
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "yellow"
       End If
       
       If ep > 90 Then
       i = 8
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "lightgreen"
       ElseIf ep >= 80 And ep < 90 Then
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "yellow"
       End If
       
       If ep = 100 Then
       i = 9
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "lightgreen"
       ElseIf ep >= 90 And ep < 100 Then
       objExplorer.Document.Body.All.ComputerList.Rows(i).bgColor = "yellow"
       End If
       i = 0
       Wscript.Sleep 60000
      Loop
   End If
  End If
    Err.Clear
 Next
End If

Scripting BitLocker

For those of you who read this (that would be me and my sainted mother) I have been a bit remiss in updating this blog. I have been between opportunities, as they say. As luck would have it, I found a contract that requires me to script a BitLocker implementation. The first issue I had to deal with was determining if BitLocker was already installed. That proved to be no easy task for me. With some help and luck I came up with this;

dim retval, em
arrComputers = Array(".")
For Each strComputer In arrComputers
   WScript.Echo
   WScript.Echo "=========================================="
   WScript.Echo "Computer: " & strComputer
   WScript.Echo "=========================================="
 

Set objWMIService = GetObject("winmgmts:\" & strComputer _
    & "rootCIMV2SecurityMicrosoftVolumeEncryption")

Set volumes = objWMIService.InstancesOf("Win32_EncryptableVolume")

 
 for each volume In volumes
     If volume.DriveLetter = "C:" then 
     retval = volume.GetEncryptionMethod(em)
     WScript.Echo em
     End If
 Next
Next
 
If it returns 1 (one) BitLocker is enabled and running. 0 (zero) means it is not.
 
And here it is in Powershell;
 
$strComputer = "."
$colItems = Get-WmiObject -class Win32_EncryptableVolume -namespace "rootCIMV2SecurityMicrosoftVolumeEncryption" `
-computername $strComputer -filter "DriveLetter=’C:’"
$b = $colItems.GetEncryptionMethod()
 write-host "EncryptionMethod: " $b.EncryptionMethod
 
You can also check on the status of your Conversion by adding a line;
 
retval1 = volume.GetConversonStatus(cs, ep) to the vbScript.
 
Like this:
 
dim retval, em
arrComputers = Array(".")
For Each strComputer In arrComputers
   WScript.Echo
   WScript.Echo "=========================================="
   WScript.Echo "Computer: " & strComputer
   WScript.Echo "=========================================="
Set objWMIService = GetObject("winmgmts:\" & strComputer _
    & "rootCIMV2SecurityMicrosoftVolumeEncryption")
Set volumes = objWMIService.InstancesOf("Win32_EncryptableVolume")
 for Each volume in volumes
     If volume.DriveLetter = "C:" then 
     retval = volume.GetEncryptionMethod(em)
     retval1 = volume.GetConversionStatus(cs, ep) ‘ <— added line
     Wscript.Echo "Conversion Status: " & cs & vbTab & "% Complete: " & ep
     End If
 Next
Next
 And in PowerShell;
 
$strComputer = "."
$colItems = Get-WmiObject -class Win32_EncryptableVolume -namespace "rootCIMV2SecurityMicrosoftVolumeEncryption" `
-computername $strComputer -filter "DriveLetter=’C:’"
$c = $colItems.GetConversionStatus()
$ep = $c.EncryptionPercentage
$ep 
if ($C.ConversionStatus -eq 0)
   {"Conversion Status: FULLY DECRYPTED"}
   elseif($C.ConversionStatus -eq 1)
      {"Conversion Status: FULLY ENCRYPTED"}
   elseif($C.ConversionStatus -eq 2)
      {"Conversion Status: ENCRYPTION IN PROGRESS"}
   elseif($C.ConversionStatus -eq 3)
      {"Conversion Status: DECRYPTION IN PROGRESS"}
   elseif($C.ConversionStatus -eq 4)
      {"Conversion Status: ENCRYPTION PAUSED"}
   elseif($C.ConversionStatus -eq 5)
      {"Conversion Status: DECRYPTION PAUSED"}
   else
      {$C.ConversionStatus + " Conversion Status: unknown"}
 
And here are some words from Microsoft on the subject:
 

Although the documentation was in C language notation, it is similar in call in VBScript. According to the documentation, it is:

 uint32 GetEncryptionMethod([out] uint32 EncryptionMethod); 

For more information, see:

GetEncryptionMethod Method of the Win32_EncryptableVolume Class

http://msdn.microsoft.com/en-us/library/aa376434(VS.85).aspx

You will need to also modify the calls for the GetProtectionStatus and GetConversionStatus calls, otherwise, this too will only output their respective Return Value. Below is the syntax for the 2 other methods that you are calling.

uint32 GetProtectionStatus([out] uint32 ProtectionStatus);
uint32 GetConversionStatus([out] uint32 ConversionStatus, [out] uint32 EncryptionPercentage); 

In VBScript, they would look like:

returnValue1 = GetProtectionStatus(ps)

WScript.Echo "ProtectionStatus: " & ps

returnValue2 = GetConversionStatus(cs, ep)

WScript.Echo "ConversionStatus: " & cs

WScript.Echo "EncryptionPercentage: " & ep 

For more information, see: 

GetProtectionStatus Method of the Win32_EncryptableVolume Class

http://msdn.microsoft.com/en-us/library/aa376448(VS.85).aspx 

GetConversionStatus Method of the Win32_EncryptableVolume Class

http://msdn.microsoft.com/en-us/library/aa376433(VS.85).aspx