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