New-ADQuery Function to resolve Active Directory information

by on August 14th, 2013

With this function you can query objects from Active Directory.

function New-ADQuery
{
    param (
        [Parameter( Mandatory = $false,
                    Position = 1)] 
        [string]$Domain,
        [Parameter( Mandatory = $false,
                    Position = 2,
					HelpMessage="Fill in the Organisation Unit or Container name to search in.`nWithout a DirectorySearch value, all values within the domain will be resolved.")]
        [string]$DirectorySearch,
        [Parameter( Mandatory = $false,
                    Position = 3,
                    HelpMessage="Add query Filter.`nExample: `"objectclass=name`",`"lastName=Davis`"")]
    )
     
    if (!($Domain)){$Domain = [DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()}
    $ADSearch = new-object DirectoryServices.DirectorySearcher
     
    if ($DirectorySearch){
        $ADSearch.Filter = "ou=$DirectorySearch"
        if (!(($ADSearch.Findall()).path)){$ADSearch.Filter = "cn=$DirectorySearch"}
        $Objects = @()
        $ADSearch.findall() | %{$Objects += $_.path}
        $ADSearch.Filter = $null
    }
     
    if ($ObjectFilter){
        if ($ObjectFilter.count -lt 2){$ADSearch.Filter = "(&($ObjectFilter))"}else{
            $ObjectFilter = $(($ObjectFilter | %{"($_)"}) -join(""))
            $ADSearch.Filter = "(&$ObjectFilter)"
        }
    }
     
    if ($DirectorySearch){
        $Objects | %{
            $ADSearch.SearchRoot = $_
            $ADSearch.FindAll()
        }
    }else{
		$ADSearch.FindAll()
	}
     
}

Send Serialized ByteArray through TCP (objects through tcp)

by on June 9th, 2013

In an early post I wrote a way to send data over TCP. This is simple text data (String or array data). But what if you like to send an object from a client to a server? This needs serialisation and deserialisation of the object to convert it to a byte array and send over TCP.

So here’s a new version of the earlier TCP post. I’ve edited the functions and made it workable with sending objects and string data etc.

Send-TCPMessage

Function Send-TCPMessage 
{ 
    param ( [ValidateNotNullOrEmpty()] 
        [string] $EndPoint, 
        [int] $Port, 
        $Message
    ) 
    
	$memorystream = new-object system.IO.MemoryStream(1024)
	$serializer = new-object system.Runtime.Serialization.formatters.Binary.BinaryFormatter
	$serializer.Serialize($memorystream,$Message)
	$bytearray = $memorystream.GetBuffer()
    $IP = [System.Net.Dns]::GetHostAddresses($EndPoint) 
    $Address = [System.Net.IPAddress]::Parse($IP) 
    $Socket = New-Object System.Net.Sockets.TCPClient($Address,$Port) 
    $Stream = $Socket.GetStream() 
    $Stream.Write($bytearray,0,$bytearray.Length)
    $Stream.Close()
    $Socket.Close()
}

Receive-TCPMessage

Function Receive-TCPMessage 
{ 
    param ( [ValidateNotNullOrEmpty()] 
        [int] $Port
    ) 
    try { 
     
        $endpoint = new-object System.Net.IPEndPoint([ipaddress]::any,$port) 
        $listener = new-object System.Net.Sockets.TcpListener $EndPoint
        $listener.start() 
 		
		$binaryformatter = new-object system.Runtime.Serialization.formatters.Binary.BinaryFormatter
		$memorystream = new-object system.IO.MemoryStream(1024)
        $data = $listener.AcceptTcpClient() # will block here until connection 
        $bytes = New-Object System.Byte[] 1024
        $stream = $data.GetStream()
		$ByteArray = @()
        while (($i = $stream.Read($bytes,0,$bytes.Length)) -ne 0){$ByteArray += $bytes}
        $memorystream = new-object system.IO.MemoryStream(1024)
		$deserialize = new-object system.Runtime.Serialization.formatters.Binary.BinaryFormatter
		$memorystream.Write($bytearray,0,$bytearray.Length)
		[void]$memorystream.Seek(0,0)
		$Message = $deserialize.Deserialize($memorystream)
		write-output $Message
        $stream.close()
        $listener.stop()
    }catch [exception]{}
}

Client / Server connection (TCP) Multithreading

by on June 6th, 2013

I’m busy creating a Client / Server application. To communicate between 2 locations with multiple clients, I’ll need a multithread solution. I’ve build a Listener and Sender. The Listener will stay in a loop to listen for every client on port 4000.
When a client connects to the listener he will be launched in a new thread.

Cause the multithread gave errors back (if started directly as a scriptblock) when killing the connection within the thread. I’ve build a construction with a function that will call a scriptblock with all the functions and needed code to communicate within the thread.

If there is a good Multithread Client/Server powershell code, or you’ve got good ideas… be welcome to reply on this post.

(Sender)

	$IP = "127.0.0.1"
	$Port = 4000

	$UTF8 = [System.Text.Encoding]::UTF8
	$Endpoint = [System.Net.Dns]::GetHostAddresses($IP) 
	$Address = [System.Net.IPAddress]::Parse($Endpoint)
	$TCPClient = New-Object System.Net.Sockets.TcpClient
	$TCPClient.Connect($Address,$Port)
	$strdata = $TCPClient.GetStream()
	$writer = new-object System.IO.StreamWriter($strdata)
	$reader = new-object System.IO.StreamReader($strdata)


	function send-tcpmessage
	{
		param(
			[array]$message
		)
		
		if ($message.count -eq 1){
			$writer.Write(($message[0]))
			$writer.Flush()
		}else{
			$Message | %{
				$writer.WriteLine($_)
				$writer.Flush()
			}
		}
	}
	function stop-tcpconnection
	{
		$strdata.Close()
		$reader.Close()
		$writer.Close()
	}

(Listener)

function Get-ScriptDirectory
{ 
	if($hostinvocation -ne $null)
	{
		Split-Path $hostinvocation.MyCommand.path
	}
	else
	{
		Split-Path $script:MyInvocation.MyCommand.Path
	}
}
function start-scriptblock
{
	param(
		[scriptblock]$script
	)
	&$scripblock
}

$scriptpath = Get-ScriptDirectory
$ListPort = 4000

$ListPort = new-object System.Net.IPEndPoint([ipaddress]::any,$ListPort) 
$listener = New-Object System.Net.Sockets.TcpListener($ListPort)
$listener.Start()
$running = $true


while ($running){
	$tcpclient = $listener.AcceptTcpClient()
	$scripblock = {
		$client = $tcpclient
		$scriptpth = $scriptpath
		
		#Region Main FUnction - Add message commands in here
		function add-newclient
		{
			param(
				[object]$client
			)
			
			$bytes = New-Object System.Byte[] 1024
			$stream = $client.GetStream()
				
			while (($i = $stream.Read($bytes,0,$bytes.Length)) -ne 0){
				$EncodedText = New-Object System.Text.ASCIIEncoding
				Write-Output ($EncodedText.GetString($bytes,0, $i))
				
				
				<############################################
				#											#
				# 				 Add Commands				#
				#											#
				#############################################>
				
				if (($EncodedText.GetString($bytes,0, $i)) -eq "test"){
					$scriptpth | Out-File c:\Temp\test.log
				}
				
				
				<############################################>
			}
			
			$client.close()
			$stream.close()
		} 
		
		#EndRegion
		
		#region Functions
		
		#endregion
		
		add-newclient -client $client
	}

	try{
		$thread = new-object system.threading.thread((start-scriptblock -script $scripblock))
		$thread.Start()
	}catch{}
}

Function: Install-MSI

by on May 16th, 2013

To make MSI installations a bit more complex, I wrote a function that can be used to run MSI installations. This Function will create a more commandline lookalike string, without creating arrays etc to run MSI installations. I’ve added the most functional options for installing MSIs.

Example on how to run Install-MSI:

Install-MSI -Msi “C:\Test\Test.msi” -Dest “c:\Temp\test” -Property “UELA=1 TABLE=NO PATH=`”c:\Program Files\test`””

Parameters that can be set:

Msi – Path to MSI filename (include msi filename)
Dest – This is INSTALL directory
property – Add MSI Property table items that must be set during installation
Hide – Switch to enable /QN option
mst – Path to MST filename (include mst filename)
logfile – Path where to store the INSTALL logfile

Function Install-MSI
{
	param(
		[ValidateNotNullOrEmpty()]
		[Parameter(	Mandatory = $true,
					Position = 0,
					HelpMessage="Full path to MSI file (including msi filename)")]
		[string]$Msi,
		[ValidateNotNullOrEmpty()]
		[Parameter(	Mandatory = $false,
					Position = 1,
					HelpMessage="INSTALLDIR Path")]
		[validatescript({test-path (ni -ItemType Directory -Force -Path $_)})]
		[string]$Dest,
		[ValidateNotNullOrEmpty()]
		[Parameter(	Mandatory = $false,
					Position = 2,
					HelpMessage="Full path to MST file (including mst filename)")]
		[validatescript({test-path $_})]
		[string]$mst,
		[Parameter(	Mandatory = $false,
					Position = 3,
					HelpMessage="Silent Installation `"/QN`" option.")]
		[switch]$Hide,
		[Parameter(	Mandatory = $false,
					Position = 4,
					HelpMessage="Set MSI Property values.`nExample: -Property `"UELA=1 TABLE=4`"")]
		[string]$Property,
		[Parameter(	Mandatory = $false,
					Position = 5,
					HelpMessage="Full path to Logfile (including log filename `".log`")")]
		[validatescript({(test-path "$(split-path $_)") -and (((split-path $_ -Leaf) -split("\."))[1] -eq "log")})]
		[string]$Logfile
	)
	process
	{
		$Args = @("/i",$Msi)
		if ($Dest){$Args += "INSTALLDIR=$Dest"}
		if ($Hide){$Args += "/QB"}
		if ($Property){
			$i = 0
			$propArr = @()
			$Property -split("=") | %{
				if (([regex]"`"").match($_).Success){
					([regex]"(^?.*`")\s(.*$)").match($_).groups[1].value
					([regex]"(^?.*`")\s(.*$)").match($_).groups[2].value
				}else{$_ -split(" ")}
			} | %{
				if($i -eq 0){
					$val = $_
					$i++
				}
				elseif($i -eq 1){
					$val = "$val=$($_)"
					$propArr += $val
					$i = 0
				}
			}
			$Args += $propArr
		}
		if ($Logfile){
			$Args += ("/L*V",$Logfile)
		}
			
		$Process = Start-Process msiexec.exe -ArgumentList $args -Wait -PassThru
		
		$Index = New-Object PSObject
		$Index | Add-Member -MemberType NoteProperty -Name "MSI" -Value (split-path $Msi -Leaf)
		$Index | Add-Member -MemberType NoteProperty -Name "Path" -Value (split-path $Msi)
		$Index | Add-Member -MemberType NoteProperty -Name "Arguments" -Value $Args
		$Index | Add-Member -MemberType NoteProperty -Name "ExitCode" -Value $Process.exitcode
		return $Index
	}
}

Function: Enable-UplinkNICS

by on May 15th, 2013

This function will walk through every physical NIC adapter. If the adapter is enabled, then it will check if it has an uplink.
If true, then it will move on to the next NIC adapter. If false, it will enable the NIC, wait till the NIC is established and
check if it has an Uplink.
These actions will be applied to all physical NICS and return only the NIC properties (Array) of the NICS with an Uplink.

Function Enable-UplinkNICS
{
	$array = @()
	gwmi -Class Win32_NetworkAdapter | ?{$_.PhysicalAdapter -eq $true} | ?{$_.PNPDeviceID -notlike "USB*"} | %{
		if ($_.Enable().returnValue -eq 0){
		
			# Wait till NIC is enabled
			$state = $_.NetConnectionStatus
			$ID = $_.DeviceID
			$Uplink = $_.NetEnabled
			while ($state -eq 0){
				sleep 1
				$NIC = (gwmi -Class Win32_NetworkAdapter | ?{$_.DeviceID -eq $ID})
				$Uplink = $NIC.NetEnabled
				$state = $NIC.NetConnectionStatus
			}
			
			if ($Uplink -eq $false){
				$_.disable() | Out-Null
			}else{
				$array += (gwmi -Class Win32_NetworkAdapter | ?{$_.DeviceID -eq $ID})
			}
		}
	}

	return $array
}

Function: Send-WebRequest

by on May 15th, 2013

With the Send-WebRequest function it is possible to resolve the html page in plain text.
This way you can run through html pages and resolve data or build scrapers etc.

Example: Send-WebRequest -URL http://www.google.com -OutXML $false

Function Send-WebRequest
{
	param (
		[ValidateNotNullOrEmpty()]
		[Parameter(Mandatory = $true)]
		[string] $URL,
		[ValidateNotNullOrEmpty()]
		[Parameter(Mandatory = $true)]
		[bool] $OutXML
	)
	
	$request = [System.Net.WebRequest]::Create("$URL")
	$request.method = "GET"
	$response = $request.getresponse()
	$stream = $response.GetResponseStream()
	$reader = New-Object IO.StreamReader($stream)
	if ($OutXML -eq $true){
		$xml = [xml]($reader.readtoend())
		$response.close()
		return $xml
	}else{
		$reader.readtoend()
	}
}

Powershell Module – Compress files and Folders

by on February 28th, 2013

I’ve found a nice dotnetzip library that I’ve used to build a powershell module. I’ve added the functions that I use the most. I will update this module and add more functions later this year. Copy and paste the script into a “ZipFunctions.psm1″ file and store it together with the “Ionic.Zip.dll” file into a subfolder “ZipFunctions” in the modules folder.

if (Test-Path variable:\hostinvocation){
	$env:MODULEPATH = (get-item ($hostinvocation.MyCommand.path)).DirectoryName
}else{
	$env:MODULEPATH = (get-item ((get-variable myinvocation -scope script).value.Mycommand.Definition)).DirectoryName
}

Function Add-Zip
{
	<#  
	.SYNOPSIS  
	Function that compress seperate files or complete folders to a zip file  
  
	.DESCRIPTION  
	With the Add-Zip Function it is possible to compress complete folders or seperate files to a 
	zip file. If the zip doesn't exists, then it will create the zip file. When exists, it will add
	the file to the existing file

	.EXAMPLE  
	Add-Zip -Source "C:\Temp\SourceFolder" -Destination c:\Temp\example.zip
	Add-Zip -Source "C:\Temp\SourceFolder" -Destination c:\Temp\example.zip -Encryption WinZipAes256 -Password "3x@mpl3p@s$"
	Add-Zip -Source "C:\Temp\SourceFolder" -Destination c:\Temp\example.zip -CompressionLevel "Level9"
	
	.NOTES    
	Parameters:
	-Source				(The folder or file that needs to be compressed) (required)
	-Destination		(The destination (including filename) where the zip must be stored) (required)
	-Encryption			(Encryption type: PkzipWeak,WinZipAes128,WinZipAes256) (optional)
	-Password			(Password that is set on the zip file) (required on Encryption)
	-CompressionLevel	(Encryption Level type: "None", "Level0", "BestSpeed", "Level1",
						"Level2", "Level3", "Level4", "Level5", "Level6", "Level7", "Level8",
						"BestCompression", "Level9".
						
						If no Encryption type is set, then the Default encryption will be applied).
	
	.LINK  

http://www.skipdaflip.nl

	#>
	param(
		[ValidateNotNullOrEmpty()]
		[Parameter(Mandatory = $true,Position = 1)]
		[string]$Source,
		[ValidateNotNullOrEmpty()]
		[Parameter(Mandatory = $true,Position = 2)]
		[string] $Destination,
		[Parameter(Position = 3)]
		[ValidateSet("None", "Level0", "BestSpeed", "Level1",
		"Level2", "Level3", "Level4", "Level5", "Level6",
		"Level7", "Level8", "BestCompression", "Level9")]
		[string] $CompressionLevel,
		[ValidateSet("PkzipWeak","WinZipAes128","WinZipAes256")]
	  	[Parameter(Position = 4)]
	  	[string]$Encryption,
		[ValidateNotNullOrEmpty()]
		[Parameter(Position = 5)]
		[string]$Password
	)
	
	[Reflection.Assembly]::LoadFile("$env:MODULEPATH\Ionic.Zip.dll") | Out-Null
	
	
	if (($Destination -gt $null) -and ($Destination -like "*.zip") -and (($srcchk = Test-Path $Source))){
		#Create or open ZIP
		if (Test-Path $Destination){
			$zip = [Ionic.Zip.ZipFile]::read($Destination)
		}else{
			$zip = New-Object ionic.Zip.ZipFile
		}
		
		#Set CompressionLevel
		if ($CompressionLevel -eq ""){
			$zip.CompressionLevel = "Default"
		}else{
			$zip.CompressionLevel = $CompressionLevel
		}
		
		#Set Encryption
		if ($Encryption){
			$zip.Encryption = [Ionic.Zip.EncryptionAlgorithm]::$Encryption
			if ($Password){
				$zip.Password = $Password
			}else{
				$pwdchk = $false
			}
		}
		
		#Add Items to ZipFile
		if ((gi $Source).gettype().name -eq "DirectoryInfo"){
			[void]$zip.AddDirectory($Source)
		}elseif((gi $Source).gettype().name -eq "FileInfo"){
			[void]$zip.AddFile($Source)
		}else{
			return "Source file or directory not found"
			$chk = $false
		}
		
	}else{
		if ($srcchk -eq $false){
			return "Please select a valid source directory or file"
		}else{
			return "Please give a valid path and/or filename"
		}
		$chk = $false
	}
	
	if (($chk -ne $false) -and ($pwdchk -ne $false)){
		#Save Zip File
		[void]$zip.Save($Destination)
		[void]$zip.Dispose()
	}elseif($pwdchk -eq $false){
		return "Please enter a valid password"
	}
}
Function Open-Zip
{
	<#  
	.SYNOPSIS  
	Function that will extract a zip file  
  
	.DESCRIPTION  
	With the Open-Zip function you're able to extract a compressed file to a specific folder

	.EXAMPLE  
	Open-Zip -Source c:\Temp\example.zip -Destination c:\Temp\ExampleFolder
	Open-Zip -Source c:\Temp\example.zip -Destination c:\Temp\ExampleFolder -Password "3x@mpl3p@s$"
	
	.NOTES    
	Parameters:
	-Source				(The zip file that will be extracted) (required)
	-Destination		(The destination folder where the zip file will be extracted) (required)
	-Password			(Password that is set on the zip file) (optional)
	
	.LINK  

http://www.skipdaflip.nl

	#>
	param(
		[ValidateNotNullOrEmpty()]
		[Parameter(Mandatory = $true,Position = 1)]
		[string]$Source,
		[ValidateNotNullOrEmpty()]
		[Parameter(Mandatory = $true,Position = 2)]
		[string] $Destination,
		[ValidateNotNullOrEmpty()]
		[Parameter(Position = 3)]
		[string]$Password
	)
	
	[Reflection.Assembly]::LoadFile("$env:MODULEPATH\Ionic.Zip.dll") | Out-Null
	
	if (Test-Path $Source){
		$zip = [Ionic.Zip.ZipFile]::Read($Source)
		if ($Password){
			$zip.Password = $Password
		}
		if (Test-Path $Destination){
			[void]$zip.ExtractAll($Destination)
			$zip.ZipErrorAction = [Ionic.Zip.ZipErrorAction]::Skip
			[void]$zip.Dispose()
		}else{
			return "Source file `"$Destination`" not found"
		}
	}else{
		return "Source file `"$Source`" not found"
	}
}
Function Get-ZipInfo
{
	<#  
	.SYNOPSIS  
	The Get-ZipInfo will resolve all information of the compressed file
  
	.DESCRIPTION  
	This Function will show all the files/folders and all the information of all the content
	available in the zip file.

	.EXAMPLE  
	Get-ZipInfo -ZipFile c:\Temp\example.zip
	
	.NOTES    
	Parameters:
	-ZipFile				(The zip file that will enumerated) (required)
	
	.LINK  

http://www.skipdaflip.nl

	#>
	param(
		[ValidateNotNullOrEmpty()]
		[Parameter(Mandatory = $true)]
		[string]$ZipFile
	)
	
	[Reflection.Assembly]::LoadFile("$env:MODULEPATH\Ionic.Zip.dll") | Out-Null
	
	if (Test-Path $ZipFile){
		$zip = ([Ionic.Zip.ZipFile]::read($ZipFile))
		return $zip
		[void]$zip.Dispose()
	}else{
		return "Zip File not found"
	}
}
Function Remove-FromZip
{
	<#  
	.SYNOPSIS  
	The Remove-FromZip function will remove defined files or folders
  
	.DESCRIPTION  
	This Function remove files and/or folders that are available in the compressed zip file.

	.EXAMPLE  
	 Remove-FromZip -ZipFile c:\Temp\example.zip -FileName "CopyFile_To_Desktop/Example.ps1" -Password "3x@mpl3p@s$"
	
	.NOTES    
	Parameters:
	-ZipFile				(The zip file that will enumerated) (required)
	-FileName				(Define the Filename in the compressed zip file that must be removed.
							To resolve filenames in a zip file, use the Get-ZipInfo function).
	-Password				(Password that is set on the zip file) (required on Encryption)			
	
	.LINK  

http://www.skipdaflip.nl

	#>
	param(
		[ValidateNotNullOrEmpty()]
		[Parameter(Mandatory = $true,Position = 1)]
		[string]$ZipFile,
		[ValidateNotNullOrEmpty()]
		[Parameter(Mandatory = $true,Position = 2)]
		[string]$FileName,
		[ValidateNotNullOrEmpty()]
		[Parameter(Position = 2)]
		[string]$Password
	)
	
	[Reflection.Assembly]::LoadFile("$env:MODULEPATH\Ionic.Zip.dll") | Out-Null
	
	if (Test-Path $ZipFile){
		$zip = ([Ionic.Zip.ZipFile]::read($ZipFile))
		if ($Password){
			$zip.Password = $Password
		}
		$Entry = $zip[$FileName]
		[void]$zip.RemoveEntry($Entry)
		[void]$zip.Save()
		[void]$zip.Dispose()
	}else{
		return "Zip File not found"
	}
}

The dotnetzip file can be found at the following page:
Dotnetzip file

Resolve DFS Link through Powershell

by on February 23rd, 2013

I’ve build 2 functions that will work with each other. The “Find-DFSServers” Function will check your Current Active Directory for a Dfs-Configuration. And Resolve the DFS Servers that are known in your AD environment.

A second Function “Find-DFSLink” will use the “Find-DFSServers” to resolve the servername where the namespace is stored for your given path. After that it will query the WMI on that server to resolve the DFS link for the path given to the function. And returns the servername where the physical folder is stored, including the share, state and Linknames.

Function Find-DFSServers
{
	<#  
		.SYNOPSIS  
		Function that will resolve the current DFS Servers  
	  
		.DESCRIPTION  
		The Find-DFSServer will resolve the DFS Servers in your environment by resolving your current
		Active Directory and sends a LDAP query to your AD to resolve the DFS configuration. Then it
		resolves the DFS Remote Servers.

		.EXAMPLE  
		Find-DFSServers

		.NOTES    
		(no parameters required)
		
		.LINK  

http://www.skipdaflip.nl

	#>  
	
	$LDAP = "LDAP://$([string]::Join(",",@("CN=Dfs-Configuration"
	"CN=System"
	([DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()) -split("\.") | %{
		"DC=$_"
	})))"

	$DFS = [adsi]$LDAP
	$Serverlist = @()
	$DFS.Children | %{
		$_.remoteservername | %{
			if ($_ -like "*\\*"){
				$DFSSERVER = New-Object PSObject
				$DFSSERVER | Add-Member -MemberType NoteProperty -Name "RemoteServer" -Value "$($_)"
				$Serverlist += $DFSSERVER
			}
		}
	}
	
	return $Serverlist
}
Function Find-DFSLink
{
	<#  
		.SYNOPSIS  
		Function that will resolve the DFS Links from the given path
	  
		.DESCRIPTION  
		The Find-DFSLink will resolve the remote server and connects to that server to resolve the
		given path. It will split the namespace so it will filter out the correct server.
		Then it will collect all the results and returns all DFS links found. The state, Share and Servername
		where the physical folder is stored.

		.EXAMPLE  
		Find-DFSLink -path \\domainname\namespace\path

		.NOTES    
		(no parameters required)
		
		.LINK  

http://www.skipdaflip.nl

	#>  
	param (
		[ValidateNotNullOrEmpty()]
		[Parameter(Mandatory = $true)]
		[string]$Path
	)
	
	$DFSLINKS = @()
	$servers = Find-DFSServers | ?{$_.RemoteServer -like "*$(($Path -split("\\"))[3])*"}
	$srv = ((Get-Random $servers).RemoteServer -split("\\"))[2]
	$srch = $(($Path -split("$(($Path -split("\\"))[3])"))[1])
	gwmi -ComputerName $srv -class Win32_DfsTarget | ?{$_.LinkName -like "*$srch*"} | %{
		$DFSLNK = New-Object PSObject
		$DFSLNK | Add-Member -MemberType NoteProperty -Name "ServerName" -Value "$($_.ServerName)"
		$DFSLNK | Add-Member -MemberType NoteProperty -Name "LinkName" -Value "$($_.LinkName)"
		$DFSLNK | Add-Member -MemberType NoteProperty -Name "ShareName" -Value "$($_.ShareName)"
		$DFSLNK | Add-Member -MemberType NoteProperty -Name "State" -Value "$($_.State)"
		$DFSLINKS += $DFSLNK
	}
	
	return $DFSLINKS
}

