widsnet.com
22Jul/140

Javascript to check IP syntax

My first javascript. Colors the inputbox green if the syntax is correct. Simple check to test if the IP entered is "valid". Meaning an IP between 1.0.0.0 and 255.255.255.255.
Regexp pattern can easily be modified to check for some other known syntax. Computername or such.

<script type="text/javascript">
function ipCheck(formID) {
	var patt = /^([1-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])([.]([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])){3}$/i;
	var form = document.getElementById(formID);
	if (patt.test(form.value)) {
		/* green if correct */
		form.style['backgroundColor'] = "#00FF00";
		/* form.value = form.value.toUpperCase(); 
		I used this for another function to check for the computername syntax 
		and force it to be uppercase when entered correct. */
	} else if (form.value == "") {
		/* Remove color if blank value */
		form.style['backgroundColor'] = "";
	} else {
		/* yellow otherwise */
		form.style['backgroundColor'] = "#FFFF00";
	}
}
</script>
<input type="text" name="Subnet" id="Subnet" Value="<%=sSubnet%>" Maxlength="15" onmouseout="ipCheck('Subnet')" onkeyup="ipCheck('Subnet')">
Filed under: Javascript No Comments
22Jul/140

Nice to have CM2012 vbscripts

Some of these are only slighlty modified from CM SDK. Others are very modified 🙂
Response.Write is for ASP, replace it with Wscript.Echo to use in a script.

First. Connect to CM.

' Set connection = ConnectToCM
Function ConnectToCM
	' Make the connection to CM. Uses constants for servername, username and password
	' Also kind of from the CM SDK. A bit modified
    On Error Resume Next
    Set swbemLocator = CreateObject("WbemScripting.SWbemLocator")
    swbemLocator.Security_.AuthenticationLevel = 6 'Packet Privacy
    
    ' Connect to the server.
    Set swbemServices= swbemLocator.ConnectServer(sCMServer, "root\sms", sCMUser, sCMPassword)
    If Err.Number<>0 Then
        Response.Write "Couldn't connect: " + Err.Description
        Set ConnectToCM = null
        Exit Function
    End If

    ' Determine where the provider is and connect.
    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,sCMUser,sCMPassword)
			If Err.Number<>0 Then
				Response.Write "Couldn't connect:" + Err.Description
				Set ConnectToCM = Null
				Exit Function
			End If
			Set ConnectToCM = swbemServices
			Exit Function
		End If
	Next
    Set ConnectToCM = null ' Failed to connect.
End Function

Start with import a new computer. Returns the ResourceID for the new object.

Function AddNewComputer(connection, netBiosName, smBiosGuid, macAddress)
	' Import a new computer into CM. Based on function from CM SDK
	' Returns the ResourceID for the new object
	If (IsNull(smBiosGuid) = True) And (IsNull(macAddress) = True) Then
		Response.Write "smBiosGuid or macAddress must be defined"
		AddNewComputer = False
		Exit Function
	End If     

	If IsNull(macAddress) = False Then
		macAddress = Replace(macAddress,"-",":")
	End If    

	' Obtain an InParameters object specific
	' to the method.
	Set siteClass = connection.Get("SMS_Site")
	Set inParams = siteClass.Methods_("ImportMachineEntry").inParameters.SpawnInstance_()

	' Add the input parameters.
	inParams.Properties_.Item("MACAddress") =  macAddress
	inParams.Properties_.Item("NetbiosName") =  netBiosName
	inParams.Properties_.Item("OverwriteExistingRecord") =  False
	inParams.Properties_.Item("SMBIOSGUID") =  smBiosGuid

	' Add the computer.
	Set outParams = connection.ExecMethod("SMS_Site","ImportMachineEntry", inParams)
	AddNewComputer = outParams.ResourceID
End Function

Create a dynamic collection. Returns the CollectionID for the collection.

