Monday, September 12, 2011

VBScript Function: Split a string, character by character

Custom function to give VBS the ability to split a string, character by character.



Function SplitByCharacter(strString)
 Dim arrTemp()
 iLen = Len(strString)-1
 redim arrTemp(iLen)
 For iCounter = 0 to iLen
  arrTemp(iCounter) = Mid(strString, iCounter + 1,1)
 Next

 SplitByCharacter = arrTemp
End Function

Wednesday, July 13, 2011

SCCM/SMS Client Uninstall Script

Forgive the sloppy code but I'm just posting this in response to a post on TechNet in regards to someone trying to mass uninstall the SCCM client.

This script was hastily/sloppily written to address a major problem we had migrating from SMS 2003 to SCCM 2007 where the clients didn't like being reassinged to a new site. The fix action ended up being a myraid of things:

  1. Hung 'ccmexec' service due to the process not terminating
  2. The uninstall didn't fully complete
  3. Duplicate GUID problems
  4. ...etc

You may have to change some parts around:

On Error Resume Next

Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")

strOutputFile = "CCMOutputFile.txt"
strComputerFile = "computers.txt"
strSMSCfgFile = "c$\Windows\smscfg.ini"
strSMSDelCertString = "c:\temp\ccmdelcert.exe"
strSMSUninstallString = "c:\windows\system32\ccmsetup\ccmsetup.exe /uninstall"
strSMSCleanString = "c:\temp\ccmclean.exe /all /q"
strSCCMServer = "SCCMSERVERNAME"
strSMSServiceName = "ccmexec"

iComputersSuccess = 0
iComputersOffline = 0
iComputersTotal = 0



arrComputers = Split(getTextFile(strComputerFile), vbCrLf)