Find-DFSLink -Path “\\domain\dfs\path to folder”

How to Enable Data Deduplication in Windows 8

by on January 29th, 2013

This Item is taken from the following Site:

A nice capability in the new OS of windows is swappable features from an server to a desktop Operating System. Please read the article from above where “Teh Wei King” tells about how to add a feature from Windows 2012 to Windows 8.

A nice feature to swap is the Data Deduplication. This way double items will be reduced.

dism /online /add-package /packagepath:Microsoft-Windows-VdsInterop-Package~31bf3856ad364e35~amd64~~6.2.9200.16384.cab /packagepath:Microsoft-Windows-VdsInterop-Package~31bf3856ad364e35~amd64~en-US~6.2.9200.16384.cab /packagepath:Microsoft-Windows-FileServer-Package~31bf3856ad364e35~amd64~~6.2.9200.16384.cab /packagepath:Microsoft-Windows-FileServer-Package~31bf3856ad364e35~amd64~en-US~6.2.9200.16384.cab /packagepath:Microsoft-Windows-Dedup-Package~31bf3856ad364e35~amd64~~6.2.9200.16384.cab /packagepath:Microsoft-Windows-Dedup-Package~31bf3856ad364e35~amd64~en-US~6.2.9200.16384.cab

dism /online /enable-feature /featurename:Dedup-Core /all
    Import the Feature in Windows 8

