PowerShell Caratteri Speciali – Special Characters And Tokens

Site
 

$ (dollar sign)

Declare/use a variable
Example.
$abc = "123"
 

$_ (dollar underscore)

‘THIS’ token. Typically refers to the item inside a foreach loop.
Task: Print all items in a collection.
Solution.
... | foreach { Write-Host $_ }
 

$$ (double dollar, two dollars)

Last token of last command. Does NOT refer to the whole command.
Example.
Write-Host "Hello, world!"
$$

Output.
Hello, world!
Hello, world!
 

$^ (dollar sign + caret)

Thanks to Richard for accidentally finding this one.
First token of last command. Does NOT refer to the whole command.
Example.
Write-Host "Hello, world!"
$^

Output.
Hello, world!
Write-Host
 

$? (dollar sign + question mark)

Many google searches were looking for this information, so I experimentally found what it does.
Returns True or False value indicating whether previous command ended with an error. For some reason it does not catch all errors, but most of the time it works.
Task 1: See if a powershell cmdlet exists in the system.
Code.
SomeCmdLet #does not exists
$?
$?

Output.
The term ‘SomeCmdLet’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:15
+ SomeCmdLet <<<< #does not exists
+ CategoryInfo : ObjectNotFound: (SomeCmdLet:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
False #error occured – previous cmdlet (SomeCmdLet) was not found
True #no errors returned by the previous command ($?)

Task 2: See if a WMI class exists in the system
Code.
gwmi win32_processo -ErrorAction SilentlyContinue #intentional error, win32_processor is the right one
$?
$?

Output.
False
True
 

$() (dollar sign + round brackets)

Thanks to Kevin for a suggestion to add this one.
Sub-expression operator for double-quoted strings. Whatever is in the brackets should be evaluated first.
Example.
$name = "Kevin";
"Hello, $name, there are $($name.length) characters in your name"

Output.
Hello, Kevin, there are 5 characters in your name

It can be used with any expression, so this will also work:
“There are $(2+3) characters in your name”
 

${} (dollar sign + curly brackets)

Thanks to Remco for a hint about it.
Declare or use a variable with non-standard characters in it, a more generalized syntax to $variableName. It adds support for punctuation or non-English characters.
References: StackOverflow, Technet, ss64.com.
Example.
${,,,} = 5
${,,,}

Output.
5
 

| (pipeline)

Catch output of the command and pass it to another command.
Task: Get list of processes and select top 3 items.
Solution.
Get-Process | Select-Object -first 3
 

% (percentage)

1. Shortcut to foreach.
Task: Print all items in a collection.
Solution.
... | % { Write-Host $_ }

2. Same as Mod in VB.
Example:
5 % 2
 

.. (double dot)

Specify a range.
Task: Print numbers 1 through 5 without a foreach loop.
Code.
1..5
Output.
1
2
3
4
5
 

:: (double-colon)

Thanks to Darrell for asking about this one.
Reference static member of a class. The class name must be enclosed in square brackets.
Task: Compare two strings.
Code.
[string]::Equals("a", "b")
Output.
False
 

+ (plus sign)

Thanks to Cody for pointing at this feature of Powershell.
Aside from its natural use, i.e. addition of two arguments, you can also use a plus sign to reference a public nested class.
For official reference, see here. Thanks to David Brabant for help in figuring this out.
Code.
[System.Net.WebRequestMethods+Ftp]::UploadFile
Output.
STOR
 

+= (plus equals)

Thanks to Brian G.
Increments value on the left by the amount on the right (and stores result). For strings it means concatenation.
Very well known to C# developers, so not strictly a Powershell feature.
In Powershell, however, this operator has a special use – you can add elements to arrays.
Mostly syntactic sugar, the array is still recreated behind the scenes, so just to save a few characters.
Code.
$b = 1 #initialize a variable
$b += 2 #add 2
$b #output 3 (1 + 2)

$a = @(1,2,3) #initialize array with 3 elements
$a += 4 #add element number 4
$a #output 4 elements
Output.
3

1
2
3
4
 

! (exclamation mark)

Thanks to Leo for asking about this one.
Shortcut to -not.
Code.
$a = $null;
if(!$a) { Write-Host '$a is null' }

Output.
$a is null
 

? (question mark)

Output all items that conform with condition (shortcut to where). Shortcut to the following:
foreach { if (…) {return … } }
Task: Print all odd numbers between 1 and 5 (inclusive):
Code.
1..5 | ? { $_ % 2 }
Output.
1
3
5
 

` (backtick)

1. Continue command on the next line.
Code.
Write-Host `
"Hello, world!"

Output.
Hello, world!

2. Include a special symbol into a string. Available options:
`$ – include a dollar symbol in your string. If you don’t escape it, Powershell will assume you are trying to embed a variable.
`0 – Null. My preference is using $null instead.
`a – Alert. Yes, it does make sound, and you can use multiple for multiple beeps.
`b – Backspace
`f – form feed – only affects printed documents.
`n – New line
`r – Carriage return
`t – Horizontal tab
`v – Vertical tab – only affects printed documents.
`’ – Single quote – I prefer using double quotes when I need to escape a single one, since I don’t need any escaping in this case.
`” – Double quote – you can use single quotes, and you don’t need this symbol. My preference is use standard escaping instead, so 4 double quotes (“”””) means a double quote.
Official article by Microsoft with full description on every token: http://technet.microsoft.com/en-us/library/hh847835.aspx
 

# (hash sign)

Single line comment.
Example.
#This is a commented line
#This is a second one

 

<# … #> (left angle bracket / &lt + pound … pound + right angle bracket / &gt)

Block/Multi-line comment.
Example.
<#This is a commented block#>
 

& (ampersand)

Execute string as command.
Example.
& "Get-Process"
 

@( ) (email-at + round brackets)

Declare arrays.
Note: comma is used as a separator, in contrast to hash table declaration.
Example.
$a = @("One", "Two", "Three")
 

@{ } (email-at + curly brackets/braces)

Declare hash tables.
Note: semicolon is used as a separator, in contrast to array declaration.
Example.
$a = @{"1" = "one"; "2" = "two"; "3" = "three"}
 

@’ … ‘@ (email-at + single quote … single quote + email-at)

Here-string without embedded variables.
Code.
@'
$(1+2)
$(3+4)
$(5+6)
'@

Output.
$(1+2)
$(3+4)
$(5+6)
 

@” … “@ (email-at + double quote … double quote + email-at)

Here-string with embedded variables or other code bloc from other language like C# C++.
Code.
@"
$(1+2)
$(3+4)
$(5+6)
"@

Output.
3
7
11

Annunci

Migrazione Dominio Client Windows 7

Prima Esperienza Powershell molto interessante. Necessario PsExec dei PSTolls. Posizionare nella stessa cartella 4 file loop.bat, migra.ps1, pc_list.txt e psexec.exe. inserire uno per riga gli ip dei pc da migrare nel file pc_list.txt. Eseguire cmd.exe con diritti di amministrazione del vecchio dominio da cui si sta migrando (es:old.dir.domain.old). Posisizionarsi nella cartella contenente i file ed eseguire loop.bat

:: loop.bat esegue lo script migra.ps1 tramite psexec nei computer definiti

:: Necessario che ogni riga del file pc_list.txt sia un indirizzo ip e che il file
:: sia nella stessa cartella dello script e che lo script sia lanciato dalla cartella
:: dove si trova con credenziali che abbiano diritti di amministrazione nei pc didestinazione

for /F %%I in (pc_list.txt) do call :azioni %%I
goto :_EOF

:azioni

date /t >> migraLog.txt
time /t >> migraLog.txt

echo %1 >> migraLog.txt

:: ******* = password .\Administrator macchina remota

xcopy migra.ps1 \\%1\C$\admin\ /C /Y >> migraLog.txt
psexec.exe \\%1 -u .\Administrator -p ******* -h PowerShell.exe -ExecutionPolicy Bypass -File "C:\migra.ps1" >> migraLog.txt

goto :_EOF

:_EOF

# migra.ps1 Retrocompatibile Windows PowerShell 1.0 http://technet.microsoft.com/en-us/library/hh848793.aspx

Param(
        [ValidateSet("join","")]
        [String] 
        $Parametro
    ) 

if ($Parametro -eq "join")
    {
        # ******* = password user new.domain.new\domainadmin
        gwmi Win32_ComputerSystem -computername $env:computername | ForEach-Object{$_.JoinDomainOrWorkgroup('new.domain.new','*******','new.domain.new\domainadmin',$null,3)}

        Set-Location -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon'
        Set-ItemProperty -Path . -Name AutoAdminLogon -Value "0"
        Set-ItemProperty -Path . -Name DefaultUserName -Value "install"
        Remove-ItemProperty -Path . -Name DefaultPassword
        Remove-ItemProperty -Path . -Name ForceAutoLogon
        
        Remove-Item C:\migra.ps1
        
        Start-Sleep -s 2
        
        Restart-Computer -Force
    }
else
    {
        # Unjoin

        $domain = "old.dir.domain.old"
        # ******* = password user $domain\domainadmin
        $result = gwmi Win32_ComputerSystem -computername $env:computername | ForEach-Object{$_.UnjoinDomainOrWorkgroup('*******','$domain\domainadmin')}

        # gwmi abbreviazione di Get-WmiObject http://technet.microsoft.com/en-us/library/ee692685.aspx
        
        switch($result.ReturnValue)
            {       
                0 { Write-Host "Unjoin " $env:computername "on domain " $domain "`n"}
                5  { Write-Host "Unjoin Access is denied" "`n"}
                87 { Write-Host "Unjoin The parameter is incorrect""`n"}
                110 { Write-Host "Unjoin The system cannot open the specified object""`n"}
                1323 { Write-Host "Unjoin Unable to update the password""`n"}
                1326 { Write-Host "Unjoin Logon failure: unknown username or bad password""`n"}
                1355 { Write-Host "Unjoin The specified domain either does not exist or could not be contacted""`n"}
                2224 { Write-Host "Unjoin The account already exists""`n"}
                2691 { Write-Host "Unjoin The machine is already joined to the domain""`n"}
                2692 { Write-Host "Unjoin The machine is not currently joined to a domain""`n"}
            
                default { Write-Host "Error - return value of " $result.ReturnValue }
            }
    
        # Join to WORKGROUP

        $domain = "WORKGROUP"
        $result = gwmi Win32_ComputerSystem -computername $env:computername | ForEach-Object{$_.JoinDomainOrWorkgroup($domain,'','a',$null,$null)}
        switch($result.ReturnValue)
            {       
                0 { Write-Host "Join to WORKGROUP " $env:computername "on domain " $domain"`n"}
                5  { Write-Host "Join to WORKGROUP Access is denied"}
                87 { Write-Host "Join to WORKGROUP The parameter is incorrect""`n"}
                110 { Write-Host "Join to WORKGROUP The system cannot open the specified object""`n"}
                1323 { Write-Host "Join to WORKGROUP Unable to update the password""`n"}
                1326 { Write-Host "Join to WORKGROUP Logon failure: unknown username or bad password""`n"}
                1355 { Write-Host "Join to WORKGROUP The specified domain either does not exist or could not be contacted""`n"}
                2224 { Write-Host "Join to WORKGROUP The account already exists""`n"}
                2691 { Write-Host "Join to WORKGROUP The machine is already joined to the domain""`n"}
                2692 { Write-Host "Join to WORKGROUP The machine is not currently joined to a domain""`n"}
        
                default { Write-Host "Error - return value of " $result.ReturnValue "`n"}
            }

        # change DNS

        $pattern = '^192.168.(\w+)'
        $newDNS = "192.168.0.30","192.168.0.31"
        $DNSSuffixx = "dir.domain.new","new.dir.domain.new","new.domain.new"
        $NICs = gwmi -ComputerName $env:computername Win32_NetworkAdapterConfiguration | Where-Object {$_.IPAddress -match $pattern}

        ForEach($NIC in $NICs)
            {
                $x = $NIC.SetDNSServerSearchOrder($newDNS)
                if($x.ReturnValue -eq 0){Write-Host "Successfully Changed DNS Servers on " $env:computername "`n"}
                else{Write-Host "Failed to Change DNS Servers on " $env:computername " Error:" $x.ReturnValue "`n"}
            
                $x = Invoke-WmiMethod -Class Win32_NetworkAdapterConfiguration -Name SetDNSSuffixSearchOrder -Computername $env:computername -ArgumentList @($DNSSuffixx),$null
                if($x.ReturnValue -eq 0){Write-Host "Successfully Insert DNS Suffix on " $env:computername "`n"}
                else{Write-Host "Failed to Change Insert DNS Suffix on " $env:computername " Error:" $x.ReturnValue "`n"}
            
            }

        # Rename
        
        Write-Host "Old Name is " $env:computername "`n"

        $ComputerName = $env:computername -replace "^(\w+)-(\w+)", 'acc-$2'
        
        # ******* = password local Administrator
        
        $result = gwmi Win32_ComputerSystem -computername $env:computername | ForEach-Object{$_.rename($ComputerName,"******","Administrator")}

        # gwmi abbreviazione di Get-WmiObject http://technet.microsoft.com/en-us/library/ee692685.aspx
        
        switch($result.ReturnValue)
            {       
                0 { Write-Host "New Name " $ComputerName "`n"}
                5  { Write-Host "Rename Access is denied" "`n"}
                87 { Write-Host "Rename The parameter is incorrect""`n"}
                110 { Write-Host "Rename The system cannot open the specified object""`n"}
                1323 { Write-Host "Rename Unable to update the password""`n"}
                1326 { Write-Host "Rename Logon failure: unknown username or bad password""`n"}
                1355 { Write-Host "Rename The specified domain either does not exist or could not be contacted""`n"}
                2224 { Write-Host "Rename The account already exists""`n"}
                2691 { Write-Host "Rename The machine is already joined to the domain""`n"}
                2692 { Write-Host "Rename The machine is not currently joined to a domain""`n"}
            
                default { Write-Host "Error Rename - return value of " $result.ReturnValue }
            }
        
        # RunOnce joinDomain

        Set-Location -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce'
        Set-ItemProperty -Path . -Name joinDomain -Value "C:\WINDOWS\system32\WindowsPowerShell\v1.0\Powershell.exe -ExecutionPolicy Bypass -File C:\admin\migra.ps1 join"
        
        # Autologon
        
        Set-Location -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon'
        Set-ItemProperty -Path . -Name AutoAdminLogon -Value "1"
        Set-ItemProperty -Path . -Name DefaultUserName -Value "Administrator"
        Set-ItemProperty -Path . -Name DefaultPassword -Value "******"
        Set-ItemProperty -Path . -Name ForceAutoLogon -Value "1"
        
        Start-Sleep -s 2
        
        Restart-Computer -Force
    }

