Stuart James at myITforum.com

Modifying Program Flags using VBScript

The script below gives an example of how to modify the program flags in SCCM. In the sample it will change all of the programs to be able to run from a task sequence without being advertised.

If you want to modify some other value then search for “SMS_Program” in the SDK and have a look for the relevant “ProgramFlags” value. I’ve pasted the current list at time of writing below for reference:

0x00000001 (0)
AUTHORIZED_DYNAMIC_INSTALL. The program is authorized for dynamic install.

0x00000002 (1)
USECUSTOMPROGRESSMSG. The task sequence shows a custom progress user interface message.

0x00000010 (4)
DEFAULT_PROGRAM. This is a default program

0x00000020 (5)
DISABLEMOMALERTONRUNNING. Disables MOM alerts while the program runs.

0x00000040 (6)
MOMALERTONFAIL. Generates MOM alert if the program fails.

0x00000080 (7)
RUN_DEPENDANT_ALWAYS. If set, this program's immediate dependent should always be run.

0x00000100 (8)
WINDOWS_CE. Indicates a device program. If set, the program is not offered to desktop clients.

0x00000200 (9)
This value is not used.

0x00000400 (10)
COUNTDOWN. The countdown dialog is not displayed.

0x00000800 (11)
FORCERERUN. This value is not used.

0x00001000 (12)
DISABLED. The program is disabled.

0x00002000 (13)
UNATTENDED. The program requires no user interaction.

0x00004000 (14)
USERCONTEXT. The program can run only when a user is logged on.

0x00008000 (15)
ADMINRIGHTS. The program must be run as the local Administrator account.

0x00010000 (16)
EVERYUSER. The program must be run by every user for whom it is valid. Valid only for mandatory jobs.

0x00020000 (17)
NOUSERLOGGEDIN. The program is run only when no user is logged on.

0x00040000 (18)
OKTOQUIT. The program will restart the computer.

0x00080000 (19)
OKTOREBOOT. Configuration Manager restarts the computer when the program has finished running successfully.

0x00100000 (20)
USEUNCPATH. Use a UNC path (no drive letter) to access the distribution point.

0x00200000 (21)
PERSISTCONNECTION. Persists the connection to the drive specified in the DriveLetter property. The USEUNCPATH bit flag must not be set.

0x00400000 (22)
RUNMINIMIZED. Run the program as a minimized window.

0x00800000 (23)
RUNMAXIMIZED. Run the program as a maximized window.

0x01000000 (24)
HIDEWINDOW. Hide the program window.

0x02000000 (25)
OKTOLOGOFF. Logoff user when program completes successfully.

0x04000000 (26)
RUNACCOUNT. This value is not used.

0x08000000 (27)
ANY_PLATFORM. Override check for platform support.

0x10000000 (28)
STILL_RUNNING. This value is not used.

0x20000000 (29)
SUPPORT_UNINSTALL. Run uninstall from the registry key when the advertisement expires.

0x40000000 (30)
The platform is not supported.

0x80000000 (31)
SHOW_IN_ARP. This value is not used.

ProgramFlags are bitwise so you need to flip the bit if you want to change something. The code that does the real work is below:

If program.ProgramFlags AND 2^0 Then
   ' AUTHORIZED_DYNAMIC_INSTALL is set.
    wscript.echo "Value is already set, no need to modify"
Else
     ' AUTHORIZED_DYNAMIC_INSTALL is not set. Setting AUTHORIZED_DYNAMIC_INSTALL value.
    wscript.echo  "***********************************"
    wscript.echo "*** Value is not set, modifying ***"
    wscript.echo  "***********************************"
    program.ProgramFlags = program.ProgramFlags + 2^0
    wscript.echo "Program Updated"
End If

In the example above I am setting the dynamic installation option, which if you look in the list of options above is “0”.  If for example you wanted to change the setting for “Hide the program window” you would change it to 2^24. To deselect something you would subtract the value rather than add.