Now, because you’re on Windows 8 and not on Windows Server 2012, you can’t configure it using the Server manager. So your next best friend here is PowerShell. No biggy! Here’s how you can configure Data Deduplication using PowerShell.

These are the few commands I used to get it working. This is to enable the feature on a particular volume.

PS C:\> Enable-DedupVolume D:

This is to start the optimization manually.

PS C:\> Start-DedupJob –Volume D: –Type Optimization

To look at the progress of the dedup job.

PS C:\> Get-DedupJob

Compare ACL and replace ACL if needed

by on September 12th, 2012

We’ve created a folder on every desktop that stores all the shortcuts of all the physical applications installed on that machine. We use this concept, cause we’re using Mandatory profiles in combination with SCCM/App-V.

To make sure that shortcuts will only be applied to the right user, we’re adding security rights to the shortcuts with a powershell script template. This Template will install the application MSI/Setup or manual files. Will create a shortcut. Move shortcuts from the all-users profile to the current logged-on user that has triggered the installation and will also move the shortcuts of that installation to a specific folder on the desktop. (programdata). Also will it set a security right to the installation folder or a specific file if needed. (All optional).
This template script will also set a unique TAG in the shortcut file so that it will be defined as a managed shortcut.

When a user logs onto this computer a group policy script will run and will delete all shortcuts with this specific TAG. Then it will copy the shortcuts folder from the computer the user has logged onto. This way it will only copy the shortcuts to the userprofile if the user is a member of the security group that is set onto the shortcut.

