4/13/2011

vbScript - set permissons on ConfigMgr Objects in bulk

This little vbscript loops throught the file SetPermissons.txt and creates all class and instance permissons for your ConfigMgr Objects which are defined

File Structure must be:
1st postition: Object Level (Possible Values: Class(C) or Instance (I))
2nd postition: Object Type (COLLECTION, ADVERTISEMENT, PACKAGE, ...)
3rd postition: Object Name (If Object Level is Class, the Name is not used. Best value in this case is "N/A")
4th postition: Username (Format: domain\username)
5th postition: Permissons (Format: Permisson1&Permisson2&...) - For all Permissons on an Object use keyword "FULL". Check the lower part of the vbScript for detailed information. Also note that the permissons have to make sense. So please first check the available permissons for each object in your ConfigMgr Console

# are and blank lines are ignored
# are available for comments

The SetPermissons.txt file should look like this:

###########################################################################
############################### EXAMPLES ##################################
###########################################################################
### I;COLLECTION;All Systems;mydomain\myuser;READ&MODIFY&READ_RESOURCE
### I;COLLECTION;All Systems;mydomain\myuser2;READ&ADVERTISE&DELETE_RESOURCE
### I;PACKAGE;Adobe_Reader;mydomain\myuser2;DISTRIBUTE
### I;PACKAGE;Adobe_Reader;mydomain\myuser;MODIFY&DISTRIBUTE
### I;ADVERTISEMENT;Install_Adobe_Reader;mydomain\myuse;FULL
### C;SITE;N/A;mydomain\myuser;FULL
### C;TASKSEQUENCE;N/A;mydomain\myuser2;READ&MODIFY
###########################################################################
###########################################################################
###########################################################################

#Set Collections Permissons
I;Collection;MyCollectionABC;mydomain\BillGates;READ&MODIFY&READ_RESOURCE
I;Collection;MyCollectionXYZ;mydomain\SteveBallmer;READ&ADVERTISE&DELETE_RESOURCE

#Set Package Permissons
I;PACKAGE;Adobe_Reader;mydomain\BillGates;DISTRIBUTE
I;PACKAGE;Adobe_Reader;mydomain\SteveBallmer;READ&DISTRIBUTE
I;PACKAGE;Adobe_Reader;mydomain\ElvisPresley;READ&MODIFY&DISTRIBUTE

#Set Advertisement Permissons
I;Advertisement;Repair_Java;mydomain\SteveBallmer;READ

#Set Permissons for the new HelpDesk Employee
I;COLLECTION;MyCollection;mydomain\johnwayne;READ
I;COLLECTION;HisCollection;mydomain\johnwayne;READ&MODFIY
I;Advertisement;Uninstall_7ZIP;mydomain\johnwayne;READ&DELETE
C;COLLECTION;N/A;mydomain\johnwayne;READ
C;SITE;N/A;mydomain\johnwayne;READ&IMPORTMACHINE

#Set Permissons for the Group OSD Admins
C;OSINSTALLPACKAGE;N/A;mydomain\OSDAdmins;FULL
C;COMPUTERASSOCIATION;N/A;mydomain\OSDAdmins;READ&DELETE&ADMINISTER&CREATE
C;OSIMAGE;N/A;mydomain\OSDAdmins;FULL
C;TASKSEQUENCE;N/A;mydomain\OSDAdmins;FULL
C;DRIVERPACKAGE;N/A;mydomain\OSDAdmins;FULL
C;DEVICEDRIVER;N/A;mydomain\OSDAdmins;FULL