'sCollectionID = CreateDynamicCollection(connection, sCollName, sComment, True, "SELECT * FROM SMS_R_System WHERE Name LIKE '" & sCountry & "%'", sCollComment, sLimitingCollection)
Function CreateDynamicCollection(connection, newCollectionName, newCollectionComment, ownedByThisSite, queryForRule, ruleName, limitToCollectionID)
	' Function from CM SDK, slightly modified
    ' Create the collection.
    Set newCollection = connection.Get("SMS_Collection").SpawnInstance_
    newCollection.Name = newCollectionName
    newCollection.Comment = newCollectionComment
    newCollection.OwnedByThisSite = ownedByThisSite
    newCollection.LimitToCollectionID = limitToCollectionID
    
    ' Save the new collection and save the collection path for later.
    Set collectionPath = newCollection.Put_    
	
    ' Create a new collection rule object for validation.
    Set queryRule = connection.Get("SMS_CollectionRuleQuery")
    
    ' Validate the query (good practice before adding it to the collection). 
    validQuery = queryRule.ValidateQuery(queryForRule)
    
    ' Continue with processing, if the query is valid.
    If validQuery Then
        ' Create the query rule.
        Set newQueryRule = QueryRule.SpawnInstance_
        newQueryRule.QueryExpression = queryForRule
        newQueryRule.RuleName = ruleName
        
        ' Add the new query rule to a variable.
        Set newCollectionRule = newQueryRule
        
        ' Get the collection.
        Set newCollection = connection.Get(collectionPath.RelPath)
        
        ' Add the rules to the collection.
        newCollection.AddMembershipRule newCollectionRule
		
        ' Call RequestRefresh to initiate the collection evaluator.
        newCollection.RequestRefresh True
    End If
	CreateDynamicCollection = newCollection.CollectionID
End Function

Perhaps get the ID of a Folder, based on the name, to put the new collection in.

Function GetCollectionFolderID(connection, sName)
	' Returns FolderID for a folder under "Device Collections" based on Name
	Set oNodeID = connection.ExecQuery("SELECT * FROM SMS_ObjectContainerNode WHERE Name='" & sName & "' AND ObjectType='5000'") '5000 for SMS_Collection_Device
	If oNodeID.Count = 1 Then
		GetCollectionFolderID = oNodeID.ItemIndex(0).ContainerNodeID
	Else
		GetCollectionFolderID = ""
	End If
End Function

Move the collection to the folder.

Sub MoveCollectionToFolder(connection, CollectionID, TargetFolderID)
	ObjectType = 5000 '5000 is SMS_Collection_Device
	SourceFolderID = 0 ' Root folder
	On Error Resume Next
	' Move one collection. 
	sourceItems = Array(CollectionID)
	Set objInstance = connection.Get("SMS_ObjectContainerItem")
	
	' Set up the in parameters 
	Set objInParam = objInstance.Methods_("MoveMembers").inParameters.SpawnInstance_() 
	objInParam.Properties_.Item("InstanceKeys") = sourceItems 
	objInParam.Properties_.Item("ContainerNodeID") = SourceFolderID 
	objInParam.Properties_.Item("TargetContainerNodeID") = TargetFolderID 
	objInParam.Properties_.Item("ObjectType") = ObjectType
	
	' Call the method. 
	Set objOutParams = connection.ExecMethod("SMS_ObjectContainerItem","MoveMembers",objInParam)
End Sub

Create a new variable on the collection.

Sub CreateCollectionVariable(connection, name, value, mask, collectionId, precedence)
	' Sub from CM SDK
	' See if the settings collection already exists. if it does not, create it.
	Set settings = connection.ExecQuery("Select * From SMS_CollectionSettings Where CollectionID = '" & collectionID & "'")
	
	If settings.Count = 0 Then
		'Response.Write "Creating collection settings object"
		Set collectionSettings = connection.Get("SMS_CollectionSettings").SpawnInstance_
		collectionSettings.CollectionID = collectionId
		collectionSettings.Put_
	End If  
	
	' Get the collection settings object.
	Set collectionSettings = connection.Get("SMS_CollectionSettings.CollectionID='" & collectionId &"'" )
	
	' Get the collection variables.
	collectionVariables = collectionSettings.CollectionVariables
	
	' Create and populate a new collection variable.
	Set collectionVariable = connection.Get("SMS_CollectionVariable").SpawnInstance_
	collectionVariable.Name = name
	collectionVariable.Value = value
	collectionVariable.IsMasked = mask
	
	' Add the new collection variable.
	ReDim Preserve collectionVariables (UBound (collectionVariables)+1)
	Set collectionVariables(UBound(collectionVariables)) = collectionVariable
	collectionSettings.CollectionVariables=collectionVariables
	collectionSettings.Put_