This concept works with a Mandatory profile, Flex Profiles and SCCM/App-V streaming apps. This way manual created shortcuts in the start menu won’t be deleted. But only our own managed shortcuts.

Now something went wrong in our environment with some applications and the security rights has been overwritten on some computers. To fix this problem I’ve created a script that will check some specific folders, then compare it with a set of rights that I like to check.
Then it will report through DCM if the computer is Compliant or not.
I also created the option to enable self healing. When a mismatch has been checked, it will be reported through DCM (SCCM) and then fix the security rights to the default.

Clear-Host
#Region Controle Set
$Security = @(
	("NT AUTHORITY\SYSTEM","FullControl","ContainerInherit, ObjectInherit", "None", "Allow",$false),
	("BUILTIN\Administrators","FullControl","ContainerInherit, ObjectInherit","None","Allow",$false),
	("BUILTIN\Users","ReadAndExecute","ContainerInherit, ObjectInherit", "None","Allow",$false)
)

$Folders = @(
	"$env:ProgramData\Company\Comp_SCCM_Shortcuts\Company Applications",
	"$env:ProgramData\Company\Comp_SCCM_Shortcuts\Support",
	"$env:ProgramData\Company\Comp_SCCM_Shortcuts\Standard Office Applications"
)
#EndRegion