The vbScript is the below code - Have fun ;)
Note: There's not build in a lot of error handling, so please first test it carefully

  1. '************************************************************************************************************  
  2. ' Jonas Hettich  
  3. '************************************************************************************************************  
  4. '  
  5. ' Ver 1.00 - 13.04.2011 - initial version  
  6. '  
  7. ' What this script does:  
  8. ' This Scripts creates the Permissons defined in the file SetPermissons.txt  
  9. '  
  10. ' Not Supported: Instace Rights for Drivers, Asset Intelligence  
  11. '************************************************************************************************************  
  12.   
  13. result = MsgBox("Do you really want to create the Collection Permissons?", vbYesNo)  
  14. If result = vbNo Then WScript.Quit  
  15.   
  16. Dim strChoosenPermissons  
  17. Dim strSiteServer : strSiteServer = "<servername>"  
  18. Dim strSitecode : strSitecode = "<sitecode>"  
  19. Dim objSWbemLocator : Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")  
  20. Dim objSWbemServices : Set objSWbemServices = objSWbemLocator.ConnectServer(strSiteServer,"root/sms/site_" & strSitecode)  
  21.   
  22. Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")  
  23. Dim objFile : Set objFile = objFSO.OpenTextFile("SetPermissons.txt")  
  24. Dim strCurrentLine  
  25. Dim strObjectsType, strObjectName, strUser, strPermissons, strObjectEnv  
  26.   
  27. 'Loop the Source File  
  28. Do While not objFile.AtEndOfStream  
  29.  strCurrentLine = objFile.ReadLine  
  30.    
  31.  'Skip Comment and Blank lines  
  32.  If strCurrentLine <> "" Then  
  33.   If Not Left(strCurrentLine,1) = "#" Then  
  34.      
  35.    'Parse the information  
  36.    strObjectEnv = Ucase(Split(strCurrentLine,";")(0))  
  37.    strObjectsType = Ucase(Split(strCurrentLine,";")(1))  
  38.    strObjectName = Ucase(Split(strCurrentLine,";")(2))  
  39.    strUser = Ucase(Split(strCurrentLine,";")(3))  
  40.    strPermissons = Ucase(Split(strCurrentLine,";")(4))  
  41.      
  42.    Call SetInstanceRights(strObjectEnv,strObjectsType, strObjectName, strUser, strPermissons)  
  43.   
  44.    'Reset the Permissons for the next action  
  45.    strChoosenPermissons = 0  
  46.      
  47.   End If  
  48.  End If  
  49.    
  50.   
  51. Loop  
  52.   
  53. Function NameToID(strObjectType,strObjectName)  
  54. Dim colResuls, objResult  
  55.   
  56. Select Case (strObjectType)  
  57. Case("COLLECTION")  
  58.   
  59.  Set colResults = objSWbemServices.ExecQuery ("select * from SMS_Collection where Name='" & strObjectName & "'")  
  60.  For Each objResult In colResults  
  61.   NameToID = objResult.CollectionID  
  62.  Next  
  63.   
  64. Case("PACKAGE")  
  65.   
  66.  Set colResults = objSWbemServices.ExecQuery ("select * from SMS_Package where Name='" & strObjectName & "'")  
  67.  For Each objResult In colResults  
  68.   NameToID = objResult.PackageID  
  69.  Next  
  70.    
  71. Case ("ADVERTISEMENT")  
  72.   
  73.  Set colResults = objSWbemServices.ExecQuery ("select * from SMS_Advertisement where AdvertisementName='" & strObjectName & "'")  
  74.  For Each objResult In colResults  
  75.   NameToID = objResult.AdvertisementID  
  76.  Next  
  77.    
  78. Case ("TASKSEQUENCE")  
  79.   
  80.  Set colResults = objSWbemServices.ExecQuery ("Select * from SMS_TaskSequencePackage where Name='" & strObjectName & "'")  
  81.  For Each objResult In colResults  
  82.   NameToID = objResult.PackageID  
  83.  Next  
  84.    
  85. Case ("OSINSTALLPACKAGE")  
  86.   
  87.  Set colResults = objSWbemServices.ExecQuery ("Select * from SMS_OperatingSystemInstallPackage where Name='" & strObjectName & "'")  
  88.  For Each objResult In colResults  
  89.   NameToID = objResult.PackageID  
  90.  Next  
  91.   
  92. Case ("OSIMAGE")  
  93.   
  94.  Set colResults = objSWbemServices.ExecQuery ("Select * from SMS_ImagePackage where Name='" & strObjectName & "'")  
  95.  For Each objResult In colResults  
  96.   NameToID = objResult.PackageID  
  97.  Next   
  98.   
  99. Case ("BOOTIMAGE")  
  100.   
  101.  Set colResults = objSWbemServices.ExecQuery ("Select * from SMS_BootImagePackage where Name='" & strObjectName & "'")  
  102.  For Each objResult In colResults  
  103.   NameToID = objResult.PackageID  
  104.  Next    
  105.   
  106. Case ("DRIVERPACKAGE")  
  107.   
  108.  Set colResults = objSWbemServices.ExecQuery ("Select * from SMS_DriverPackage where Name='" & strObjectName & "'")  
  109.  For Each objResult In colResults  
  110.   NameToID = objResult.PackageID  
  111.  Next  
  112. Case Else  
  113.  Log "Error: Objecttype not supported"  
  114.  Exit Function  
  115. End Select  
  116.   
  117. End Function  
  118.   
  119. Function SetInstanceRights(ObjectEnv, ObjectType, ObjectName, User, Permissons)  
  120.  Dim arrPermissons, strPermisson  
  121.  Dim strObjectID  
  122.  Dim objUserPermissions  
  123.    
  124.  'Choose between Class and Instance Permissons  
  125.  If ObjectEnv = "I" Then  
  126.   Set objUserPermissions = objSWbemServices.Get("SMS_UserInstancePermissions")  
  127.   Log vbNewLine &"*** Configure Instance Permissons ***"  
  128.  ElseIf ObjectEnv = "C" Then  
  129.   Set objUserPermissions = objSWbemServices.Get("SMS_UserClassPermissions")  
  130.   Log vbNewLine &"*** Configure Class Permissons ***"  
  131.  Else  
  132.   Log "Error: Object Environment not available. Must be Class(C) or Instance(I)"  
  133.   WScript.Quit  
  134.  End If  
  135.    
  136.    
  137.  'Create UserInstancePermissonsObject  
  138.  Set objNewUserPermissions = objUserPermissions.SpawnInstance_  
  139.    
  140.  'Set the Objecttype  
  141.  Select Case (ObjectType)  
  142.  Case "COLLECTION"  
  143.   objNewUserPermissions.ObjectKey = 1  
  144.  Case "PACKAGE"  
  145.   objNewUserPermissions.ObjectKey = 2  
  146.  Case "ADVERTISEMENT"  
  147.   objNewUserPermissions.ObjectKey = 3  
  148.  Case "STATUSMESSAGE"  
  149.   objNewUserPermissions.ObjectKey = 4  
  150.  Case "SITE"  
  151.   objNewUserPermissions.ObjectKey = 6  
  152.  Case "QUERY"  
  153.   objNewUserPermissions.ObjectKey = 7  
  154.  Case "REPORT"  
  155.   objNewUserPermissions.ObjectKey = 8  
  156.  Case "SOFTWAREMETERINGRULE"  
  157.   objNewUserPermissions.ObjectKey = 9  
  158.  Case "APPLICABLEUPDATESSUMMARY"  
  159.   objNewUserPermissions.ObjectKey = 10  
  160.  Case "CONFIGURATIONITEMS"  
  161.   objNewUserPermissions.ObjectKey = 11  
  162.  Case "OSINSTALLPACKAGE"  
  163.   objNewUserPermissions.ObjectKey = 14  
  164.  Case "DEPLOYMENTTEMPLATE"  
  165.   objNewUserPermissions.ObjectKey = 15  
  166.  Case "DEPLOYMENT"  
  167.   objNewUserPermissions.ObjectKey = 16  
  168.  Case "COMPUTERASSOCIATION"  
  169.   objNewUserPermissions.ObjectKey = 17  
  170.  Case "OSIMAGE"  
  171.   objNewUserPermissions.ObjectKey = 18  
  172.  Case "BOOTIMAGE"  
  173.   objNewUserPermissions.ObjectKey = 19  
  174.  Case "TASKSEQUENCE"  
  175.   objNewUserPermissions.ObjectKey = 20  
  176.  Case "DEVICESETTINGPACKAGE"  
  177.   objNewUserPermissions.ObjectKey = 21  
  178.  Case "DEVICESETTINGITEM"  
  179.   objNewUserPermissions.ObjectKey = 22  
  180.  Case "DRIVERPACKAGE"  
  181.   objNewUserPermissions.ObjectKey = 23  
  182.  Case "DEPLYOMENTPACKAGE"  
  183.   objNewUserPermissions.ObjectKey = 24  
  184.  Case "DEVICEDRIVER"  
  185.   objNewUserPermissions.ObjectKey = 25  
  186.  Case Else  
  187.   Log "Error: Objecttype not supported"  
  188.   Exit Function  
  189.  End Select   
  190.    
  191.    
  192.  'Set the Object ID  
  193.  If ObjectEnv = "I" Then  
  194.   strObjectID = NameToID(ObjectType,ObjectName)  
  195.   If strObjectID <> "" Then   
  196.    objNewUserPermissions.InstanceKey = strObjectID  
  197.   Else  
  198.    Log "Error: " &ObjectType &" was not found: " &ObjectName  
  199.    WScript.Quit  
  200.   End If  
  201.  End If  
  202.    
  203.  'Set the User or Group  
  204.  objNewUserPermissions.UserName = User  
  205.    
  206.  'Set the Permissons  
  207.  If Permissons = "FULL" Then  
  208.   'Set Full Permissons String  
  209.   Permissons = FullPermissons(ObjectType,ObjectEnv)  
  210.  End If  
  211.   
  212.    
  213.  arrPermissons = Split(Permissons,"&")  
  214.  For Each strPermisson In arrPermissons  
  215.     
  216.   'Parse the Permissons  
  217.   'http://msdn.microsoft.com/en-us/library/cc143194.aspx  
  218.   Select Case UCASE(strPermisson)  
  219.   Case "READ"  
  220.    strChoosenPermissons = strChoosenPermissons + 1  
  221.   Case "MODIFY"  
  222.    strChoosenPermissons = strChoosenPermissons + 2  
  223.   Case "DELETE"  
  224.    strChoosenPermissons = strChoosenPermissons + 4  
  225.   Case "DISTRIBUTE"  
  226.    strChoosenPermissons = strChoosenPermissons + 8  
  227.   Case "REMOTE_CONTROL"  
  228.    strChoosenPermissons = strChoosenPermissons + 32  
  229.   Case "ADVERTISE"  
  230.    strChoosenPermissons = strChoosenPermissons + 64  
  231.   Case "MODIFY_RESOURCE"  
  232.    strChoosenPermissons = strChoosenPermissons + 128  
  233.   Case "ADMINISTER"  
  234.    strChoosenPermissons = strChoosenPermissons + 256  
  235.   Case "DELETE_RESOURCE"  
  236.    strChoosenPermissons = strChoosenPermissons + 512  
  237.   Case "CREATE"  
  238.    If ObjectEnv = "I" And ObjectType = "COLLECTION" Then  
  239.     'Collection Instances do no have the permissons CREATE, ADMINISTER, DELEGATE  
  240.     Log "ERROR: CREATE, ADMINISTER and DELEGATE permissons are not possible on Collection Instances"  
  241.     Exit Function  
  242.    Else  
  243.     strChoosenPermissons = strChoosenPermissons + 1024  
  244.    End If  
  245.   Case "VIEWCOLLECTEDFILES"  
  246.    strChoosenPermissons = strChoosenPermissons + 2048  
  247.   Case "READ_RESOURCE"  
  248.    strChoosenPermissons = strChoosenPermissons + 4096  
  249.   Case "DELEGATE"  
  250.    strChoosenPermissons = strChoosenPermissons + 8192  
  251.   Case "METER"  
  252.    strChoosenPermissons = strChoosenPermissons + 16384  
  253.   Case "MANAGESQLCOMMAND"  
  254.    strChoosenPermissons = strChoosenPermissons + 32768  
  255.   Case "MANAGESTATUSFILTER"  
  256.    strChoosenPermissons = strChoosenPermissons + 65536  
  257.   Case "MANAGEFOLDERS"  
  258.    strChoosenPermissons = strChoosenPermissons + 131072  
  259.   Case "NETWORKACCESS"  
  260.    strChoosenPermissons = strChoosenPermissons + 262144  
  261.   Case "IMPORTMACHINE"  
  262.    strChoosenPermissons = strChoosenPermissons + 524288  
  263.   Case "CREATETASKSEQUENCEMEDIA"  
  264.    strChoosenPermissons = strChoosenPermissons + 1048576  
  265.   Case "MODIFYCOLLECTIONSETTING"  
  266.    strChoosenPermissons = strChoosenPermissons + 2097152  
  267.   Case "MANAGEOSDCERTIFICATE"  
  268.    strChoosenPermissons = strChoosenPermissons + 4194304  
  269.   Case "RECOVERUSERSTATE"  
  270.    strChoosenPermissons = strChoosenPermissons + 8388608  
  271.   Case "MANAGEMGMTCONROLLERS"  
  272.    strChoosenPermissons = strChoosenPermissons + 16777216  
  273.   Case "VIEWMGMTCONROLLERS"  
  274.    strChoosenPermissons = strChoosenPermissons + 33554432  
  275.   Case Else  
  276.    Log "Error: Permissons not supported"  
  277.   End Select   
  278.       
  279.  Next  
  280.   
  281.   
  282.  If ObjectEnv = "I" Then  
  283.   objNewUserPermissions.InstancePermissions = strChoosenPermissons  
  284.  ElseIf ObjectEnv = "C" Then  
  285.   objNewUserPermissions.ClassPermissions  = strChoosenPermissons  
  286.  End If  
  287.   
  288.    
  289.  'Creating Permissons  
  290.  On Error Resume Next  
  291.  objNewUserPermissions.put_  
  292.    
  293.    
  294.  If Err.Number = 0 Then  
  295.   Log "Successfully set following permissons:"  
  296.   Log vbTab &" - ObjectType: " &ObjectType  
  297.   Log vbTab &" - ObjectName: " &ObjectName  
  298.   Log vbTab &" - User: " &User  
  299.   Log vbTab &" - Permissons: " &Permissons   
  300.  Else  
  301.   Log "Error (" &Err.Description  &") when trying to create the object:"  
  302.   Log vbTab &" - ObjectType: " &ObjectType  
  303.   Log vbTab &" - ObjectName: " &ObjectName  
  304.   Log vbTab &" - User: " &User  
  305.   Log vbTab &" - Permissons: " &Permissons   
  306.  End If  
  307.   
  308.    
  309.  Set objNewUserPermissions = Nothing  
  310.     
  311. End Function  
  312.   
  313.   
  314. Function FullPermissons(ObjectType,ObjectEnv)  
  315.   
  316. Select Case (ObjectType)  
  317.   
  318. Case "SITE"  
  319.  FullPermissons = "IMPORTMACHINE&DELEGATE&ADMINISTER&CREATE&DELETE&READ&MODIFY&MANAGEOSDCERTIFICATE&MANAGESTATUSFILTER&MANAGESQLCOMMAND&METER"  
  320. Case "OSINSTALLPACKAGE"  
  321.  FullPermissons = "READ&DISTRIBUTE&MODIFY&DELETE&ADMINISTER&CREATE&MANAGEFOLDERS&DELEGATE"  
  322. Case "OSIMAGE"  
  323.  FullPermissons = "READ&DISTRIBUTE&MODIFY&DELETE&ADMINISTER&CREATE&MANAGEFOLDERS&DELEGATE"  
  324. Case "TASKSEQUENCE"  
  325.  FullPermissons = "READ&CREATETASKSEQUENCEMEDIA&MODIFY&DELETE&ADMINISTER&CREATE&MANAGEFOLDERS&DELEGATE"  
  326. Case "DRIVERPACKAGE"  
  327.  FullPermissons = "READ&DISTRIBUTE&MODIFY&DELETE&ADMINISTER&CREATE&MANAGEFOLDERS&DELEGATE"  
  328. Case "STATUSMESSAGE"   
  329.  FullPermissons = "READ&DELETE&CREATE&ADMINISTER"  
  330. Case "QUERY"  
  331.  FullPermissons ="READ&MODIFY&DELETE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS"  
  332. Case "REPORT"  
  333.  FullPermissons = "READ&MODIFY&DELETE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS"  
  334. Case "SOFTWAREMETERINGRULE"  
  335.  FullPermissons = "READ&MODIFY&DELETE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS"  
  336. Case "APPLICABLEUPDATESSUMMARY"  
  337.  FullPermissons = "READ&MODIFY&DELETE&ADMINISTER&CREATE&DELEGATE"  
  338. Case "CONFIGURATIONITEMS"  
  339.  FullPermissons = "READ&MODIFY&DELETE&DISTRIBUTE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS&NETWORKACCESS"  
  340. Case "DEPLOYMENTTEMPLATE"  
  341.  FullPermissons = "READ&MODIFY&DELETE&ADMINISTER&CREATE&DELEGATE"  
  342. Case "DEPLOYMENT"  
  343.  FullPermissons = "READ&MODIFY&DELETE&ADMINISTER&CREATE&DELEGATE"  
  344. Case "DEVICESETTINGPACKAGE"  
  345.  FullPermissons ="READ&MODIFY&DELETE&DISTRIBUTE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS"  
  346. Case "DEVICESETTINGITEM"  
  347.  FullPermissons = "READ&MODIFY&DELETE&ADMINISTER&CREATE&DELEGATE"  
  348. Case "DEPLYOMENTPACKAGE"  
  349.  FullPermissons = "READ&MODIFY&DELETE&DISTRIBUTE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS"  
  350. Case "COLLECTION"  
  351.  If ObjectEnv = "C" Then  
  352.   FullPermissons = "READ&MODIFY&DELETE&CREATE&REMOTE_CONTROL&ADVERTISE&MODIFY_RESOURCE&ADMINISTER&DELETE_RESOURCE&VIEWCOLLECTEDFILES&READ_RESOURCE&DELEGATE&MODIFYCOLLECTIONSETTING&MANAGEMGMTCONROLLERS&VIEWMGMTCONROLLERS"  
  353.  ElseIf ObjectEnv = "I" Then  
  354.   'Collection Instances do no have the permissons CREATE, ADMINISTER, DELEGATE  
  355.   FullPermissons = "READ&MODIFY&DELETE&REMOTE_CONTROL&ADVERTISE&MODIFY_RESOURCE&DELETE_RESOURCE&VIEWCOLLECTEDFILES&READ_RESOURCE&MODIFYCOLLECTIONSETTING&MANAGEMGMTCONROLLERS&VIEWMGMTCONROLLERS"  
  356.  End If  
  357. Case "PACKAGE"  
  358.  FullPermissons = "READ&MODIFY&DELETE&DISTRIBUTE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS"  
  359. Case "ADVERTISEMENT"  
  360.  FullPermissons = "READ&MODIFY&DELETE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS"  
  361. Case "DRIVERPACKAGE"  
  362.  FullPermissons = "READ&MODIFY&DISTRIBUTE&DELETE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS"  
  363. Case "COMPUTERASSOCIATION"  
  364.  FullPermissons = "READ&DELETE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS&RECOVERUSERSTATE"  
  365. Case "DEVICEDRIVER"  
  366.  FullPermissons = "READ&MODIFY&DELETE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS"  
  367. Case "BOOTIMAGE"  
  368.  FullPermissons = "READ&MODIFY&DELETE&DISTRIBUTE&ADMINISTER&CREATE&DELEGATE&MANAGEFOLDERS"  
  369. Case Else  
  370.  Log "Permissons not supported"  
  371. End Select  
  372.   
  373. End Function  
  374.   
  375. Function Log(strTextToLog)  
  376.  WScript.Echo strTextToLog  
  377.     Dim objFile, objLogFile, objLogFile2  
  378.  Dim strFilenameWithoutExtension, intMaxFileSize, n   
  379.         intMaxFileSize = 15 * 1024 * 1024 '15MB   
  380.         'strip ".vbs" from the full path scriptname   
  381.         strFilenameWithoutExtension= left(WScript.ScriptFullName,len(WScript.ScriptFullName)-4)   
  382.     On Error Resume Next   
  383.         n = -1   
  384.         'we need to check the current logfile size 1st - open the current logfile   
  385.         Set objFile = objFSO.getfile(strFilenameWithoutExtension & ".log")   
  386.         'check if the the current logfile is bigger than the max file size   
  387.     If objFile.Size > intMaxFileSize Then   
  388.         'it's bigger - so open the backup log file   
  389.         Set objLogFile2 = objFSO.getfile(strFilenameWithoutExtension & ".lo_")   
  390.         'delete the backup file   
  391.         objLogFile2.Delete   
  392.         'rename the original file to "*.lo_"   
  393.         objFile.name = left(objFile.name, len(objFile.name)-1) & "_"   
  394.                 'close the file   
  395.                 objFile.close   
  396.     End If   
  397.     Set objLogFile = objFSO.opentextfile(strFilenameWithoutExtension & ".log", 8, True)   
  398.     'objLogFile.writeline Date & " - " & Time & " - """ & strTextToLog & """"   
  399.         objLogFile.writeline Date & " - " & Time & " - " & " - """ & strTextToLog & """"   
  400.   If len(strTextToLog) > 78 then strTextToLog = left(strTextToLog,76) & "..."  
  401.         'Log strTextToLog  
  402.     objLogFile.Close   
  403.     Set objFile = Nothing   
  404.     Set objFile2 = Nothing   
  405.     Set oLogFile = Nothing   
  406.     Set oFSOLog = Nothing   
  407.     If Err Then Err.Clear   
  408.     On Error GoTo 0   
  409. End Function  
  410. </sitecode></servername>  

vbScript - bulk import collections

This little vbscript loops throught the file CollectionStructure.txt and creates all the defined collections

# are and blank lines are ignored
# are available for comments

The CollectionStructure.txt file should look like this:

############################################
################ EXAMPLES ##################
############################################
### Parent Collection;Child Collection
### COLLROOT;MyCollection1
### Collection1;MyCollection2
############################################
############################################
############################################

#Create Collections for Department XYZ
COLLROOT;Department XYZ
Department XYZ;Department XYZ-123
Department XYZ;Department XYZ-ABC
Department XYZ;Department XYZ-LOL

#Create Collections for Adobe Reader
SWDIST;Adobe Reader
Adobe Reader;Install_Adobe Reader
Adobe Reader;Uninstall_Adobe Reader


The vbScript is the below code - Have fun ;)
Note: There's not build in a lot of error handling, so please first test it

  1. '************************************************************************************************************  
  2. ' Jonas Hettich  
  3. '************************************************************************************************************  
  4. ' Ver 1.00 - 13.04.2011 - initial version  
  5. ' What this script does:  
  6. ' This Scripts creates the Collection Structure defined in the file CollectionStructure.txt  
  7. '************************************************************************************************************  
  8. result = MsgBox("Do you really want to create the Collections?", vbYesNo)  
  9. If result = vbNo Then WScript.Quit  
  10.   
  11. Dim strSiteServer : strSiteServer = ""  
  12. Dim strSitecode : strSitecode = ""  
  13. Dim objSWbemLocator : Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")  
  14. Dim objSWbemServices : Set objSWbemServices = objSWbemLocator.ConnectServer(strSiteServer,"root/sms/site_" & strSitecode)  
  15.   
  16. Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")  
  17. Dim objFile : Set objFile = objFSO.OpenTextFile("CollectionStructure.txt")  
  18. Dim strCurrentLine  
  19. Dim strRootCollection, strChildCollection  
  20. Dim strRootCollectionID, strChildCollectionID  
  21.   
  22. 'Loop the Source File  
  23. Do While not objFile.AtEndOfStream  
  24.  strCurrentLine = objFile.ReadLine  
  25.    
  26.  'Skip Comment and Blank lines  
  27.  If strCurrentLine <> "" Then  
  28.   If Not Left(strCurrentLine,1) = "#" Then  
  29.    'Parse the Root- and Child Collection  
  30.    strRootCollection = Split(strCurrentLine,";")(0)  
  31.    strChildCollection = Split(strCurrentLine,";")(1)  
  32.      
  33.    'Create the collection.  
  34.    Dim strpath  
  35.       Dim objChildCollection : Set objChildCollection = objSWbemServices.Get("SMS_Collection").SpawnInstance_()  
  36.       objChildCollection.Name = strChildCollection  
  37.       objChildCollection.OwnedByThisSite = True  
  38.       strpath=objChildCollection.Put_  
  39.         
  40.       If Err.Number = 0 Then  
  41.        WScript.Echo "Created Collection: " &strChildCollection  
  42.       Else  
  43.     WScript.Echo "Error creating Collection: " &strChildCollection &" - ErrNumber:" &Err.Number  
  44.       End If  
  45.       Err.Clear  
  46.         
  47.       'Get Collection ID  
  48.       Dim objCollection : Set objCollection=objSWbemServices.Get(strpath)  
  49.       strChildCollectionID = objCollection.CollectionID  
  50.      
  51.      
  52.    'Configure Root Collection  
  53.       Dim objCollectionRelation  
  54.       Set objCollectionRelation = objSWbemServices.Get"SMS_CollectToSubCollect" ).SpawnInstance_()  
  55.       If strRootCollection = "COLLROOT" Then  
  56.        objCollectionRelation.parentCollectionID = strRootCollection  
  57.       Else  
  58.        objCollectionRelation.parentCollectionID = CollectionNameToID(strRootCollection)  
  59.       End If  
  60.       objCollectionRelation.subCollectionID = strChildCollectionID  
  61.       objCollectionRelation.Put_  
  62.         
  63.       If Err.Number = 0 Then  
  64.        WScript.Echo "Linked to Root Collection: " &strRootCollection  
  65.       Else  
  66.     WScript.Echo "Error when linking to Root Collectionn: " &strRootCollection &" - ErrNumber:" &Err.Number  
  67.       End If  
  68.   End If  
  69.  End If  
  70. Loop  
  71.   
  72. Function CollectionNameToID(strName)  
  73.  Dim strCollection  
  74.  Dim intCollectionID : intCollectionID = ""  
  75.  Dim allCollections : Set allCollections = objSWbemServices.ExecQuery("SELECT * FROM SMS_Collection WHERE Name = '" & strName & "'")  
  76.  For Each strCollection In allCollections  
  77.   intCollectionID = strCollection.CollectionID  
  78.  Next  
  79.   
  80.  CollectionNameToID = intCollectionID  
  81.    
  82. End Function  

4/12/2011

Programmatically creating AppV Deployments in ConfigMgr

When creating AppV Packages programmatically in ConfigMgr there are some things to consider as they do have programs like classic packages. It's important that the program name is the following string: [Virtual application]. If you use asterisk (*) or a any other string the package will not install.

Here's a example how to create an AppV Program in VB.Net
  1. Set objNewProgram = oWMIService.Get("SMS_Program").SpawnInstance_()  
  2. objNewProgram.ProgramName = "[Virtual application]"  
  3. objNewProgram.PackageID = strPackageID  


If you want to create a Task Sequence which installs a AppV package you've also to define this string as the program name.
  1. Set objTSAction = connection.Get("SMS_TaskSequence_InstallSoftwareAction").SpawnInstance_  
  2. objTSAction.PackageID=strPackageID  
  3. objTSAction.ProgramName="[Virtual application]"   
  4. objTSAction.Name=strName  

Advertisement on state "WaitingDisabled"

An App-V Package which you try to deploy does not get installed.
If the App-V Package is assigned directly the Advertisement is not displayed in "Run advertised Programs". If the Package is assigned over a Task Sequence the Advertisement is visible, but cannot be executed.
In both cases the following Errors are shown:

In CAS.log and Execmgr.log Client logfiles it looks like that the sources are found, but it ends up with the message that no sourcefiles could be located.
Download location found 1
Matching DP Location found 0


Also the state of the Advertisement is on WaitingDisabled

The ConfigMgr behaviour is this case is correct, cause App-V is not active on your ConfigMgr Site

Solution: Enable the AppV deployment on your site in the Client Agent Settings -> Advertised Programs Client Agent -> "Allow virtual application package advertisement"

4/07/2011

Restricted Users cannot create a Direct Membership Rule on a Collection programmatically in SCCM

Consider the following scenario:
You have a User in SCCM 2007 who has only restricted permissions in SCCM. For example the User can just read and modify some specific collections, import computers and create Collection Membership Rules. When the User is using the SCCM Console there’s no problem and all tasks can be performed.
You have written a tool (vbscript, vb.net or whatever) which makes this User possible to perform some tasks very easy and fast on your SCCM Server. The User can import a new machine (with name and mac address), but when trying to create a Direct Membership Rule the tools crashes with “Generic failure”.
If you check the smsprov.log file on your SCCM Server you get this error message:
User … has no read resource rights in any collection for this ResourceID

The problem is that you cannot define a “Default Collection” in the SCCM API where the machine is member of from the beginning. As the User has no Read Rights on the all Collections Class it cannot find that Machine and so it cannot create the Membership Rule. Even if you catch the machine’s ResourceID from the ImportMachineEntry function when creating the machine you the tool crashes.

Either you give the User read Permissions for the all Collections Class Rights, (but then the User can see all Machines in SCCM) or you use the following workaround:
When importing the machine entry there’s created a Status Message on your Site Server. This message looks like listed below and has the Message ID 30213:
User "XYZ" imported machine at site "SiteServer - SiteCode" (NetbiosName=YourMachineName, MACAddress=F7:E8:D3:A9:84:FE, SMBIOSGUID=).
Now create a Status Filter Rule which gets triggered from when this MessageID occurs and start a script with the following command line:
cscript.exe YourScript.vbs %msgis04
%msgis04 later contains the Machine name which you have created.
Now the script runs with the Local System Account of your SCCM Server and must create a Collection Membership Rule on any collection:

Any part of this script would look like this:
  1. strComputername  = Wscript.Arguments(0)  
  2. strCollectionID = “XYZ“  
  3. Set instCollection = objSWbemServices.Get("SMS_Collection.CollectionID='" &strCollectionID & "'")  
  4. Set instDirectRule = objSWbemServices.Get("SMS_CollectionRuleDirect").SpawnInstance_  
  5. instDirectRule.ResourceClassName = "SMS_R_System"  
  6. instDirectRule.ResourceID = NameTOResourceID(strComputerName)  
  7. instDirectRule.RuleName = strComputername  
  8. instCollection.AddMembershipRule(instDirectRule)  


After the script has been executed the Users tool should be able to create the Direct Membership Rule.

AddOn: Maybe you have to build in a “wait-routine” in the Users tool until the Machine’s name get resolved into a ResourceID
  1. Do  
  2. objSWbemServices.ExecQuery("SELECT * FROM SMS_R_System WHERE Name = '" & strComputerName & "'"  
  3. Loop While objSWbemServices.Count = 0  

4/06/2011

Switch from Local System to User context

Sometimes there’s a need to switch from Local System context to the current logged on User.
The following article describes how to achieve this.

In short words the following happens:
1. Something is executed in local system context
2. At the end a EventLog entry is written
3. A Scheduled Tasks gets trigged by the created EventLog entry
4. The Scheduled Tasks which is running in User context executes another script

One example is e.g. to inform Users about an Installation which was executed from the Local System Account. The Application Deployment process executes the CreateEventToInform.vbs Script at the end of the installation to create the EventLog entry for informing the User

CreateEventToInform.vbs
  1. Dim objShell : Set objShell = CreateObject("WScript.Shell")  
  2. Dim strMessage : strMessage = "Dear User this is a message from your local system"  
  3. objShell.LogEvent(4, strMessage)  


InformUser.vbs
  1. Dim strMessage  
  2. Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & "."  
  3. "\root\cimv2")  
  4. Set colLoggedEvents = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where Logfile = 'Application' and SourceName='WSH' and EventCode=4 and Type='Information'")  
  5.   
  6. For Each objEvent In colLoggedEvents  
  7. strMessage = objEvent.Message  
  8. Exit For  
  9. Next  
  10.   
  11. MsgBox(strMessage, vbInformation + vbOKOnly, "Your Company")  


It could also be used as an immediately executed “ActiveSetup” for the current logged User. The Application Deployment process executes the CreateEventToExecute.vbs Script at the end of the installation to create the EventLog entry for performing a Active Setup for the current User

CreateEventToExecute.vbs
  1. Dim objShell : Set objShell = CreateObject("WScript.Shell")  
  2. Dim strCommandLine : strCommandLine = "msiexex /fup <msi>"  
  3. objShell.LogEvent(4, strCommandLine)  
  4. </msi>  


ExecuteUserPart.vbs
  1. Dim objShell : Set objShell = CreateObject("Wscript.Shell")  
  2. Dim strCommandLine  
  3. Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & "." & "\root\cimv2")  
  4. Set colLoggedEvents = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where Logfile = 'Application' and SourceName='WSH' and EventCode=4 and Type='Information'")  
  5.   
  6. For Each objEvent In colLoggedEvents  
  7. strCommandLine = objEvent.Message  
  8. Exit For  
  9. Next  
  10.   
  11. objShell.Run(strCommandLine, 1, False)  


To make the whole think work we have to create a trigger which reacts to the EventLog Entry which was created. Create a Scheduled Tasks which is executed in the User context as listed below for this

Note: You can deploy scheduled tasks to many computer automatically e.g. with Group Policies

Now as soon as the EventID is written the Scheduled Tasks executes the below listed command



Further thoughts:
You could create a whole Application which is written variable so that you can perform different actions in User context. To achieve this easily you could tag the EventLog Message with specific keywords. Later the Application parses the EventLog Message and you can react on this. So you can use it for different scenarios. Example:

WriteEventLog.vbs
  1. Dim objShell : Set objShell = CreateObject("WScript.Shell")  
  2. Dim strMessage : strMessage = "[Inform]Dear User now there's happening something" &vbNewLine &"[Execute]msiexex /fup <msi>"  
  3. objShell.LogEvent 4, strMessage  
  4. </msi>  


PerformInUserContext.vbs
  1. Dim objShell : objShell = CreateObject("Wscript.Shell")  
  2. Dim strMessage, arrEventEntry  
  3. Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & "." & "\root\cimv2")  
  4. Set colLoggedEvents = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where Logfile = 'Application' and SourceName='WSH' and EventCode=4 and Type='Information'")  
  5.   
  6. For Each objEvent In colLoggedEvents  
  7. strMessage = objEvent.Message  
  8. Exit For  
  9. Next  
  10.   
  11. arrEventEntry = Split(strMessage, vbNewLine)  
  12.   
  13. For Each strLine In arrEventEntry  
  14. If InStr(strLine, "[Inform]"Then  
  15. MsgBox(Replace(strLine, "[Inform]"""))  
  16. ElseIf InStr(strLine, "[Execute]"Then  
  17. objShell.Run(Replace(strLine, "[Execute]"""), 1, False)  
  18. End If  
  19. Next