Anyway, full script sample below.  The script also shows something I use quite often which is to force use of CScript even when double clicked so that everything is output to a command window rather than lots of nasty popups.

Pasting the script in seems to wrap some of the lines so you may just need to check that all is OK before running it.

'=====================================
'SetRunFromTS - Sets all programs to be able to run from Task Sequence
'Author: Stuart James
'
'Requirements: Run on the site server with account that has necessary rights
'
'Usage: CScript SetRunFromTS.vbs or double click
'=====================================

'Check we're using CScript and if not then relaunch
If "CSCRIPT.EXE" <> UCase(Right(WScript.Fullname, 11)) Then
  Set WshShell = WScript.CreateObject("WScript.Shell")
  WshShell.Run "CSCRIPT.EXE /nologo " & WScript.ScriptFullName
  Wscript.Quit
End If

' Setup a connection to the local provider.
Set swbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set swbemServices= swbemLocator.ConnectServer(".", "root\sms")
Set providerLoc = swbemServices.InstancesOf("SMS_ProviderLocation")

For Each Location In providerLoc
    If location.ProviderForLocalSite = True Then
        Set swbemServices = swbemLocator.ConnectServer(Location.Machine, "root\sms\site_" + Location.SiteCode)
        Exit For
    End If
Next

'Main call
QueryPrograms swbemServices

Sub QueryPrograms(connection)

    On Error Resume next

    Dim programs
    Dim program
    ' Run the query.
    Set programs = connection.ExecQuery("Select * From SMS_Program")

    If Err.Number<>0 Then
        Wscript.Echo "Couldn't get programs"
        Wscript.Quit
    End If
    For Each program In programs
        ModifyProgram connection,program.PackageID, program.ProgramName
    Next
    If programs.Count=0 Then
        Wscript.Echo "No packages found"
    End If

End Sub

Sub ModifyProgram (connection, existingPackageID, existingProgramName)

    ' Build a query to get the specified package.
    packageQuery = "SMS_Package.PackageID='" & existingPackageID & "'"

    ' Run the query to get the package.
    Set package = connection.Get(packageQuery)
    ' Output package name and ID.
    wscript.echo "============================================"
    wscript.echo "Package ID:     "  & package.PackageID
    wscript.echo "Package Name:   "  & package.Name
    ' Build a query to get the programs for the package.
    programQuery = "SELECT * FROM SMS_Program WHERE PackageID='" & existingPackageID & "'"
    ' Run the query to get the programs.
    Set allProgramsForPackage = connection.ExecQuery(programQuery, , wbemFlagForwardOnly Or wbemFlagReturnImmediately)
    'The query returns a collection of program objects that needs to be enumerated.
    For Each program In allProgramsForPackage               
        If program.ProgramName = existingProgramName Then
            ' Output the program name
            wscript.echo "Program Name:   "  & program.ProgramName
            'Get all program object properties (in this case we specifically need some lazy properties).
             programPath = program.Put_
             Set program = connection.Get(programPath)
            If program.ProgramFlags AND 2^0 Then
               ' AUTHORIZED_DYNAMIC_INSTALL is set.
                wscript.echo "Value is already set, no need to modify"
            Else
                 ' AUTHORIZED_DYNAMIC_INSTALL is not set. Setting AUTHORIZED_DYNAMIC_INSTALL value.
                wscript.echo  "***********************************"
                wscript.echo "*** Value is not set, modifying ***"
                wscript.echo  "***********************************"
                program.ProgramFlags = program.ProgramFlags + 2^0
                wscript.echo "Program Updated"
            End If
            ' Save the program.
            program.Put_
        End If       
    Next
End Sub

'Add pause to end in case script was double clicked so we can review what happened
WScript.Echo "=== F I N I S H E D ==="
strMessage = "Press the ENTER key to continue. "
Wscript.StdOut.Write strMessage

Do While Not WScript.StdIn.AtEndOfLine
   Input = WScript.StdIn.Read(1)
Loop

Comments

No Comments