If IsArray(arrComputers) Then
 For Each strComputer In arrComputers
  strComputer = Trim(strComputer)
  If strComputer <> "" Then 
   WScript.Echo "Pinging " & strComputer & " to see if it is online."
   If Ping(strComputer) Then
    WScript.Echo "Binding to " & strComputer & " via WMI."
    Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    If Err.Number <> 0 Then
     displayError("Binding error to WMI on:  " & strComputer)
     Err.Clear
    End If
    
    If Not objWMI Is Nothing Then
    
     WScript.Echo "Copying pertinent files to c:\temp"
     If Not objFSO.FileExists("\\" & strComputer & "\c$\" & strSMSUninstallString) Then
      objFSO.CopyFile "\\" & strSCCMServer & "\SCCM Client Tools\*", "\\" & strComputer & "\c$\temp\", true
     End If
     
     killProcess strComputer, "ccmexec.exe"

     Set objWMIProcess = GetObject("winmgmts:\\" & strComputer & "\root\cimv2:Win32_Process") 
     
     WScript.Echo "Running delcert process on remote host."
     If objFSO.FileExists("\\" & strComputer & "\c$\temp\ccmdelcert.exe") Then
      spawnProcess strComputer, strSMSDelCertString
     Else
      WScript.Echo "Unable to locate delcert executable for execution."
     End If
     
     WScript.Echo "Running ccmsetup /uninstall process on remote host."
     If objFSO.FileExists("\\" & strComputer & "\c$\windows\system32\ccmsetup\ccmsetup.exe") Then
      spawnProcess strComputer, strSMSUninstallString
     Else
      WScript.Echo "Unable to locate ccmsetup executable for execution."
     End If
     
     WScript.Echo "Running ccmclean process on remote host."
     If objFSO.FileExists("\\" & strComputer & "\c$\temp\ccmclean.exe") Then
      spawnProcess strComputer, strSMSCleanString
     Else
      WScript.Echo "Unable to locate ccmclean executable for execution."
     End If
           
     iComputersSuccess = iComputersSuccess + 1
    Else    
     WScript.Echo "Error binding to WMI using the syntax:  winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2"
    End If
   Else
    iComputersOffline = iComputersOffline + 1
   End If
   iComputersTotal = iComputersTotal + 1
  End If
  If iComputersTotal Mod 5 = 0 Then
   WScript.Echo ""
   WScript.Echo "STATUS UPDATE:"
   WScript.Echo vbTab & "Hosts Successfully Uninstalled:  " & iComputersSuccess
   WScript.Echo vbTab & "Hosts Offline:  " & iComputersOffline
   WScript.Echo vbTab & "Total Hosts Evaluated:  " & iComputersTotal
   WScript.Echo ""
  Else
   WScript.Echo ""
  End If
 Next
End If



' ***********************************************************************************

Sub displayError(strMessage)
    'Display custom message and information from VBScript Err object.

    strError = VbCrLf & "ERROR:  " & strMessage & VbCrLf & _
      "Number (dec) : " & Err.Number & VbCrLf & _
      "Number (hex) : &H" & Hex(Err.Number) & VbCrLf & _
      "Description  : " & Err.Description & VbCrLf & _
      "Source       : " & Err.Source
    Err.Clear
    WScript.Echo strError

End Sub

Function Ping(strComputer)
 Dim objPing, strPing

 Set objPing = objShell.Exec("ping -n 1 -w 2000 " & strComputer & "")
 
 strPing = objPing.StdOut.ReadAll()
 
 If Instr(strPing, "Reply") <> 0 Then
  Ping = True
 Else
  Ping = False
 End If
End Function


Function getTextFile(strFilePath)
 If Not objFSO.FileExists(strFilePath) Then
  WScript.Echo "Could not locate text file:  " & strFilePath
  WScript.Quit
 End If
 
 Set objTextFile = objFSO.OpenTextFile(strFilePath, 1)
 strTemp = objTextFile.ReadAll
 objTextFile.Close
 
 getTextFile = strTemp
End Function

Sub killProcess(strComputer, strProcess)
 Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator") 
 objSWbemLocator.Security_.privileges.addasstring "sedebugprivilege", true
 Set objWMIService = objSWbemLocator.ConnectServer(strComputer, "root\CIMV2")
 Set colProcesses = objWMIService.ExecQuery("Select * From Win32_Process Where Name = '" & strProcess & "'")
 
 If colProcesses.Count = 0 Then
  log("Process not found to be running:  " & strProcess & vbCrLf)
 ElseIf colProcesses.Count > 0 Then
  For Each objProcess in colProcesses
   intReturn = objProcess.Terminate()
   log("Attempting to kill process (" & strProcess & ") returned error code:  " & intReturn & vbCrLf)
  Next
 Else
  log(".Count method returned an unexpected value while attempting to kill:  " & strProcess & vbCrLf)
 End If
End Sub

Sub spawnProcess(strComputer, strExec)
 intReturn = objWMIProcess.Create(strExec)
 Select Case intReturn
  Case 0 WScript.Echo "Process creation was a success"
  Case 2 WScript.Echo "Process creation returned Access Denied"
  Case 3 WScript.Echo "There were insufficient priviledges to complete the process"
  Case 8 WScript.Echo "Unknown failure"
  Case 9 WScript.Echo "Path not found"
  Case 21 WScript.Echo "Invalid Parameter"
  Case Else WScript.Echo "Process creation returned an unrecognized parameter"
 End Select
End Sub

Wednesday, June 15, 2011

PowerShell GUI Errors Referencing STA or Single Thread Apartment

So I've been working with Powershell GUIs for a bit now and run into some errors while running some of my test forms. Whenever I'd click a certain drop-down list, I get a large error message with the following text:

The following exception occurred in the DataGridView:
System.Threading.ThreadStateException: Current thread must be set to
single thread apartment (STA) mode before OLE calls can be made.
Ensure that your Main function has STAThreadAttribute marked on it.
at
System.Windows.Forms.ComboBox.set_AutoCompleteSource(AutoCo
mpleteSource value)
at
System.Windows.Forms.DataGridViewComboBoxCellJnitializeEditingCo
ntrol(1nt32 rowlndeƧ Object initialFormattedValue
DataGridViewCellStyle dataGridViewCellStyle)
at
System.Windows.Forms.DataGridViewJnitializeEditingControlValue(Dat
aGridViewCellStyle& dataGridViewCellStyle. DataGridViewCell
dataGridViewCell)

I found through a PowerShell forum that this is because PowerShell, by default, runs in multi-threaded apartment mode (MTA). For some GUI aspects, it is required to run in single-threaded aparetment mode (STA).

A quirk of working with different editors is knowing the difference and which mode loads by default. As an example, when working with PowerShell ISE, the integrated shell loads in STA mode. However, by default, PowerShell (itself) loads in MTA mode unless specified otherwise.

You can execute powershell in STA mode simply by adding a -STA switch when calling the powershell executable.

You can check which mode you're running in by running the following:

[threading.thread]::CurrentThread.GetApartmentState()

This will either return STA or MTA depending on what context powershell is being run in.

I haven't figured out how to programmatically set the apartment state inside of a script but I will repost that information if/when I find it.

A workaround for this problem is to add this snippet of code at the start of your script:

if ([threading.thread]::CurrentThread.GetApartmentState() -eq "MTA") {
   & $env:SystemRoot\system32\WindowsPowerShell\v1.0\powershell.exe -sta $MyInvocation.ScriptName
   Exit
}


Tuesday, June 14, 2011

Copy Text from Image

Optical Character Recognition (OCR) is how you can read text from image files. There are some tools out there that will allow you to do this (freeware/shareware/etc.) However, if you are in a Microsoft-heavy environment as I am and you have Microsoft Office OneNote available, you already have this function readily available. The steps are as follows:

- Take a screenshot of the image that has text that you want (error message, web image, etc.)

- Open Microsoft OneNote

- In a new tab, paste the image into the new Tab (Edit > Paste; Ctrl-v)

- Right-click on your newly pasted image and select, "Copy Text from Picture"

...that's it! Paste the text now on your clipboard wherever you want it!

Tuesday, June 7, 2011

PowerShell Create-ComplexPassword v1

NEW!:  http://thepip3r.blogspot.com/2012/02/powershell-create-complexpassword-v2.html


Description: Generates complex passwords based off of the criteria given. Able to create passwords of any length and any complexity given the following standard options:

  • length
  • lowercase
  • uppercase
  • numbers
  • special characters

Acknowledgements: Depending on the complexity given, with this being a true random password generation, a potential exists to generate a large number (thousands of iterations) of internal bad passwords before presenting one back that matches. As an example, if you specified a 30 character password where 29 had to be numbers, the possible iterations before you found a match could be in the millions or more.


Future: I'm currently working on a much more efficient version that will simply generate the random values requested and then shuffle the resulting string. The result will be much less random, but much more efficient.


Logic Overview:

  • Determine supplied options
  • Build Regular Expression based off of those options
  • Generate a random string of characters based off the $PasswordLength and compare it to the generated Regular Expression to see if it meets the remaining complexity requirements supplied.


Example Syntax:

Create-ComplexPassword -PasswordLength 30 -LowerAlphas 5 -UpperAlphas 5 -Numbers 10 -SpecialCharacters 10

Create-ComplexPassword -PasswordLength 16 -LowerAlphas 2 -UpperAlphas 2 -Numbers 2 -SpecialCharacters 2

Create-ComplexPassword -PasswordLength 16 -SpecialCharacters 16



Script:
Function Create-ComplexPassword {
 
Param (
        [parameter()] [ValidateNotNullOrEmpty()] [int] [ValidateScript({$_ -gt 0})] $PasswordLength = 8,
        [parameter()] [ValidateNotNullOrEmpty()] [int] [ValidateScript({$_ -gt 0})] $LowerAlphas = 1,
        [parameter()] [ValidateNotNullOrEmpty()] [int] [ValidateScript({$_ -gt 0})] $UpperAlphas = 1,
        [parameter()] [ValidateNotNullOrEmpty()] [int] [ValidateScript({$_ -gt 0})] $Numbers = 1,
        [parameter()] [ValidateNotNullOrEmpty()] [int] [ValidateScript({$_ -gt 0})] $SpecialCharacters = 1
    )
  
    If (($LowerAlphas + $UpperAlphas + $Numbers + $SpecialCharacters) -gt $PasswordLength) { 
        Throw "The specified sum of the number of upper, lower, numeric, and special characters cannot be greater than the desired length of the password."
    }
    
    # Build the regular expression for pattern matching based on the supplied requirements
    $match = "^"
    
    # Build match for number of required lower alphas
    $match += "(?="
    For ($i=1; $i -le $LowerAlphas; $i++) {
        $match += ".*[a-z]"
    }
    $match += ")"
    
    # Build match for number of required upper alphas
    $match += "(?="
    For ($i=1; $i -le $UpperAlphas; $i++) {
        $match += ".*[A-Z]"
    }
    $match += ")"
    
    # Build match for number of required numbers
    $match += "(?="
    For ($i=1; $i -le $Numbers; $i++) {
        $match += ".*[0-9]"
    }
    $match += ")"
    
    
    # Build match for number of required special characters
    $match += "(?="
    For ($i=1; $i -le $SpecialCharacters; $i++) {
        $match += ".*[^a-zA-Z0-9]"
    }
    $match += ")"
    
    # Build the ending match of the statement to include anything else
    $match += ".*$"

    # Creates random object with seed to guarantee uniqueness
 $objRnd = New-Object System.Random((Get-Date).Millisecond); 

    $iterations = 0

    Do {
        $strPassword = $Null
     For ($i = 0; $i -lt $PasswordLength; $i++) {
       $NextChar = $objRnd.next(33,126)
                $strPassword += ([char]$nextChar)
     }
        $iterations++
    } Until (($strPassword -match $match) -eq $True)

 $strPassword
}



Thursday, June 2, 2011

PowerShell GUIs: Active Directory TreeView

So this is a modified bit of code I wrote to build a tree-view of the local Active Directory OU structure. I'm using this snippet in another piece of code but it *should* work just fine in any domain. Please let me know of any modifications or fixes necessary.



function Add-Node { 
        param ( 
            $selectedNode, 
            $name
        ) 
        $newNode = new-object System.Windows.Forms.TreeNode  
        $newNode.Name = $name 
        $newNode.Text = $name 
        $selectedNode.Nodes.Add($newNode) | Out-Null 
        return $newNode 
} 

function Get-NextLevel {
    param (
        $selectedNode,
        $dn
   )
   
    $OUs = Get-ADObject -Filter 'ObjectClass -eq "organizationalUnit" -or ObjectClass -eq "container"' -SearchScope OneLevel -SearchBase $dn

    If ($OUs -eq $null) {
        $node = Add-Node $selectedNode $dn
    } Else {
        $node = Add-Node $selectedNode $dn
        
        $OUs | % {
            Get-NextLevel $node $_.distinguishedName
        }
    }
}
 
function Build-TreeView { 
    if ($treeNodes)  
    {  
          $treeview1.Nodes.remove($treeNodes) 
        $form1.Refresh() 
    } 
    
    $treeNodes = New-Object System.Windows.Forms.TreeNode 
    $treeNodes.text = "Active Directory Hierarchy" 
    $treeNodes.Name = "Active Directory Hierarchy" 
    $treeNodes.Tag = "root" 
    $treeView1.Nodes.Add($treeNodes) | Out-Null 
     
    $treeView1.add_AfterSelect({ 
        $textbox1.Text = $this.SelectedNode.Name
    }) 
     
    #Generate Module nodes 
    $OUs = Get-NextLevel $treeNodes $strDomainDN
    
    $treeNodes.Expand() 
} 
 
#Generated Form Function 
function GenerateForm { 
 
    #region Import the Assemblies 
    Import-Module ActiveDirectory
    [reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null 
    [reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null 
    $objIPProperties = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
    $strDNSDomain = $objIPProperties.DomainName.toLower()
    $strDomainDN = $strDNSDomain.toString().split('.'); foreach ($strVal in $strDomainDN) {$strTemp += "dc=$strVal,"}; $strDomainDN = $strTemp.TrimEnd(",").toLower()
    #endregion 
     
    #region Generated Form Objects 
    $form1 = New-Object System.Windows.Forms.Form 
    $treeView1 = New-Object System.Windows.Forms.TreeView 
    $label1 = New-Object System.Windows.Forms.Label
    $textbox1 = New-Object System.Windows.Forms.TextBox
    $InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState 
    #endregion Generated Form Objects 
     
    #---------------------------------------------- 
    #Generated Event Script Blocks 
    #---------------------------------------------- 
    $button1_OnClick=  
    { 
    $form1.Close() 
     
    } 
     
    $OnLoadForm_StateCorrection= 
    {Build-TreeView 
    } 
     
    #---------------------------------------------- 
    #region Generated Form Code 
    $form1.Text = "Form" 
    $form1.Name = "form1" 
    $form1.DataBindings.DefaultDataSourceUpdateMode = 0 
    $form1.ClientSize = New-Object System.Drawing.Size(400,500) 
     
    $treeView1.Size = New-Object System.Drawing.Size(350,375)
    $treeView1.Name = "treeView1" 
    $treeView1.Location = New-Object System.Drawing.Size(15,15)
    $treeView1.DataBindings.DefaultDataSourceUpdateMode = 0 
    $treeView1.TabIndex = 0 
    $form1.Controls.Add($treeView1)
    
    $label1.Name = "label1" 
    $label1.Location = New-Object System.Drawing.Size(15,400)
    $label1.Size = New-Object System.Drawing.Size(350,20)
    $label1.Text = "Selected Value:"
    $form1.Controls.Add($label1) 
    
    $textbox1.Name = "textbox1" 
    $textbox1.Location = New-Object System.Drawing.Size(15,425)
    $textbox1.Size = New-Object System.Drawing.Size(350,20)
    $textbox1.Text = ""
    $form1.Controls.Add($textbox1) 
     
     
    #endregion Generated Form Code 
     
    #Save the initial state of the form 
    $InitialFormWindowState = $form1.WindowState 
    #Init the OnLoad event to correct the initial state of the form 
    $form1.add_Load($OnLoadForm_StateCorrection) 
    #Show the Form 
    $form1.ShowDialog()| Out-Null 
     
} #End Function 
 
#Call the Function 
GenerateForm


Monday, April 18, 2011

SCCM 2007 User/Group Rights Distribution

Example of SetPermissions.txt:
# Permissions based off available 'ClassPermissions' Property in the SMS_UserClassPermissions Class found here:  http://msdn.microsoft.com/en-us/library/cc143194.aspx
# Example Syntax:
#  Class;[ObjectName;]domain\[user|group][;Permission1[,Permission2,Permission3]]
#
# Example 1 - Sets all permissions to all classes for the specified user/group:
#   CLASS_ALL;contoso\Contoso SCCM Administrators
#
# Example 2 - Setting Specific class permissions:
#  Advertisement;contoso\Contoso SCCM Administrators;READ&MODIFY&DELETE&ADMINISTER&CREATE
#  Collection;contoso\Contoso SMS Site Administrators;READ&MODIFY&DELETE&REMOTE_CONTROL&ADVERTISE&MODIFY_RESOURCE&ADMINISTER&CREATE&VIEW_COLL_FILE&READ_RESOURCE&MODIFYCOLLECTIONSETTING&MANAGEBMC&VIEWBMC
#  MeteredProductRule;contoso\Contoso SMS Site Administrators;READ
#
# Example 3 - Instance specific permissions:
#  This section is out-of-date.  At the writing of this document, the source script has changed.  Please visit http://pleasepressanykey.blogspot.com/2011/04/vbscript-set-permissons-on-configmgr.html for the latest version of the instance-specific permissions for more information.


Script:
' ********************************************************************************
'
' Author:  Cameron Wilson (aka thepip3r)
' Date:   4/15/2011
' Credit:  Original script development and import format taken and adapted from Jonas Hettich's script for setting instance-specific permissions (4/15/2011)
'    http://pleasepressanykey.blogspot.com/2011/04/vbscript-set-permissons-on-configmgr.html
' Description: Jonas's script is designed around setting instance-specific permissions.   At my location, we almost exclusively set class-level permissions only so
'    this version of the script goes through and sets class-level permissions.  Other deviations from Jonas's script are some variable spelling and naming
'    consistency changes, the inclusion of all Class objects and all possible permissions as constants for use, and also some custom work that allows you
'    to just specify a class name and the script assigns all available rights off of a static assignment.
' 
' ********************************************************************************



Dim strChosenPermissions  
Dim strSiteServer : strSiteServer = ""  
Dim strSitecode : strSitecode = ""  
Dim objSWbemLocator : Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")  
Dim objSWbemServices : Set objSWbemServices = objSWbemLocator.ConnectServer(strSiteServer,"root/sms/site_" & strSitecode)  
  
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")  
Dim objFile : Set objFile = objFSO.OpenTextFile("SetPermissions.txt")  
Dim strCurrentLine  
Dim strObjectsType, strObjectName, strUser, strPermissions  

' Class Permission Constants
Const CP_READ      = 1
Const CP_MODIFY      = 2
Const CP_DELETE      = 4
Const CP_DISTRIBUTE     = 8
' Class Permission 16 is NOT used
Const CP_REMOTE_CONTROL    = 32
Const CP_ADVERTISE     = 64
Const CP_MODIFY_RESOURCE   = 128
Const CP_ADMINISTER     = 256
Const CP_DELETE_RESOURCE   = 512
Const CP_CREATE      = 1024
Const CP_VIEW_COLL_FILE    = 2056
Const CP_READ_RESOURCE    = 4096
Const CP_DELEGATE     = 8192
Const CP_METER      = 16384
Const CP_MANAGESQLCOMMAND   = 32768
Const CP_MANAGESTATUSFILTER   = 65536
Const CP_MANAGEFOLDER    = 131072
Const CP_NETWORKACCESS    = 262144
Const CP_IMPORTMACHINE    = 524288
Const CP_CREATETSMEDIA    = 1048576
Const CP_MODIFYCOLLECTIONSETTING = 2097152
Const CP_MANAGEOSDCERTIFICATE  = 4194304
Const CP_RECOVERUSERSTATE   = 8388608
Const CP_MANAGEBMC     = 16777216
Const CP_VIEWBMC     = 33554432
Const CP_MANAGEAI     = 67108864
Const CP_VIEWAI      = 134217728

' Class Constants
Const C_COLLECTION      = 1  ' ConfigMgr DisplayName:  'Collection'
Const C_PACKAGE       = 2  ' ConfigMgr DisplayName:  'Package'
Const C_ADVERTISEMENT     = 3  ' ConfigMgr DisplayName:  'Advertisement'
Const C_STATUSMESSAGE     = 4  ' ConfigMgr DisplayName:  'Status message'
' Class ID 5 NOT USED
Const C_SITE       = 6  ' ConfigMgr DisplayName:  'Site'
Const C_QUERY       = 7  ' ConfigMgr DisplayName:  'Query'
Const C_REPORT       = 8  ' ConfigMgr DisplayName:  'Report'
Const C_METEREDPRODUCTRULE    = 9  ' ConfigMgr DisplayName:  'Software metering rule'
Const C_APPLICABLEUPDATESSUMMARYEX  = 10 ' ConfigMgr DisplayName:  'Applicable updates summary' 
Const C_CONFIGURATIONITEM    = 11 ' ConfigMgr DisplayName:  'Configuration items'
' Class ID 12 Omitted
' Class ID 13 Omitted
Const C_OPERATINGSYSTEMINSTALLPACKAGE = 14 ' ConfigMgr DisplayName:  'OS install package'
Const C_TEMPLATE      = 15 ' ConfigMgr DisplayName:  'Deployment template'
Const C_UPDATESASSIGNMENT    = 16 ' ConfigMgr DisplayName:  'Deployment'
Const C_STATEMIGRATION     = 17 ' ConfigMgr DisplayName:  'Computer association'
Const C_IMAGEPACKAGE     = 18 ' ConfigMgr DisplayName:  'OS image'
Const C_BOOTIMAGEPACKAGE    = 19 ' ConfigMgr DisplayName:  'Boot image package'
Const C_TASKSEQUENCEPACKAGE    = 20 ' ConfigMgr DisplayName:  'Task sequence package'
Const C_DEVICESETTINGPACKAGE   = 21 ' ConfigMgr DisplayName:  'Device setting package'
Const C_DEVICESETTINGITEM    = 22 ' ConfigMgr DisplayName:  'Device setting item'
Const C_DRIVERPACKAGE     = 23 ' ConfigMgr DisplayName:  'Driver Package'
Const C_SOFTWAREUDPATESPACKAGE   = 24 ' ConfigMgr DisplayName:  'Deployment package'
Const C_DRIVER       = 25 ' ConfigMgr DisplayName:  ?





' Begin Code Execution
 
 WScript.Echo "Site Server:  " & strSiteServer 
 
'Loop the Source File  
Do While not objFile.AtEndOfStream  
 strCurrentLine = objFile.ReadLine  

 'Skip Comment and Blank lines  
 If strCurrentLine <> "" Then  
  If Not Left(strCurrentLine,1) = "#" Then  
   'Parse the information  
   arrLine = Split(strCurrentLine,";")
   
   If Ubound(arrLine) = 1 Then ' Check for 2 arguments, if so, assume set all class permissions on user/group
    ' Set Class Permissions
    WSCript.Echo "Found Custom-Level ALL Definition... Executing"
    strObjectsType = arrLine(0)  
    strUser = arrLine(1)  
    
    Call SetClassRights_All(strUser)
   ElseIf Ubound(arrLine) = 2 Then ' Check for 3 arguments, if so, assume assignment of a class-level permission on user/group
    ' Set Class Permissions
    WSCript.Echo "Found Class-Level Definition... Executing"
    strObjectsType = arrLine(0)  
    strUser = arrLine(1)  
    strPermissions = arrLine(2)
    
    Call SetClassRights(strObjectsType, strUser, strPermissions)
   ElseIf (Ubound(arrLine)) = 3 Then ' Check for 4 arguments, if so, assume assignment of an instance-level permission on an entity for a user/group
    ' Set Instance Permissions
    WSCript.Echo "Found Instance-Level Definition... Executing"
    strObjectsType = arrLine(0)  
    strObjectName = arrLine(1)  
    strUser = arrLine(2)  
    strPermissions = arrLine(3)
    
    Call SetInstanceRights(strObjectsType, strObjectName, strUser, strPermissions)
   Else
    WScript.Echo "An invalid number of parameters have been passed, please check the permissions file for proper formatting."
    WScript.Quit
   End If

     

   'Reset the Permissions for the next action  
   strChosenPermissions = 0  
  End If  
 End If  

Loop  
  
' Grabs the GUID for the instance-level object
' Not modified from Jonas's script except for variable renaming 
Function NameToID(strObjectType,strObjectName)  
 Dim colResuls, objResult  

 Select Case (strObjectType)  
  Case("Collection")  
   Set colResults = objSWbemServices.ExecQuery ("select * from SMS_Collection where Name='" & strObjectName & "'")  
   For Each objResult In colResults  
    NameToID = objResult.CollectionID  
   Next  
  Case("Package")  
   Set colResults = objSWbemServices.ExecQuery ("select * from SMS_Package where Name='" & strObjectName & "'")  
   For Each objResult In colResults  
    NameToID = objResult.PackageID  
   Next  
  Case ("Advertisement")  
   Set colResults = objSWbemServices.ExecQuery ("select * from SMS_Advertisement where AdvertisementName='" & strObjectName & "'")  
   For Each objResult In colResults  
    NameToID = objResult.AdvertisementID  
   Next  
 End Select  
End Function  

' Sets the permissions on the instance-level object
' Not modified from Jonas's script except for variable renaming 
Function SetInstanceRights(strObjectType, strObjectName, strUser, strPermissions)  
 Dim arrPermissions, strPermission  
 Dim strObjectID  
 Dim objUserInstancePermissions  
 SetInstanceRights = False  

 Set objUserInstancePermissions = objSWbemServices.Get("SMS_UserInstancePermissions")  

 'Create UserInstancePermissionsObject  
 Set objNewUserInstancePermissions = objUserInstancePermissions.SpawnInstance_  

 'Set the Object type  
 Select Case (strObjectType)   
  Case "Package"  
   objNewUserInstancePermissions.ObjectKey = 2  
  Case "Advertisement"  
   objNewUserInstancePermissions.ObjectKey = 3  
  Case "Collection"  
   objNewUserInstancePermissions.ObjectKey = 1  
  Case Else  
   WScript.Echo "Objecttype not supported"  
 End Select   


 'Set the Object ID  
 strObjectID = NameToID(strObjectType,strObjectName)  
 If strObjectID <> "" Then   
  objNewUserInstancePermissions.InstanceKey = strObjectID  
 Else  
  WScript.Echo strObjectType & " was not found: " & strObjectName  
  WScript.Quit  
 End if  

 'Set the User or Group  
 objNewUserInstancePermissions.UserName = strUser  

 'Set the Permissions  
 arrPermissions = Split(strPermissions,"&")  
 For Each strPermission In arrPermissions  
  'Parse the Permissions  
  Select Case UCASE(strPermission)  
   Case "READ"  
    strChosenPermissions = strChosenPermissions + 1  
   Case "MODIFY"  
    strChosenPermissions = strChosenPermissions + 2  
   Case "DELETE"  
    strChosenPermissions = strChosenPermissions + 4  
   Case "DISTRIBUTE"  
    strChosenPermissions = strChosenPermissions + 8  
   Case "REMOTE_CONTROL"  
    strChosenPermissions = strChosenPermissions + 32  
   Case "ADVERTISE"  
    strChosenPermissions = strChosenPermissions + 64  
   Case "MODIFY_RESOURCE"  
    strChosenPermissions = strChosenPermissions + 128  
   Case "ADMINISTER"  
    strChosenPermissions = strChosenPermissions + 256  
   Case "DELETE_RESOURCE"  
    strChosenPermissions = strChosenPermissions + 512  
   Case "CREATE"  
    strChosenPermissions = strChosenPermissions + 1024  
   Case "READ_RESOURCE"  
    strChosenPermissions = strChosenPermissions + 4096  
   Case "MODIFYCOLLECTIONSETTING"  
    strChosenPermissions = strChosenPermissions + 2097152  
   Case Else  
    WScript.Echo "Permissions not supported"  
  End Select   
 Next  

 objNewUserInstancePermissions.InstancePermissions = strChosenPermissions  


 'Creating Permissions  
 On Error Resume Next  
 objNewUserInstancePermissions.put_  


 If Err.Number = 0 Then  
  WScript.Echo "Successfully set following Permissions:"  
  WScript.Echo vbTab & " - " & strObjectType  
  WScript.Echo vbTab & " - " & strObjectName  
  WScript.Echo vbTab & " - " & strUser  
  WScript.Echo vbTab & " - " & strPermissions   
 Else  
  WScript.Echo "Error (" &Err.Description  &") when trying to create the object:"  
  WScript.Echo vbTab & " - " & strObjectType  
  WScript.Echo vbTab & " - " & strObjectName  
  WScript.Echo vbTab & " - " & strUser  
  WScript.Echo vbTab & " - " & strPermissions   
 End If  

 Set objNewUserInstancePermissions = Nothing  
End Function  


' Sets permissions on the class level object
Function SetClassRights(strObjectType, strUser, strPermissions)  
 Dim arrPermissions, strPermission  
 Dim strObjectID  
 Dim objUserClassPermissions  
 SetClassRights = False  

 Set objUserClassPermissions = objSWbemServices.Get("SMS_UserClassPermissions")  

 ' Create UserClassPermissionsObject  
 Set objNewUserClassPermissions = objUserClassPermissions.SpawnInstance_  

 ' Set the Object type  
 ' Here we specify all classes for greater script flexibility
 Select Case UCase(strObjectType)   
  Case "COLLECTION"
   objNewUserClassPermissions.ObjectKey = C_COLLECTION  
  Case "PACKAGE"
   objNewUserClassPermissions.ObjectKey = C_PACKAGE  
  Case "ADVERTISEMENT"
   objNewUserClassPermissions.ObjectKey = C_ADVERTISEMENT  
  Case "STATUSMESSAGE"
   objNewUserClassPermissions.ObjectKey = C_STATUSMESSAGE
  Case "SITE"
   objNewUserClassPermissions.ObjectKey = C_SITE
  Case "QUERY"
   objNewUserClassPermissions.ObjectKey = C_QUERY
  Case "REPORT"
   objNewUserClassPermissions.ObjectKey = C_REPORT
  Case "METEREDPRODUCTRULE"
   objNewUserClassPermissions.ObjectKey = C_METEREDPRODUCTRULE
  Case "APPLICABLEUPDATESSUMMARY"
   objNewUserClassPermissions.ObjectKey = C_APPLICABLEUPDATESSUMMARYEX
  Case "CONFIGURATIONITEM"
   objNewUserClassPermissions.ObjectKey = C_CONFIGURATIONITEM
  Case "OPERATINGSYSTEMINSTALLPACKAGE"
   objNewUserClassPermissions.ObjectKey = C_OPERATINGSYSTEMINSTALLPACKAGE
  Case "DEPLOYMENTTEMPLATE"
   objNewUserClassPermissions.ObjectKey = C_TEMPLATE
  Case "UPDATESASSIGNMENT"
   objNewUserClassPermissions.ObjectKey = C_UPDATESASSIGNMENT
  Case "STATEMIGRATION"
   objNewUserClassPermissions.ObjectKey = C_STATEMIGRATION
  Case "IMAGEPACKAGE"
   objNewUserClassPermissions.ObjectKey = C_IMAGEPACKAGE
  Case "BOOTIMAGEPACKAGE"
   objNewUserClassPermissions.ObjectKey = C_BOOTIMAGEPACKAGE
  Case "TASKSEQUENCEPACKAGE"
   objNewUserClassPermissions.ObjectKey = C_TASKSEQUENCEPACKAGE
  Case "DEVICESETTINGPACKAGE"
   objNewUserClassPermissions.ObjectKey = C_DEVICESETTINGPACKAGE
  Case "DEVICESETTINGITEM"
   objNewUserClassPermissions.ObjectKey = C_DEVICESETTINGITEM
  Case "DRIVERPACKAGE"
   objNewUserClassPermissions.ObjectKey = C_DRIVERPACKAGE
  Case "SOFTWAREUPDATESPACKAGE"
   objNewUserClassPermissions.ObjectKey = C_SOFTWAREUDPATESPACKAGE
  Case "DRIVER"
   objNewUserClassPermissions.ObjectKey = C_SOFTWAREUDPATESPACKAGE
  Case Else  
   WScript.Echo "Object type unknown:  " & strObjectType 
 End Select   

 ' Set the User or Group  
 objNewUserClassPermissions.UserName = strUser  

 ' Set the Permissions  
 ' Included all permissions avaiable for all classes.
 arrPermissions = Split(strPermissions,"&")  
 For Each strPermission In arrPermissions  
  'Parse the Permissions  
  Select Case UCASE(strPermission)  
   Case "READ"  
    strChosenPermissions = strChosenPermissions + CP_READ  
   Case "MODIFY"  
    strChosenPermissions = strChosenPermissions + CP_MODIFY  
   Case "DELETE"  
    strChosenPermissions = strChosenPermissions + CP_DELETE  
   Case "DISTRIBUTE"  
    strChosenPermissions = strChosenPermissions + CP_DISTRIBUTE  
   Case "REMOTE_CONTROL"  
    strChosenPermissions = strChosenPermissions + CP_REMOTE_CONTROL  
   Case "ADVERTISE"  
    strChosenPermissions = strChosenPermissions + CP_ADVERTISE  
   Case "MODIFY_RESOURCE"  
    strChosenPermissions = strChosenPermissions + CP_MODIFY_RESOURCE  
   Case "ADMINISTER"  
    strChosenPermissions = strChosenPermissions + CP_ADMINISTER  
   Case "DELETE_RESOURCE"  
    strChosenPermissions = strChosenPermissions + CP_DELETE_RESOURCE  
   Case "CREATE"  
    strChosenPermissions = strChosenPermissions + CP_CREATE
   Case "READ_RESOURCE"  
    strChosenPermissions = strChosenPermissions + CP_READ_RESOURCE
   Case "VIEW_COLL_FILE"  
    strChosenPermissions = strChosenPermissions + CP_VIEW_COLL_FILE 
   Case "DELEGATE"  
    strChosenPermissions = strChosenPermissions + CP_DELEGATE
   Case "METER"  
    strChosenPermissions = strChosenPermissions + CP_METER
   Case "MANAGESQLCOMMAND"  
    strChosenPermissions = strChosenPermissions + CP_MANAGESQLCOMMAND
   Case "MANAGESTATUSFILTER"  
    strChosenPermissions = strChosenPermissions + CP_MANAGESTATUSFILTER
   Case "MANAGEFOLDER"  
    strChosenPermissions = strChosenPermissions + CP_MANAGEFOLDER
   Case "NETWORKACCESS"  
    strChosenPermissions = strChosenPermissions + CP_NETWORKACCESS
   Case "IMPORTMACHINE"  
    strChosenPermissions = strChosenPermissions + CP_IMPORTMACHINE
   Case "CREATETSMEDIA"  
    strChosenPermissions = strChosenPermissions + CP_CREATETSMEDIA
   Case "MODIFYCOLLECTIONSETTING"  
    strChosenPermissions = strChosenPermissions + CP_MODIFYCOLLECTIONSETTING
   Case "MANAGEOSDCERTIFICATE"  
    strChosenPermissions = strChosenPermissions + CP_MANAGEOSDCERTIFICATE
   Case "RECOVERUSERSTATE"  
    strChosenPermissions = strChosenPermissions + CP_RECOVERUSERSTATE
   Case "MANAGEBMC"  
    strChosenPermissions = strChosenPermissions + CP_MANAGEBMC
   Case "VIEWBMC"  
    strChosenPermissions = strChosenPermissions + CP_VIEWBMC
   Case "MANAGEAI"  
    strChosenPermissions = strChosenPermissions + CP_MANAGEAI
   Case "VIEWAI"  
    strChosenPermissions = strChosenPermissions + CP_VIEWAI
    

   ' BEGIN:  Custom Class 'ALL' Descriptors 
   ' This allows for just the specification of a user/group for a class and these are all available permissions for each class

   Case "ADVERTISEMENT_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "APPLICABLE_UPDATES_SUMMARY_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE
   Case "ASSET_INTELLIGENCE_ALL"
    strChosenPermissions = CP_ADMINISTER + CP_DELEGATE + CP_MANAGEAI + CP_VIEWAI
   Case "BOOT_IMAGE_PACKAGE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_DISTRIBUTE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "COLLECTION_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_REMOTE_CONTROL + CP_ADVERTISE + CP_MODIFY_RESOURCE + CP_ADMINISTER + CP_DELETE_RESOURCE + CP_CREATE + CP_VIEW_COLL_FILE + CP_READ_RESOURCE + CP_DELEGATE + CP_MODIFYCOLLECTIONSETTING + CP_MANAGEBMC + CP_VIEWBMC
   Case "COMPUTER_ASSOCIATION_ALL"
    strChosenPermissions = CP_READ + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER + CP_RECOVERUSERSTATE
   Case "CONFIGURATION_ITEMS_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_DISTRIBUTE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER + CP_NETWORKACCESS
   Case "DEPLOYMENT_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE
   Case "DEPLOYMENT_PACKAGE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_DISTRIBUTE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "DEPLOYMENT_TEMPLATE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE 
   Case "DEVICE_DRIVER_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "DEVICE_SETTING_ITEM_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE
   Case "DEVICE_SETTING_PACKAGE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_DISTRIBUTE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "DRIVER_PACKAGE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_DISTRIBUTE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "OS_IMAGE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_DISTRIBUTE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "OS_INSTALL_PACKAGE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_DISTRIBUTE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "PACKAGE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_DISTRIBUTE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "QUERY_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "REPORT_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "SITE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_METER + CP_MANAGESQLCOMMAND + CP_MANAGESTATUSFILTER + CP_IMPORTMACHINE + CP_MANAGEOSDCERTIFICATE
   Case "SOFTWARE_METERING_RULE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER
   Case "STATUS_MESSAGE_ALL"
    strChosenPermissions = CP_READ + CP_DELETE + CP_ADMINISTER + CP_CREATE
   Case "TASK_SEQUENCE_PACKAGE_ALL"
    strChosenPermissions = CP_READ + CP_MODIFY + CP_DELETE + CP_ADMINISTER + CP_CREATE + CP_DELEGATE + CP_MANAGEFOLDER + CP_CREATETSMEDIA
    
   ' END:  Custom Class 'ALL' Descriptors 
    
   Case ""
   Case Else  
    WScript.Echo "Permission not supported:  " & strPermission 
    WScript.Echo "Object Type:  " & strObjectType
  End Select   
 Next  

 ' Set the permissions
 objNewUserClassPermissions.ClassPermissions = strChosenPermissions  


 'Creating Permissions  
 'On Error Resume Next  
 objNewUserClassPermissions.put_  


 'If Err.Number = 0 Then  
 ' WScript.Echo "Successfully set following Permissions:"  
 ' WScript.Echo vbTab & " - " & strObjectType  
 ' WScript.Echo vbTab & " - " & strObjectName  
 ' WScript.Echo vbTab & " - " & strUser  
 ' WScript.Echo vbTab & " - " & strPermissions   
 'Else  
 ' WScript.Echo "Error (" &Err.Description  &") when trying to create the object:"  
 ' WScript.Echo vbTab & " - " & strObjectType  
 ' WScript.Echo vbTab & " - " & strObjectName  
 ' WScript.Echo vbTab & " - " & strUser  
 ' WScript.Echo vbTab & " - " & strPermissions   
 'End If  

 Set objNewUserClassPermissions = Nothing  
End Function  

' Sets all permissions on all classes for the given user/group
Function SetClassRights_All(strUser)
 Call SetClassRights("COLLECTION", strUser, "COLLECTION_ALL")
 Call SetClassRights("PACKAGE", strUser, "PACKAGE_ALL")
 Call SetClassRights("ADVERTISEMENT", strUser, "ADVERTISEMENT_ALL")
 Call SetClassRights("STATUSMESSAGE", strUser, "STATUS_MESSAGE_ALL")
 Call SetClassRights("SITE", strUser, "SITE_ALL")
 Call SetClassRights("QUERY", strUser, "QUERY_ALL")
 Call SetClassRights("REPORT", strUser, "REPORT_ALL")
 Call SetClassRights("METEREDPRODUCTRULE", strUser, "SOFTWARE_METERING_RULE_ALL")
 Call SetClassRights("APPLICABLEUPDATESSUMMARY", strUser, "APPLICABLE_UPDATES_SUMMARY_ALL")
 Call SetClassRights("CONFIGURATIONITEM", strUser, "CONFIGURATION_ITEMS_ALL")
 Call SetClassRights("OPERATINGSYSTEMINSTALLPACKAGE", strUser, "OS_INSTALL_PACKAGE_ALL")
 Call SetClassRights("DEPLOYMENTTEMPLATE", strUser, "DEPLOYMENT_TEMPLATE_ALL")
 Call SetClassRights("UPDATESASSIGNMENT", strUser, "DEPLOYMENT_ALL")
 Call SetClassRights("STATEMIGRATION", strUser, "COMPUTER_ASSOCIATION_ALL")
 Call SetClassRights("IMAGEPACKAGE", strUser, "OS_IMAGE_ALL")
 Call SetClassRights("BOOTIMAGEPACKAGE", strUser, "BOOT_IMAGE_PACKAGE_ALL")
 Call SetClassRights("TASKSEQUENCEPACKAGE", strUser, "TASK_SEQUENCE_PACKAGE_ALL")
 Call SetClassRights("DEVICESETTINGPACKAGE", strUser, "DEVICE_SETTING_PACKAGE_ALL")
 Call SetClassRights("DEVICESETTINGITEM", strUser, "DEVICE_SETTING_ITEM_ALL")
 Call SetClassRights("DRIVERPACKAGE", strUser, "DRIVER_PACKAGE_ALL")
 Call SetClassRights("SOFTWAREUPDATESPACKAGE", strUser, "DEPLOYMENT_PACKAGE_ALL")
 'Call SetClassRights("DRIVER", strUser, "DRIVER_ALL")
End Function