Check if IP is between range (Boundaries)

Check if an IP address is inside an existing boundary.

$SiteServer = ""
$SiteCode = ""

Function Get-MatchingBoundary {

    $Result = 0

    ForEach ($Boundary in $AllBoundaries) {
        $BoundaryName = $Boundary.DisplayName
        $IPRangeStart, $IPRangeEnd = $Boundary.Value.Split("-")

        $ParseIP = [System.Net.IPAddress]::Parse($IPAddress).GetAddressBytes()
        $ParseIP = [System.BitConverter]::ToUInt32($ParseIP, 0)

        $ParseIPStart = [System.Net.IPAddress]::Parse($IPRangeStart).GetAddressBytes()
        $ParseIPStart = [System.BitConverter]::ToUInt32($ParseIPStart, 0)

        $ParseIPEnd = [System.Net.IPAddress]::Parse($IPRangeEnd).GetAddressBytes()
        $ParseIPEnd = [System.BitConverter]::ToUInt32($ParseIPEnd, 0)

        if (($ParseIP -ge $ParseIPStart) -and ($ParseIP -le $ParseIPEnd)) {
            if ($BoundaryName.Length -ge 1) {
                $Results = 1
                Write-Output "$IPAddress is within: $BoundaryName"
            else {
                $Results = 1
                Write-Output "$IPAddress is within: Range $($Boundary.Value)"
    if ($Results -eq 0) {
        Write-Output "$IPAddress is not in any boundary"

[Net.IPAddress]$IPaddress = ""

# Get all boundaries from SCCM
$AllBoundaries = Get-WMIObject -computer "$SiteServer" -Namespace "Root\SMS\Site_$SiteCode" -Class "SMS_Boundary" -Filter "BoundaryType = 3"

Get-MatchingBoundary -Boundaries $AllBoundaries -IPAddress $IPaddress

Find collections with both incremental and full update

Since using incremental and full on a collection is completely useless, remove one or the other. This is one way to find the collections.
so RefreshType=6 is both.

$NameSpace = "root\sms\site_"

Function Get-Container() {
    $Path = ""
    $Container = Get-WmiObject -Query "SELECT Name,ParentContainerNodeID FROM SMS_ObjectContainerNode WHERE ContainerNodeID='$ContainerID'" -Namespace $NameSpace
    If($Container.ParentContainerNodeID -ne 0) {
        $path += Get-Container -ContainerID $Container.ParentContainerNodeID -NameSpace $NameSpace

$Colls = Get-WmiObject -Query "SELECT CollectionID,Name FROM SMS_Collection WHERE RefreshType=6" -Namespace $NameSpace
Foreach ($Coll in $Colls) {
    $Container = Get-WmiObject -Query "SELECT ContainerNodeID FROM SMS_ObjectContainerItem WHERE InstanceKey='$($Coll.CollectionID)'" -Namespace $NameSpace

    If($Container -eq $null) {
        Write-Host "\$($Coll.Name)"
    Else {
        $Container | ForEach-Object{
        $Parent = Get-Container -ContainerID $_.ContainerNodeID -NameSpace $NameSpace
        Write-Host "$Parent\$($Coll.Name) ($($Coll.CollectionID))"


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

Get members of an AD group

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

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

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

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

And the output looks like this

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

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 {
	$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")

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"}


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

Replace ending on a string with regexp

Replace filetype (everything after the last dot) on a string in powershell.
"fil.fan.log" -replace "\.[^.]*$", ".txt"

Filed under: PowerShell No Comments

SAPIEN Powershell Studio, hide a form

A solution for SAPIEN PowerShell Studio to only show a form in systray and not in taskbar or in Alt+Tab.
After you create a SystemTrayMenu and SystemTrayIcon, then:

Select the form. -> ShowInTaskbar = False
And then in the code. -> $FormName.FormBorderStyle = 'FixedToolWindow'