PS – parameter by reference

Many developers know them – parameter by reference. By this way the variables will not be duplicated. A pointer is created which points to the actual variable. If you modify this referenced parameter you will modify the referenced variable. So you can make changes to many parameters and will not create a lot of functions with returnvalues.

[string]$Global = ''


function TestRefFunction([ref]$Param)
{
    [string]$Param.Value = '5'
    $Param | Out-Default
}

TestRefFunction([ref]$Global)

$Global | Out-Default

By this example the transmitted parameter “$global” is a reference. So all changes to it in the function will also be written into the global variable. In this example so 2 times a “5” will be given out.

~David

PS – configuration for bigger scripts and simple logging

Hello all

In this post i want to show you how to create a configuration with a XML-file easily.
Lots of configuration parameters can be placed in here so that the end user makes his changes in this XML-file where the impact of modifications can be mitigated. Also it cleans up the source code. By loading all relevant parameters within one file you have to look and store all properties at only one place.

Also you can place complex configuration lists and conditional matrixes in it to load them later on with powershell and filter the outcome.

Some examples:

Loading the XML-file

[xml] $configXml = Get-Content -Path "$PSScriptRoot\Config.xml" -ErrorAction 'Stop'

Yeah – that easy.

Exemplaric structure of a file:

<?xml version="1.0" standalone="yes"?>
<Config>
   <DBConnectionString>Provider = OraOLEDB.Oracle; Data Source = ds ; User Id = USER ; Password = pwuser; OLEDB.NET = True;</DBConnectionString>
   <LogDir>c:\Logs</LogDir>
   <ConfigValue Value1="val1"></ConfigValue>
   <ConditionalMatrix>
     <Parameter Value1="val1" Value2="start" BoolValue="1"></Parameter>
     <Parameter Value1="val1" Value2="end" BoolValue="0"></Parameter>
     <Parameter Value1="val2" Value2="test" BoolValue="1"></Parameter>
     <Parameter Value1="val2" Value2="test" BoolValue="0"></Parameter>
     <Parameter Value1="val3" Value2="prod" BoolValue="1"></Parameter>
     <Parameter Value1="val3" Value2="test" BoolValue="0"></Parameter>
   </ConditionalMatrix>
</Config>

Retrieving the data:

#fetching the data directly
$ConnectionString= $configXML.Config.DBConnectionString
$Value1= $configXML.Config.ConfigValue.Value1

$Value1ByConditionalMatrix= ($configXML.Config.ConditionalMatrix.Parameter  | Where-Object {$_.Value2-eq "test" -and $_.BoolValue-eq "1"}).Value1

Easy isn´t it?! Now you have to load the configuration within the script from a relativ path. This could also be the path where afterwards the loggings could be stored into.

A very simple way for logging is to set gather the logging path from config/relative and write log files with a date in it. So you get an overview for each day.

$LogDir=$configXML.Config.LogDir
$LogFile = "$LogDir\Log" + ((Get-Date).Day) + "_" + ((Get-Date).Month) + "_" + ((Get-Date).Year) + "_" + ((Get-Date).Hour) + "_" + ((Get-Date).Minute) +".log"
(Get-Date).ToString()  + " Something happened $Object" >> $LogFile

This can also be empowered even more if you build a separate function for this. So you can grab executing function, date, user etc. which will be written to a log file.

I hope i could give you some hints of the power with working xml-configuration files and enabling you the view for very simple logging.

~David

PS – download of csv-files of a folder from Sharepoint via webclient

In this example the assumption is that you don´t have a Sharepoint server on which you could use the Sharepoint commandlets. So only the standard webclient functions were used to allow you to download all files. Also you need some valid credentials to log onto the Sharepoint website otherwise you would get the error 401 (not authorized).

Here is the code herefore:


<# 
.Synopsis 
Download all files from a sharepoint folder. 
.DESCRIPTION 
download all files from a sharepoint aspx-site. 
.EXAMPLE 
$credentials=Get-Credential -Credential Domäne\Benutzer 
[string]$sharepointURL = 'https://domäne.de/ExportOrdner/Forms/Overview.aspx' Download-AllFilesFromSP -SP_ASPX_Page $sharepointURL -DestinationFolder 'C:\ExportDirectory' -Credentials $credentials 
.INPUTS SP_ASPX_Page - aspx-site DestinationFolder target  CredentialsSP - authentication 
.FUNCTIONALITY 
Web; Sharepoint; Download 
#>
  function Download-AllCSVFilesFromSP
        {
            PARAM (
                [parameter(Mandatory=$true)]
                $SP_ASPX_Page,
                [parameter(Mandatory=$true)]
                $DestinationFolder,
                [parameter(Mandatory=$true)]
                $CredentialsSP
            )

            #create Object            
            $webclient = New-Object System.Net.WebClient 

            #set credentials
            $webclient.Credentials = $CredentialsSP 
            
            #retrieve content
            $response = Invoke-WebRequest -Uri $SP_ASPX_Page -Credential $CredentialsSP -Method Get

            #parse content parsen and search for export-files
            $matches =[regex]::Matches($response.content,'(\sUrl=\")+[0-9,a-z,A-Z\/_-]*(.csv\"\s)') 

            #foreach found file
            foreach ($item in $matches)
            {
                    #clean the download string             
                    $downloadFileURL = ($item.Groups[0].Value).Split('"')[1]

                    #extract the domain
                    $UrlDomain = ([regex]::Matches($SP_ASPX_Page,'https://[0-9,a-z,A-Z_\-\.]*')).Value

                    #extract filename
                    $downloadFile = $downloadFileURL.Split('/')[-1]
                    
                    #download to destination folder
                    $webclient.downloadfile($UrlDomain + $downloadFileURL,  $DestinationFolder + '\' + $downloadFile) 
            }
        }

PS – remote execution of scripts

In this post i want to show you some ways how to execute remote execution of scripts.

First the complicated way:

connect – set execution policy – copy script, execute, delete – roll back execution policy

$Computername=Name
#"Start Session"
$s = New-PSSession -ComputerName $Computername
#"Enable Script Execution on remote System..."
Invoke-Command -Session $s -scriptblock { Set-executionpolicy unrestricted }
#Copy Script
Copy-Item H:\Skript.ps1 \\$Computername\c$\temp\Skript.ps1
#"Start Script..."
Invoke-Command -Session $s -scriptblock { c:\temp\Skript.ps1 }
#Delete Script
Remove-Item \\$Computername\c$\Skript.ps1
#Disable Script Execution on remote System...
Invoke-Command -Session $s -scriptblock { Set-executionpolicy default }
#End Session
Remove-PSSession $s

Next we use Invoke-Command – the scriptfile is copied and executed within the command itself:

Invoke-Command -computer Computername -FilePath C:\Skript.ps1

Next code connects to a computer NOT using Kerberos. This can become necessary if you want to connect to computers outside your domain:

$Computername=Name

#Not using Kerberos:
cd WSMan:\localhost\Client
Set-Item trustedhosts $Computername -force
Restart-Service winrm
Invoke-Command Computername { #Skript in here#} -authentication negotiate -credential Get-Credential

Have fun with it.

~David