#Region Functions
Function RemoveACL {
	param (
		[string]$Folder,
		[string]$Member
	)
	
	if (Test-Path $Folder){
		$acl = Get-Acl $Folder
		$acl.Access | where-object {$_.IdentityReference -eq $Member} | %{$acl.RemoveAccessRule($_)} | Out-Null
		Set-Acl $Folder $acl
	}
}

Function SetACL {
	param (
		[string]$Folder,
		[string]$Member,
		[string]$Security,
		[string]$InheritanceFlags,
		[string]$PropagationFlags,
		[string]$Type,
		[bool]$Inheritance
		
	)

	$acl = Get-Acl $Folder
	$rule = New-Object system.Security.AccessControl.FileSystemAccessRule($Member, $Security, $InheritanceFlags, $PropagationFlags, $Type)
	if ($Inheritance -eq $false){$acl.SetAccessRuleProtection($true,$true)}
	$acl.SetAccessRule($rule)
	Set-Acl $Folder $acl
}

Function CheckSecurity {
	param (
		[bool]$AutoRepair,
		[array]$FoundSec,
		[array]$Compare,
		[string]$Folder
	)
	
	$array = @()	
	$FoundSec | %{
		
		# Check Memberships
		
		if ( -not (($Compare | %{($_)[0]}) | Select-String (($val = $_.IdentityReference.value) -replace "\\","\\"))){
			$array += "$Folder, $Val ,$($_.FileSystemRights), Unauthorized Group/User"
			
			if ($AutoRepair -eq $true){
				removeACL -Folder $Folder -Member $Val
			}
		}else{
			
			# Check Security rights on matched folders
						
			$i = (($Compare | %{($_)[0]}) | Select-String ($_.IdentityReference.Value -replace "\\","\\")).linenumber - 1
			
			if ((($_.FileSystemRights -split (","))[0]) -ne ($Compare[$i][1]) -or ($_.InheritanceFlags) -ne ($Compare[$i][2]) -or $_.PropagationFlags -ne ($Compare[$i][3]) -or $_.AccessControlType -ne ($Compare[$i][4]) -or $_.IsInherited -ne ($Compare[$i][5])){
				$array += "$Folder, $($_.IdentityReference.value),$($_.FileSystemRights), False Permissions"			
				if ($AutoRepair -eq $true){
					setacl -Folder $Folder -Member ($Compare[$i][0]) -Security ($Compare[$i][1]) -InheritanceFlags ($Compare[$i][2]) -PropagationFlags ($Compare[$i][3]) -Type ($Compare[$i][4]) -Inheritance ($Compare[$i][5])
				}
			}	
		}		
	}
	
	# Check for missing memberships
	$Compare | %{
		if (((($_)[0]).gettype().basetype.name) -eq "Object"){
			
			$a = ($_)[0]
			if (-not ($FoundSec | Where-Object {$_.IdentityReference -eq $a})){
				
				$array += "$Folder, $a, Not Set"
				
				if ($AutoRepair -eq $true){
					setacl -Folder $Folder -Member $a -Security (($_)[1]) -InheritanceFlags (($_)[2]) -PropagationFlags (($_)[3]) -Type (($_)[4]) -Inheritance (($_)[5])
				}
			}
		}
	}
	
	# Return
	if ($array -eq $null){return $null}else{return $array}
}
#EndRegion

# ----------------------------------------------------------
# Enable Automatic Repair : $true/$false
# ----------------------------------------------------------
$AutoRepair = $false
# ----------------------------------------------------------

$array = @()
$Folders | %{
	$SR = (Get-Acl "$_").Access
	$vitems = CheckSecurity -FoundSec $SR -Compare $Security -Folder $_ -AutoRepair $AutoRepair
	if ($vitems -ne $null){$array += $vitems}
}

if ($array.count -eq 0){Write-Output $true}else{Write-Output $array}