roccos34 Posted January 21, 2021 Posted January 21, 2021 How can I write this powershell command in autoit:? $Collections = (Get-WmiObject -ComputerName siteserver -Namespace root/SMS/site_sitecode -Query "SELECT SMS_Collection.* FROM SMS_FullCollectionMembership, SMS_Collection where name = 'hostname' and SMS_FullCollectionMembership.CollectionID = SMS_Collection.CollectionID").Name Thanks
Subz Posted January 21, 2021 Posted January 21, 2021 You could use "Powershell.exe -Command" switch within CMD however please note it will only return a string. If you want to interact with the object I've always used something like the following which I wrote to add computers to a collection via third party app and then refresh the local client membership afterwards nb: need to change $g_sSiteCode, $g_sSiteServer and $g_sCollectionResourceId values Usage: Script.exe -ComputerName ##ComputerName## -CollectionId P0123456 expandcollapse popupGlobal $g_COMErrorHandler = ObjEvent("AutoIt.Error", "_ErrFuncGlobal") ; Global COM error handler #include <Array.au3> #include <CmdLine.au3> Global $g_bDebug = True Global $g_sSiteCode = '##Site Code##' ;~ Modify Global $g_sSiteServer = '##Primary Site Server##' ;~ Modify Global $g_oSWbemLocator = ObjCreate("WbemScripting.SWbemLocator") Global $g_oConnectServer = $g_oSWbemLocator.ConnectServer($g_sSiteServer, 'root\SMS\site_' & $g_sSiteCode) Global Const $wbemFlagReturnImmediately = 0x10 Global Const $wbemFlagForwardOnly = 0x20 Global $g_sComputerName = StringStripWS(_CmdLine_SwitchValue("ComputerName"), 8) If $g_sComputerName = Null Then If $g_bDebug Then $g_sComputerName = @ComputerName Else Exit EndIf EndIf Global $g_sCollectionResourceId = _CmdLine_SwitchValue("CollectionId") If $g_sCollectionResourceId = Null Then If $g_bDebug Then $g_sCollectionResourceId = "##UniqueId##" ;~ Modify Else Exit EndIf EndIf _AddToCollection($g_sComputerName, $g_sCollectionResourceId) Func _AddToCollection($_sComputerName = $g_sComputerName, $_sCollectionResourceId = $g_sCollectionResourceId) Local $sComputerResourceId = _GetComputerResourceId($_sComputerName) Local $_bResourceAdded = False Local $_oCollectionResourceId = $g_oConnectServer.Get("SMS_Collection.CollectionID='" & $_sCollectionResourceId & "'") Local $_sCollections = "SELECT * FROM SMS_CM_RES_COLL_" & $_sCollectionResourceId Local $_oCollections = $g_oConnectServer.ExecQuery($_sCollections) For $_oCollection In $_oCollections If $_oCollection.ResourceID = $sComputerResourceId And $_oCollection.ISDirect Then $_bResourceAdded = True Next If $_bResourceAdded = True Then _SccmClientAction($_sComputerName, '{00000000-0000-0000-0000-000000000021}', 'Machine Policy Retrieval and Evaluation Cycle', False) EndIf $_oSccmDirectCollectionRule = $g_oConnectServer.Get("SMS_CollectionRuleDirect" ).SpawnInstance_ $_oSccmDirectCollectionRule.ResourceClassName = "SMS_R_System" $_oSccmDirectCollectionRule.ResourceID = $sComputerResourceId $_sAddMemberShipRule = $_oSccmDirectCollectionRule $_oCollectionResourceId.AddMembershipRule($_sAddMemberShipRule) _SccmClientAction($_sComputerName, '{00000000-0000-0000-0000-000000000021}', 'Machine Policy Retrieval and Evaluation Cycle', False) $_oCollectionResourceId.RequestRefresh(True) EndFunc Func _GetComputerResourceId($_sComputerName = $g_sComputerName) Local $_sTargetResource = "" Local $_sTargetResources = 'SELECT * FROM SMS_CM_RES_COLL_SMS00001 Where Name = "' & $_sComputerName & '"' Local $_oTargetResources = $g_oConnectServer.ExecQuery($_sTargetResources) If $_oTargetResources.Count = 0 Then Exit For $_oTargetResource In $_oTargetResources Return $_oTargetResource.ResourceID Next Return $_sTargetResource EndFunc Func _SccmClientAction($_sComputerName = $g_sComputerName, $_sSccmClientActionID = "{00000000-0000-0000-0000-000000000021}", $_sSccmClientActionName = "Machine Policy Retrieval and Evaluation Cycle", $_bSccmClientInventory = False) Local $_oWmiService While 1 If Ping($_sComputerName, 1000) = 0 Then ExitLoop $_oWmiService = ObjGet("winmgmts:\\" & $_sComputerName & "\root\CIMV2") If @error Then ExitLoop ;Verify SMS Agent Host service exists $_oSccmAgentActive = $_oWmiService.ExecQuery("SELECT * FROM Win32_Service WHERE Name='CcmExec'") If $_oSccmAgentActive.count < 1 Then ExitLoop ;Delete existing full inventory if resync requested If $_bSccmClientInventory = True Then $_oSccmClientInventory = ObjGet("winmgmts:\\" & $_sComputerName & "\root\ccm\invagt") If @error <> 0 Then ExitLoop $_oSccmClientInventory.Delete('InventoryActionStatus.InventoryActionID="' & $_sSccmClientActionID & '"') EndIf ;Connect to the machine's CCM namespace $oCCMNameSpace = ObjGet("winmgmts:\\" & $_sComputerName & "\root\ccm") If @error Then ExitLoop ;Invoke SMS_Client.TriggerSchedule $oSMS_Client = $oCCMNameSpace.Get("SMS_Client") $oCCMAction = $oSMS_Client.Methods_("TriggerSchedule").inParameters.SpawnInstance_() $oCCMAction.sScheduleID = $_sSccmClientActionID $oCCMNameSpace.ExecMethod("SMS_Client", "TriggerSchedule", $oCCMAction) ExitLoop WEnd EndFunc ; Global COM error handler Func _ErrFuncGlobal($oError) ; Do anything here. ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> Global COM error handler - COM Error intercepted !" & @CRLF & _ @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _ @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _ @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _ @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _ @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _ @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _ @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _ @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _ @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF) EndFunc ;==>_ErrFunc
roccos34 Posted January 22, 2021 Author Posted January 22, 2021 Thank you so much for the answer but I don't have to add computers to the collection but only check if a device is present in a collection ... I'm a beginner with script language I don't know how to get a cue, I also have to operate on the sccm of exercise a large structure and having rights that can modify objects I cannot afford to experiment .... I need a ready script that, given a hostname, tell me if it is present in the "collection X"
Subz Posted January 22, 2021 Posted January 22, 2021 (edited) If you want to go the PowerShell route then recommend just using a PowerShell script aka .ps1 file, The code above returns a list of collections to PowerShell, but you wouldn't have access to the $Collections object within Autoit. Using class method as I posted above you could do the same thing and have access within Autoit script for example, slight modification of the script above: Example Usage: Script.exe -ComputerName @ComputerName -CollectionId = SMS00001 Example Result: Message box will show @ComputerName has either a "direct membership" or a "query membership", if the computer is a member of the "All Systems" collection (CollectionId = SMS00001). expandcollapse popupGlobal $g_COMErrorHandler = ObjEvent("AutoIt.Error", "_ErrFuncGlobal") ; Global COM error handler Global Const $wbemFlagReturnImmediately = 0x10 Global Const $wbemFlagForwardOnly = 0x20 Global $g_bDebug = True Global $g_sSiteCode = 'SiteCode' ;~ Modify Global $g_sSiteServer = 'SiteServer' ;~ Modify Global $g_oSWbemLocator = ObjCreate("WbemScripting.SWbemLocator") Global $g_oConnectServer = $g_oSWbemLocator.ConnectServer($g_sSiteServer, 'root\SMS\site_' & $g_sSiteCode) Global $g_sComputerName = _CmdLine_SwitchValue("ComputerName") If $g_sComputerName = Null Then If $g_bDebug Then $g_sComputerName = @ComputerName Else Exit EndIf EndIf Global $g_sCollectionResourceId = _CmdLine_SwitchValue("CollectionId") If $g_sCollectionResourceId = Null Then If $g_bDebug Then $g_sCollectionResourceId = "SMS00001" Else Exit EndIf EndIf _GetCollection($g_sComputerName, $g_sCollectionResourceId) Func _GetCollection($_sComputerName = $g_sComputerName, $_sCollectionResourceId = $g_sCollectionResourceId) Local $sComputerResourceId = _GetComputerResourceId($_sComputerName) Local $_sCollections = "SELECT * FROM SMS_CM_RES_COLL_" & $_sCollectionResourceId Local $_oCollections = $g_oConnectServer.ExecQuery($_sCollections) For $_oCollection In $_oCollections If $_oCollection.ResourceID = $sComputerResourceId Then MsgBox(4096, "", $_sComputerName & " has a " & ($_oCollection.ISDirect ? "direct membership to the collection" : "query membership to the collection - ") & $g_oConnectServer.Get("SMS_Collection.CollectionID='" & $_sCollectionResourceId & "'").Name) Next EndFunc Func _GetComputerResourceId($_sComputerName = $g_sComputerName) Local $_sTargetResource = "" Local $_sTargetResources = 'SELECT * FROM SMS_CM_RES_COLL_SMS00001 Where Name = "' & $_sComputerName & '"' Local $_oTargetResources = $g_oConnectServer.ExecQuery($_sTargetResources) If $_oTargetResources.Count = 0 Then Exit For $_oTargetResource In $_oTargetResources Return $_oTargetResource.ResourceID Next Return $_sTargetResource EndFunc Func _CmdLine_SwitchValue($sCmdLine, $vResult = Null) For $i = 1 To $CmdLine[0] If $CmdLine[$i] = "/" & $sCmdLine Or $CmdLine[$i] = "-" & $sCmdLine Or $CmdLine[$i] = "--" & $sCmdLine Then If $CmdLine[0] >= $i + 1 Then If StringLeft($CmdLine[$i + 1], 1) = "/" Or StringLeft($CmdLine[$i + 1], 1) = "-" Or StringLeft($CmdLine[$i + 1], 2) = "--" Then Return $vResult Else Return $CmdLine[$i + 1] EndIf EndIf EndIf Next Return $vResult EndFunc ; Global COM error handler Func _ErrFuncGlobal($oError) ; Do anything here. ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> Global COM error handler - COM Error intercepted !" & @CRLF & _ @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _ @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _ @TAB & "err.description is: " & @TAB & $oError.description & @CRLF & _ @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _ @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _ @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @CRLF & _ @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _ @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _ @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF) EndFunc ;==>_ErrFunc Edited January 22, 2021 by Subz
roccos34 Posted January 22, 2021 Author Posted January 22, 2021 (edited) which UDF CmdLine.au3 should I use? (where do I download can you send me (or link) the UDF you used? Edited January 22, 2021 by roccos34
Subz Posted January 22, 2021 Posted January 22, 2021 Have updated the code above, have added the _CmdLine_SwitchValue function and also the _GetComputerResourceId function which I forgot to add. The original CmdLine UDF is found here although my version has been modified.
Moderators JLogan3o13 Posted January 22, 2021 Moderators Posted January 22, 2021 @roccos34 I think the big (first) question to answer is - why would you want to? Best practice is not to mix scripting/programming languages unless there is a compelling reason to do so. Do you have such a reason? "Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball How to get your question answered on this forum!
roccos34 Posted January 22, 2021 Author Posted January 22, 2021 (edited) @JLogan3o13 I agree in fact I wanted to do the same thing in pure autoit which I know slightly better than powershell Edited January 22, 2021 by roccos34
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now