Import-Module AzureADPreview
$keyCarrierGroups = #()
$DynamicGroupSet = #()
$storeInfo = #{}
$keyCarrierGroups = (Get-ADGroup -Filter {DisplayName -like "*_Key_Carriers"})
foreach ($group in $keyCarrierGroups){
$DynamicGroupSet.Add((Get-AzureADMSGroup -Id $group.Name.Split("_")[1]))
}
foreach($group in $DynamicGroupSet){$storeInfo.add($group.DisplayName.Split("_")[0],$group.Id)}
foreach($store in $storeinfo.Keys){Set-AzureADMSGroup -Id $storeinfo.Item($store) -MembershipRule {(user.Department -contains $store) -and (user.extensionAttribute3 -eq "A") -and (user.extensionAttribute6 -contains "10005") -or (user.extensionAttribute6 -contains "10006") -or (user.extensionAttribute6 -contains "10013") -or (user.extensionAttribute6 -contains "10064") -or (user.extensionAttribute6 -contains "10070") -or (user.extensionAttribute6 -contains "10078") -or (user.extensionAttribute6 -contains "10146") -or (user.extensionAttribute6 -contains "205") -or (user.extensionAttribute6 -contains "10158") -or (user.extensionAttribute6 -contains "10173") -or (user.extensionAttribute6 -contains "40057") -or (user.extensionAttribute6 -contains "10012") -or (user.extensionAttribute6 -contains "10022") -or (user.extensionAttribute6 -contains "10023") -or (user.extensionAttribute6 -contains "10104") -or (user.extensionAttribute6 -contains "10123") -or (user.extensionAttribute6 -contains "70017") -or (user.extensionAttribute6 -contains "70029") -or (user.extensionAttribute6 -contains "70056") -or (user.extensionAttribute6 -contains "70099") -or (user.extensionAttribute6 -contains "80004") -or (user.extensionAttribute6 -contains "80016") -or (user.extensionAttribute6 -contains "80076") -or (user.extensionAttribute6 -contains "80143") -or (user.extensionAttribute6 -contains "80156") -or (user.extensionAttribute6 -contains "10166") -or (user.extensionAttribute6 -contains "10179") -or (user.extensionAttribute6 -contains "80178") -or (user.extensionAttribute6 -contains "80217") -or (user.extensionAttribute6 -contains "80224") -or (user.extensionAttribute6 -contains "10010") -or (user.extensionAttribute6 -contains "80003") -or (user.extensionAttribute6 -contains "80011") -or (user.extensionAttribute6 -contains "80014") -or (user.extensionAttribute6 -contains "80066") -or (user.extensionAttribute6 -contains "80090") -or (user.extensionAttribute6 -contains "10136") -or (user.extensionAttribute6 -contains "10159") -or (user.extensionAttribute6 -contains "10181") -or (user.extensionAttribute6 -contains "10183") -or (user.extensionAttribute6 -contains "10185") -or (user.extensionAttribute6 -contains "70128") -or (user.extensionAttribute6 -contains "80177") -or (user.extensionAttribute6 -contains "80191")}}
So far I have tried a $DynamicGroupSet += and .add. When Debugging the array is null. I have confirmed (Get-AzureADMSGroup -Id $group.Name.Split("_")[1]) returns what I am looking for. Cannot figure out why its not populating in the array.
As commenter Lee_Dailey correcty stated, the .Add() method doesn't work for arrays. When I call .Add() on an array I get the following error message which explains it pretty much:
Exception calling "Add" with "1" argument(s): "Collection was of a
fixed size."
PowerShell's += operator works around this by recreating the array with the new size everytime you call the operator. Of course this is not very efficient, so += should be avoided unless the array will be very small.
In most cases += isn't even necessary, because PowerShell automatically (and more efficiently) creates an array when you assign the output of a cmdlet or a script block to a variable. You can even assign the output of control statements such as foreach, if and switch to a variable.
So, remove this line...
$DynamicGroupSet = #()
...and do this instead:
$DynamicGroupSet = foreach ($group in $keyCarrierGroups){
Get-AzureADMSGroup -Id $group.Name.Split("_")[1]
}
You see that the code even becomes much cleaner.
PowerShell automatically captures the output of everything that runs in the foreach body and adds it to $DynamicGroupSet, which will be an array if there are more than one elements.
Related
I am trying to get list of expiring App registrations in 7 days. In local it is working perfectly but I facing Insufficient privileges issue in automation account. I am the global administrator of the account and provided permission to service connection api below are the permissions
I literally given all the permission but don't know what i am missing. Below is the error
Get-AzureADApplication : Error occurred while executing GetApplications Code: Authorization_RequestDenied Message: Insufficient privileges to complete the operation. RequestId: a83caa17-1c58-433a-b0ea-f4a3f8a43d7f DateTimeStamp: Mon, 14 Feb 2022 04:56:58 GMT HttpStatusCode: Forbidden HttpStatusDescription: Forbidden HttpResponseStatus: Completed At line:11 char:17 + $Applications = Get-AzureADApplication -all $true + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Get-AzureADApplication], ApiException + FullyQualifiedErrorId : Microsoft.Open.AzureAD16.Client.ApiException,Microsoft.Open.AzureAD16.PowerShell.GetApplication
And below is the script
#Connect-AzureAD
$Applications = Get-AzureADApplication -all $true
$Logs = #()
$Days = 7
$AlreadyExpired = "YES"
$now = get-date
foreach ($app in $Applications) {
$AppName = $app.DisplayName
$AppID = $app.objectid
$ApplID = $app.AppId
$AppCreds = Get-AzureADApplication -ObjectId $AppID | select PasswordCredentials, KeyCredentials
$secret = $AppCreds.PasswordCredentials
$cert = $AppCreds.KeyCredentials
foreach ($s in $secret) {
$StartDate = $s.StartDate
$EndDate = $s.EndDate
$operation = $EndDate - $now
$ODays = $operation.Days
if ($AlreadyExpired -eq "No") {
if ($ODays -le $Days -and $ODays -ge 0) {
$Owner = Get-AzureADApplicationOwner -ObjectId $app.ObjectId
$Username = $Owner.UserPrincipalName -join ";"
$OwnerID = $Owner.ObjectID -join ";"
if ($owner.UserPrincipalName -eq $Null) {
$Username = $Owner.DisplayName + " **<This is an Application>**"
}
if ($Owner.DisplayName -eq $null) {
$Username = "<<No Owner>>"
}
$Log = New-Object System.Object
$Log | Add-Member -MemberType NoteProperty -Name "ApplicationName" -Value $AppName
$Log | Add-Member -MemberType NoteProperty -Name "ApplicationID" -Value $ApplID
$Log | Add-Member -MemberType NoteProperty -Name "Secret Start Date" -Value $StartDate
$Log | Add-Member -MemberType NoteProperty -Name "Secret End Date" -value $EndDate
$Log | Add-Member -MemberType NoteProperty -Name "Certificate Start Date" -Value $Null
$Log | Add-Member -MemberType NoteProperty -Name "Certificate End Date" -value $Null
$Log | Add-Member -MemberType NoteProperty -Name "Owner" -Value $Username
$Log | Add-Member -MemberType NoteProperty -Name "Owner_ObjectID" -value $OwnerID
$Logs += $Log
}
}
elseif ($AlreadyExpired -eq "Yes") {
if ($ODays -le $Days) {
$Owner = Get-AzureADApplicationOwner -ObjectId $app.ObjectId
$Username = $Owner.UserPrincipalName -join ";"
$OwnerID = $Owner.ObjectID -join ";"
if ($owner.UserPrincipalName -eq $Null) {
$Username = $Owner.DisplayName + " **<This is an Application>**"
}
if ($Owner.DisplayName -eq $null) {
$Username = "<<No Owner>>"
}
$Log = New-Object System.Object
$Log | Add-Member -MemberType NoteProperty -Name "ApplicationName" -Value $AppName
$Log | Add-Member -MemberType NoteProperty -Name "ApplicationID" -Value $ApplID
$Log | Add-Member -MemberType NoteProperty -Name "Secret Start Date" -Value $StartDate
$Log | Add-Member -MemberType NoteProperty -Name "Secret End Date" -value $EndDate
$Log | Add-Member -MemberType NoteProperty -Name "Certificate Start Date" -Value $Null
$Log | Add-Member -MemberType NoteProperty -Name "Certificate End Date" -value $Null
$Log | Add-Member -MemberType NoteProperty -Name "Owner" -Value $Username
$Log | Add-Member -MemberType NoteProperty -Name "Owner_ObjectID" -value $OwnerID
$Logs += $Log
}
}
}
foreach ($c in $cert) {
$CStartDate = $c.StartDate
$CEndDate = $c.EndDate
$COperation = $CEndDate - $now
$CODays = $COperation.Days
if ($AlreadyExpired -eq "No") {
if ($CODays -le $Days -and $CODays -ge 0) {
$Owner = Get-AzureADApplicationOwner -ObjectId $app.ObjectId
$Username = $Owner.UserPrincipalName -join ";"
$OwnerID = $Owner.ObjectID -join ";"
if ($owner.UserPrincipalName -eq $Null) {
$Username = $Owner.DisplayName + " **<This is an Application>**"
}
if ($Owner.DisplayName -eq $null) {
$Username = "<<No Owner>>"
}
$Log = New-Object System.Object
$Log | Add-Member -MemberType NoteProperty -Name "ApplicationName" -Value $AppName
$Log | Add-Member -MemberType NoteProperty -Name "ApplicationID" -Value $ApplID
$Log | Add-Member -MemberType NoteProperty -Name "Certificate Start Date" -Value $CStartDate
$Log | Add-Member -MemberType NoteProperty -Name "Certificate End Date" -value $CEndDate
$Log | Add-Member -MemberType NoteProperty -Name "Owner" -Value $Username
$Log | Add-Member -MemberType NoteProperty -Name "Owner_ObjectID" -value $OwnerID
$Logs += $Log
}
}
elseif ($AlreadyExpired -eq "Yes") {
if ($CODays -le $Days) {
$Owner = Get-AzureADApplicationOwner -ObjectId $app.ObjectId
$Username = $Owner.UserPrincipalName -join ";"
$OwnerID = $Owner.ObjectID -join ";"
if ($owner.UserPrincipalName -eq $Null) {
$Username = $Owner.DisplayName + " **<This is an Application>**"
}
if ($Owner.DisplayName -eq $null) {
$Username = "<<No Owner>>"
}
$Log = New-Object System.Object
$Log | Add-Member -MemberType NoteProperty -Name "ApplicationName" -Value $AppName
$Log | Add-Member -MemberType NoteProperty -Name "ApplicationID" -Value $ApplID
$Log | Add-Member -MemberType NoteProperty -Name "Certificate Start Date" -Value $CStartDate
$Log | Add-Member -MemberType NoteProperty -Name "Certificate End Date" -value $CEndDate
$Log | Add-Member -MemberType NoteProperty -Name "Owner" -Value $Username
$Log | Add-Member -MemberType NoteProperty -Name "Owner_ObjectID" -value $OwnerID
$Logs += $Log
}
}
}
}
$p = Write-Output $Logs | Format-Table -Property "ApplicationName","Secret End Date","Certificate End Date","Owner" | Out-String
Write-host $p
#Write-host "Add the Path you'd like us to export the CSV file to, in the format of <C:\Users\<USER>\Desktop\Users.csv>" -ForegroundColor Green
#$Path = Read-Host
#$Logs | Export-CSV $Path -NoTypeInformation -Encoding UTF8
Install-Module -Name PSSendGrid
Import-Module -Name PSSendGrid
$Parameters = #{
FromAddress = "kk****#abc.com"
ToAddress = "k********i#gmail.com", "kkucharkanti#gmail.com", "kkiran#ariqt.com"
Subject = "List of Expiring/Expired App registration keys/secrets Report - Ariqt & Ariqt-Dev/Test"
Body = "Below is list of Expiring/Expired App registration keys/secrets in 7 days $p"
Token = "SG.m1z9e*******************324w9hlTMb779xEvqIUjv0"
#FromName = "Barbara"
#ToName = "Barbara"
}
Send-PSSendGridMail #Parameters
Please help me what I am missing.
You have incorrect permissions. The ones you have are for PIM (Privileged Identity Management). To read data about App Regs you need one of these e.g.
I have written a Powershell script that receives N number of characters that have to be replaced by another given character from a user. For example, the user wants to replace (, ), and -. The user enters the characters that have to be replaced through this loop:
#Declare array for special characters to replace
$replaceChars = #( )
#Instruct the user about entering characters to replace
Write-Host
Write-Host "Please enter what you would like to replace in your names. This can contain one or more characters. Example: (2) or ^ or _" -ForegroundColor Cyan
Write-Host "Enter -1 to end your input and continue." -ForegroundColor Cyan
#Get values until sentinal is passed
$input = "" #input from user declared to blank
#loop for special characters
while($input -ne -1) {
#get the input from the user
$input = Read-Host -Prompt "Enter what you would like to replace (-1 to finish)"
#if the input isn't sentinal, put it in the replaceChars array
if($replaceChars.Length -gt 0 -and $input -eq -1) {
Write-Host
Write-Host "Your entries have been stored." -ForegroundColor Green
} #end-if
elseif($replaceChars.Length -eq 0 -and $input -eq -1) {
Write-Host
Write-Host "ERROR: You must enter at least one character to continue." -ForegroundColor Red
$input = $NULL
}
elseif($input -eq '') {
Write-Host
Write-Host "Invalid entry. Entry cannot be blank, please enter a value." -ForegroundColor Red
}#end-elseif
elseif($input.IndexOfAny([System.IO.Path]::GetInvalidFileNameChars()) -ge 0) {
Write-Host
Write-Host "Invalid entry. File names cannot contain / \ : * ? `" < > |" -ForegroundColor Red
}#end-elseif
else {
$replaceChars += $input
} #end-else
}#end-while
The user then enters the replacement character through this code:
#Get the char to replace to
Write-Host
Write-Host "Please enter what you want to replace the selected characters with. Leave blank and hit enter to delete the old characters." -ForegroundColor Cyan
$newChar = Read-Host -Prompt "Please enter new character(s)"
while($newChar.IndexOfAny([System.IO.Path]::GetInvalidFileNameChars()) -ge 0) {
Write-Host
Write-Host "The entry is invalid for file names. File names cannot contain / \ : * ? `" < > |" -ForegroundColor Red
$newChar = Read-Host -Prompt "Please enter new character(s)"
}
Write-Host
Write-Host "New character has been stored" -ForegroundColor Green
I am then processing the entries with this:
#Iterate through each character
foreach($char in $replaceChars) {
if($type -eq 1) {
gci -File -Path "$path" | Where-Object { $_.Name -match $char } | ForEach-Object { $_ | rename-item -NewName $_.Name.Replace($char, $newChar) }
} elseif ($type -eq 2) { #end-if
gci -Directory -Path "$path" | Where-Object { $_.Name -match $char } | ForEach-Object { $_ | rename-item -NewName $_.Name.Replace($char, $newChar) }
} else { #end-elseif
gci -Path "$path" | Where-Object { $_.Name -match $char } | ForEach-Object { $_ | rename-item -NewName $_.Name.Replace($char, $newChar) }
}#end-else
} #end-foreach
THE ERROR: If a user enters something like ( or ), then the last part of the script fails out with the following error code:
parsing "(" - Not enough )'s.
At <path to script>:109 char:50
+ ... gci -File -Path "$path" | Where-Object { $_.Name -match $char } | For ...
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException
MY SOLUTIONS: I have attempted to use [regex]::Escape() to escape the $char and $newChar variables to fix the parentheses error. I have also attempted to resolve this by enclosing the variables with single and double quotes; however, this prevents the actual character replacement from occuring. I understand the parentheses/special characters is what is causing the issue, and I need to escape those somehow; however, the [regex]::Escape() solution breaks the character matching and ends up not replacing any of the user's entered characters.
MY QUESTION: How can I successfully escape the $char and $newChar variables in the GCI cmdlet and still replace special characters like ( or )
gci -Path "$path" | Where-Object { $_.Name -match $char } | ForEach-Object { $_ | rename-item -NewName $_.Name.Replace($char, $newChar) }
How did you try to implement [regex]::Escape() exactly? If you tried to save $char before hand as escaped I see your problem. Since your .replace() method does not use regex. This should leave you with a few options
Just update the where clause to use the escape character just for the comparison. That was $char is not permanently changed. This would be a good idea regardless if you plan on using -match and not supporting regex characters.
gci -Path "$path" | Where-Object { $_.Name -match [regex]::Escape($char) } | ...
Save $char as escaped and use the -replace operator which also supports regex.
gci -Path "$path" | Where-Object { $_.Name -match $char } |
ForEach-Object { $_ | rename-item -NewName ($_.Name -replace $char, $newChar))
Not use regex operators at all
gci -Path "$path" | Where-Object { $_.Name.Contains($char) } | ...
Couple points of review
Don't use the name $input. It is a reserved variable name. See about_automatic_variables
Since you are working with the fullname of the file I would caution that you could also accidentally edit the extension of the file. The basename property might be useful to you in that case.
As TheMadTechnician points out you can avoid the regex/non-regex issue by filtering at the Get-ChildItem level instead.
gci -Path "$path" -Filter "*$char*" | Rename-Item -NewName {$_.Name.Replace($char, $newChar)}
THE SOLUTION: I have implemented the suggestions by #Matt and solved the errors with the following:
#Iterate through each character
foreach($char in $replaceChars) {
if($type -eq 1) {
gci -File -Path "$path" | Where-Object { $_.Basename.Contains($char) } | ForEach-Object { $_ | rename-item -NewName ($_.Basename.Replace($char, $newChar) + $_.extension) }
} elseif ($type -eq 2) { #end-if
gci -Directory -Path "$path" | Where-Object { $_.Basename.Contains($char) } | ForEach-Object { $_ | rename-item -NewName ($_.Basename.Replace($char, $newChar) + $_.extension) }
} else { #end-elseif
gci -Path "$path" | Where-Object { $_.Basename.Contains($char) } | ForEach-Object { $_ | rename-item -NewName ($_.Basename.Replace($char, $newChar) + $_.extension) }
}#end-else
} #end-foreach
i'm using windows server 2003, now i have a script to restart one specific service, can someone guide me how to run this script in parallel? i already use start-job, but seems it only run in backround but still sequential, below is my script:
file name: restart-service.ps1
$start = Get-Date
$Serverlist = Get-Content -path C:\Computers.txt
ForEach ($Server in $Serverlist){
start-job -scriptblock {param($Server) Restart-Service -InputObject $(Get-Service -ComputerName $Server -Name "aspnet_state")} -ArgumentList $Server
}
Get-Job | Wait-Job
Get-Job | Receive-Job
$end = Get-Date
$timespan = $end - $start
$seconds = $timespan.TotalSeconds
Write-Host "This took me $seconds seconds."
or this
$start = Get-Date
$Server = Get-Content -path C:\Computers.txt
$scriptblock = {
Param($Server)
Restart-Service -InputObject $(Get-Service -ComputerName $Server -Name "aspnet_state")
}
$Server | % {Start-Job -Scriptblock $scriptblock -ArgumentList $_ | Out-Null}
Get-Job | Wait-Job | Receive-Job
$end = Get-Date
$timespan = $end - $start
$seconds = $timespan.TotalSeconds
Write-Host "This took me $seconds seconds."
but i only can see the result, but can not see any result related information of my server's IP, can someone help me how to improve it...
This is the Direction, tweak it for your specific needs... add timer etc...
$Serverlist = Get-Content -path C:\Computers.txt
Foreach ($Server in $Serverlist)
{
Start-Job -Name "$Server-Job" -ScriptBlock {
Get-Service -ComputerName $args[0] -Name "aspnet_state" | Restart-Service
} -ArgumentList $Server
}
It will Create a job with the ServerName for each server, to Get the Job status/info, use:
Get-Job | Receive-Job
I'm trying to delete the processes in task manager after I finish this powershell script, but it still appears after the script is run. Any ideas?
#Declarations
$dir = "mydirectory*"
$NewName = "mydirectory"+(Get-Date).ToString("yyyy.MM.dd")+".xlsx"
$latest = Get-ChildItem -Path $dir | Sort-Object LastAccessTime -Descending | Select-Object -First 1
$latest.name
$excelObj = New-Object -ComObject Excel.Application
$excelObj.Visible = $False
$excelObj.DisplayAlerts = $False
$FileExists = Test-Path $NewName
if($FileExists -eq $True)
{#If todays file exists already
Write-Host –NoNewLine "File Already Exists, Refreshing..."
$workBook = $excelObj.Workbooks.Open($NewName)
$Worksheet = $Workbook.WorkSheets.item("DataV2")
$worksheet.activate()
$workBook.RefreshAll()
Start-Sleep -s 10
$workBook.Save()
$excelObj.Quit()
#delete old files
(Get-ChildItem $dir -recurse | select -ExpandProperty fullname) -ne $NewName | remove-item
}
Else
{#If todays file does not exist
$workBook = $excelObj.Workbooks.Open($latest)
$Worksheet = $Workbook.WorkSheets.item("DataV2")
$worksheet.activate()
$workBook.RefreshAll()
Start-Sleep -s 10
$workBook.SaveAs($NewName)
$excelObj.Quit()
Start-Sleep -Seconds 10
#delete old files
(Get-ChildItem $dir -recurse | select -ExpandProperty fullname) -ne $NewName | remove-item}
#Remove Tasks and Prcesses
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelObj)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($workBook)
Remove-Variable excelObj
Remove-Variable workBook
You can see at the end I run the ReleaseComObject stuff to clear the process.
it's really annoying i know, one way is:
$workbook.Close()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook)
$excelObj.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelObj)
Remove-Variable excelObj
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
If it still there, this is the killer way :)
$excelObj.Visible = $true
$ProcID = Get-Process | Where-Object {$_.MainWindowHandle -eq $excelObj.HWND} | Select -ExpandProperty ID
$excelObj.Visible = $False
Get-Process -Id $ProcID | Stop-Process -Force
this one goes before the $excelObj.Quit()
I am new to Power shell and I cant seem to wrap my head around this one.
The Code works when you take the input out and place actual values in for each $number and $Name as seen in the bottom example. I found that unlike specifying the values, line 7 char 13 cant be -$Name but rather has to be $Name. After doing this it tells me ln 15 char 13 "a positional character cannot be found that accepts argument "- "." where the "-" = $Name.
What do I need to change to get this to function? I have tired using [parameter(Mandatory=$true,name='What would you like your folder to be named: ')] but I cant seem to get that to work either.
Any help would be greatly appreciated.
$number = read-host "How Many Folders would you like to create: "
$Name = read-host "What would you like your folder to be named: "
$intFolders = $number
$intPad
$i = 1
New-Variable -$Name strPrefix -Value "$Name" -Option constant
do {
if ($i -lt $number)
{$intPad=0
new-item -path c:\mytest -$Name $strPrefix$intPad$i -type directory}
else
{new-item -path c:\mytest -$Name $strPrefix$i -type directory}
$i++}
until ($i -eq $intFolders+1)
This is the code below that I was able to get to work, but I want to make sure when I am gone people here can still use it for their needs as they do not understand coding.
$intFolders = 500
$intPad
$i = 1
New-Variable -Name strPrefix -Value "0001_" -Option constant
do {
if ($i -lt 500)
{$intPad=0
new-item -path c:\mytest -name $strPrefix$intPad$i -type directory}
else
{new-item -path c:\mytest -name $strPrefix$i -type directory}
$i++}
until ($i -eq $intFolders+1)
Thanks to Bruce here is the working Final code that does excatly what it should have :)
[int]$start = read-host "What number would you like your folder to start at"
[int]$number = read-host "How Many Folders would you like to create"
$Name = read-host "What would you like your folder to be named"
$intFolders = $number
$intPad
$i = $start
New-Variable -Name strPrefix -Value "$Name" -Option constant
do {
if ($i -lt 10)
{$intPad=""
new-item -path c:\mytest -Name $strPrefix$intPad$i -type directory}
else
{new-item -path c:\mytest -Name $strPrefix$i -type directory}
$i++}
until ($i -eq $intFolders+1)
Change New-Variable -$Name strPrefix -Value "$Name" -Option constant to
New-Variable -Name strPrefix -Value "$Name" -Option constant
Same for the -$name in the new-item lines. See Get-Help New-Variable and Get-Help New-Item.