End Sub

Get the collectionID based on name.

Function GetCollectionID(sName)
	' Return CollectionID based on Name
	Set oCollection = connection.ExecQuery("SELECT * FROM SMS_Collection WHERE Name='" & sName & "'")
	If oCollection.Count > 0 Then
		GetCollectionID = oCollection.ItemIndex(0).CollectionID
	Else
		GetCollectionID = ""
	End If
End Function

Add computer to a collection with direct membership.

Function AddComputerToCollection(connection, sResourceID, sCollectionID)
	' Add a computer to a collection with direct membership
	On Error Resume Next
	set collection = connection.Get("SMS_Collection.CollectionID='" & sCollectionID & "'")
	set collectionRule = connection.Get("SMS_CollectionRuleDirect").SpawnInstance_

	collectionRule.ResourceClassName = "SMS_R_System"
	collectionRule.ResourceID = sResourceID
	collection.AddMembershipRule collectionRule
	
	AddComputerToCollection = Err.Number
End Function

Two functions to get the ResourceID or the Computername, based on the other OR MAC.

Function GetResourceID(connection, sComputernameOrMAC)
	' Returns the ResourceID for a computer based on MAC or Name
	Set oResource = connection.ExecQuery("SELECT ResourceID FROM SMS_R_System WHERE Name='" & sComputernameOrMAC & "' OR MACAddresses='" & sComputernameOrMAC & "'")
	If oResource.Count > 0 Then 
		GetResourceID = oResource.ItemIndex(0).ResourceID
	Else
		GetResourceID = False
	End If
End Function

Function GetComputername(connection, sResourceIdOrMAC)
	' Returns the computername for a computer based on MAC or ResourceID
	Set oResource = connection.ExecQuery("SELECT Name FROM SMS_R_System WHERE ResourceID LIKE '" & sResourceIdOrMAC & "' OR MACAddresses='" & sResourceIdOrMAC & "'")
	If oResource.Count > 0 Then 
		GetComputername = oResource.ItemIndex(0).Name
	Else
		GetComputername = False
	End If
End Function

Clear last PXE Advertisement for a computer to be able to PXE boot the ocmputer again.

Function ClearPxeAdvertisementResource(connection, sResourceID)
	On Error Resume Next
	' Set up the Resource array parameter.
	resources = Array(1)
	resources(0) = sResourceID

	Set InParams = connection.Get("SMS_Collection").Methods_("ClearLastNBSAdvForMachines").InParameters.SpawnInstance_
	InParams.ResourceIDs = resources
	connection.ExecMethod "SMS_Collection", "ClearLastNBSAdvForMachines", InParams
	
	ClearPxeAdvertisementResource = Err.number
End Function

Is the computer already a member of a collection?

Function IsMemberOfCollection(connection, sCollID, sResourceID)
	' Check if ResourceID is member of CollectionID
	Set oExist = connection.ExecQuery("SELECT * FROM SMS_FullCollectionMembership WHERE CollectionID='" & sCollID & "' AND ResourceID='" & sResourceID & "'")
	If oExist.Count = 1 Then
		IsMemberOfCollection = True
	Else
		IsMemberOfCollection = False
	End If
End Function

Check for valid IP/Subnet/netmask and MAC syntax.

Function isValidIP(sIP)
	' not really ... just checking that the value is between 1.0.0.0 and 255.255.255.255
	' That way this function works for IP, Subnet and Netmask instead of having 3 different functions
	Set regEx = New RegExp
	regEx.Pattern = "^([1-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])([.]([0-9]|[1-9][0-9]|[1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5])){3}$"
	regEx.IgnoreCase = True
	isValidIP = regEx.Test(sIP)