# Riferimenti

# http://timnew.github.io/blog/2012/04/13/powershell-script-to-rename-computer-without-reboot/
# https://gist.github.com/timnew/2373475#file-rename-ps1
# 
# http://technet.microsoft.com/en-us/library/dd315394.aspx
# 
# http://technet.microsoft.com/it-it/magazine/2007.11.powershell.aspx
# http://technet.microsoft.com/en-us/library/hh847880.aspx
# http://technet.microsoft.com/en-us/library/hh847759.aspx
# http://ss64.com/ps/syntax-regex.html
# http://www.regular-expressions.info/powershell.html
# http://blogs.technet.com/b/heyscriptingguy/archive/2011/03/21/use-powershell-to-replace-text-in-strings.aspx
# http://powershell.com/cs/blogs/tobias/archive/2011/10/27/regular-expressions-are-your-friend-part-1.aspx
# http://www.powershelladmin.com/wiki/Powershell_regular_expressions
#
# http://social.technet.microsoft.com/Forums/windowsserver/en-US/ed3f4c9e-1467-4795-b9d1-ae41937b8962/script-to-change-dns-servers-on-remote-server?forum=winserverpowershell
# 
# http://stackoverflow.com/questions/6217799/rename-computer-and-join-to-domain-in-one-step-with-powershell
# 
# http://community.spiceworks.com/scripts/show/1540-join-computer-to-domain-with-powershell-one-click-method
#
# http://ss64.com/ps/syntax-esc.html