End Function

Function isValidMAC(sMAC)
	' Syntax: XX:XX:XX:XX:XX:XX
	Set regEx = New RegExp
	regEx.Pattern = "^([0-9A-F]{2}[:]){5}([0-9A-F]{2})$"
	regEx.IgnoreCase = True
	isValidMAC = regEx.Test(sMAC)
End Function

And last, delete the computer object.

Function DeleteComputer(connection, sResourceID)
	' Deletes a computer from SCCM
	On Error Resume Next
	Set oResource = connection.Get("SMS_R_System.ResourceID='" & sResourceID  & "'")
	oResource.Delete_
	DeleteComputer = Err.Number
End Function
12Nov/130

App-V and Powershell

Just a quick post so that i will remember this later when i need it next time.

Import-Module AppvClient
Get-Command -Module AppvClient

Add-AppvClientPackage -Path '.\Name.appv' | Publish-AppvClientPackage -Global | Mount-AppvClientPackage
Unpublish-AppvClientPackage -Global -Name 'Name' | Remove-AppvClientPackage

# Start CMD inside App-V package
Get-AppvClientPackage -Name * | ForEach-Object{Start-Process cmd -ArgumentList "/K title $($_.Name) /appvve:$($_.PackageId)_$($_.VersionId)"}
Filed under: App-V, PowerShell No Comments
2Oct/130

Unable to disable settings on the security tab in an IE10 GPP

I finally got MS to make a hotfix for this. Only took about 10 months 🙂
The problem was that F5-F8 buttons didn't disable/enable the settings on the security tab when creating an Internet Explorer 10 GPP in a GPO.

With this hotfix installed, it works.
http://support.microsoft.com/kb/2849027/en-us

25Mar/131

Get members of an AD group

Get all members in an AD group, even recursive with -Recursive.

function Get-GroupMembers {
Param(
[parameter(Mandatory = $true)][string]$group,
[switch]$Recursive
)
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ct = [System.DirectoryServices.AccountManagement.ContextType]::Domain
$groupObject = [System.DirectoryServices.AccountManagement.Principal]::FindByIdentity($ct,$group)
Return $groupObject.GetMembers($Recursive)
}
24Jan/130

Count number of client with specified program in a collection

Enter a program name, ID or publisher and a collectionID and the report will list the number of clients with the specified program installed.

SELECT arp.Publisher0, arp.DisplayName0, arp.ProdID0, Count(DISTINCT sys.Name0) AS 'Count'
FROM v_R_System sys
JOIN v_Add_Remove_Programs arp ON sys.ResourceID = arp.ResourceID 
JOIN v_FullCollectionMembership fcm on sys.ResourceID=fcm.ResourceID
WHERE (arp.DisplayName0 LIKE @SearchKey OR arp.Publisher0 LIKE @SearchKey OR arp.ProdID0 LIKE @SearchKey) 
AND fcm.CollectionID=@CollID
GROUP BY arp.Publisher0, arp.DisplayName0, arp.ProdID0
ORDER BY arp.DisplayName0 ASC

Prompts
Name: SearchKey
Prompt text: Software / Publisher / Product ID

begin
 if (@__filterwildcard = '')
  Select DISTINCT DisplayName0 FROM v_Add_Remove_Programs order by DisplayName0
 else
  Select DISTINCT DisplayName0 FROM v_Add_Remove_Programs
  WHERE DisplayName0 like @__filterwildcard
  order by DisplayName0
end

Name: CollID
Prompt text: CollectionID

begin
 if (@__filterwildcard = '')
  select CollectionID, Name from v_Collection order by Name
 else
  select CollectionID, Name from v_Collection
  WHERE Name like @__filterwildcard
  order by Name
end
22Nov/120

Create XML with Powershell

Some powershell XML code and functions that can be useful sometime...

# Document creation
[x m l]$newXML = New-Object system.Xml.XmlDocument 
$newXML.LoadXml('<?xml version="1.0" encoding="utf-16"?><root></root>')

# Creation of a the first element
$xmlElt = CreateElement -xml $newXML -name "task"

# Add the element to the document
$newXML.LastChild.AppendChild($xmlElt) | Out-Null

# Creation of a second element
$xmlElt = CreateElement -xml $newXML -name "task"

# Create an attribute
SetAttribute -xml $newXML -element $xmlElt -name "xmlns" -text "http://random.url"

# Create another attribute
SetAttribute -xml $newXML -element $xmlElt -name "Another" -text "Attribute"

# Create a child element
$xmlSubElt = CreateElement -xml $newXML -parent $xmlElt -name "ChildElement" -text "Value"

# Create another child element
$xmlSubElt = CreateElement -xml $newXML -parent $xmlElt -name "AnotherChild"

# Create an attribute to the child
SetAttribute -xml $newXML -element $xmlSubElt -name "Attribute" -text "inChild"

# Add the second element to the document
$newXML.LastChild.AppendChild($xmlElt) | Out-Null

# Save to a file
$newXML.Save("c:\Temp\out.xml")

function SetAttribute {
    param($xml, $name, $text, $element)
    $xmlAtt = $xml.CreateAttribute($name)
    $xmlAtt.Value = $text
    $element.Attributes.Append($xmlAtt) | Out-Null
}

function CreateElement {
    param($xml, $name, $text, $parent)
    $xmlElt = $xml.CreateElement($name)
    if ($text) {
        $xmlText = $xml.CreateTextNode($text)
        $xmlElt.AppendChild($xmlText) | Out-Null
    }
    If ($parent) {
        $parent.AppendChild($xmlElt) | Out-Null
    }
    $xmlElt
}

And the output looks like this

<?xml version="1.0" encoding="utf-16"?>
<root>
<task />
<task xmlns="http://random.url" Another="Attribute">
<ChildElement>Value</ChildElement>
<AnotherChild Attribute="inChild" />
</task>
</root>
Filed under: PowerShell, xml No Comments
31Oct/120

Print error in a form application

When a compiled Powershell Studio application gets an error, the error is not echoed to the screen automatically which makes it really hard to troubleshoot what have gone wrong. This short solution checks for error and prints in to a textbox of some sort.
The "return" quits the function, remove it to continue.

#Paste this where error checking is wanted in the code
If ($Error) {PrintError -Error $Error; Return}

#Function to print the error
function PrintError {
	Param($Error)
	$textbox.AppendText("`nERROR!`n")
	$textbox.AppendText("Exception: `t$($Error[0].Exception.InnerException)`n")
	$textbox.AppendText("Message: `t$($Error[0].Exception.Message)`n")
	$textbox.AppendText("Name: `t`t$($Error[0].Exception.TargetSite.Name)`n")
	$textbox.AppendText("Reason: `t`t$($Error[0].CategoryInfo.Reason)`n")
	$textbox.AppendText("Category: `t$($Error[0].CategoryInfo.Category)`n")
	$textbox.AppendText("TargetName: `t$($Error[0].CategoryInfo.TargetName)`n")
	$textbox.AppendText("TargetType: `t$($Error[0].CategoryInfo.TargetType)`n`n")
}
31Oct/120

List packages with an update schedule

List all packages in SCCM that have an update schedule of some sort.

$SCCMServer = 'Server01'
$NameSpace = 'root\sms\site_SMS'
$Provider = "\\$SCCMServer\$NameSpace"
$Packages = Get-WmiObject -Query "Select * from SMS_Package" -ComputerName $SCCMServer -NameSpace $NameSpace
$Packages | ForEach-Object {
    $PackageID = $_.PackageID
    $Sched = ([wmi]"$($Provider):SMS_Package.PackageID='$PackageID'").RefreshSchedule
    If($Sched) {Write-Host "$PackageID"}
}

4Oct/120

Get scriptname in powershell

A short simple solution to get the filename of the script and replace the ending with .log instead of .exe or .ps1.
$LogFile = $MyInvocation.ScriptName -replace "^.*\\(.*)\..*$", '$1.log'

Note: In Powershell Studio, when compiling to executable, the code must read Hostinvocation instead of Myinvocation.

Filed under: PowerShell No Comments