Trouble with Powershell writing to registry - powershell

I'm writing a script that will modify some registry settings on Windows machines.
I'm using an If to determine if the key/property exist before writing them. It should fail and write an error if it does. This chunk is working:
$currentPath = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\Ext'
$pathTest = Test-Path $currentPath
Write-Host -ForegroundColor Yellow 'Testing for: ' $currentPath
If($pathTest -ne 'True')
{
New-Item -Path $currentPath -Force | Out-Null
Write-Host -ForegroundColor Green 'Created Path: '$currentPath
}
Else{
Write-Host -ForegroundColor Red $currentPath ' already exists.'
}
Write-Host -ForegroundColor Yellow 'Disabling IE Add-On Performance Notifications (DisableAddonLoadTimePerformanceNotifications):'
If((Get-ItemProperty $currentPath -Name 'DisableAddonLoadTimePerformanceNotifications' -ea 0).'DisableAddonLoadTimePerformanceNotifications')
{
Write-Host -ForegroundColor Red 'DisableAddonLoadTimePerformanceNotifications already exists'
}
Else {
New-ItemProperty -Path $currentPath -Name DisableAddonLoadTimePerformanceNotifications -PropertyType DWord -Value '1' | Out-Null
Write-Host -ForegroundColor Green 'DisableAddonLoadTimePerformanceNotifications created and set to 1'
}
It gives me this output if the key/property exists:
Testing for: HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\Ext
HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\Ext already exists.
Disabling IE Add-On Performance Notifications (DisableAddonLoadTimePerformanceNotifications):
DisableAddonLoadTimePerformanceNotifications already exists
However, this chunk does not work:
$currentPath = 'HKLM:\Software\Policies\Microsoft\Internet Explorer\Main'
$pathTest = Test-Path $currentPath
Write-Host -ForegroundColor Yellow 'Testing for: ' $currentPath
If($pathTest -ne 'True')
{
New-Item -Path $currentPath -Force | Out-Null
Write-Host -ForegroundColor Green 'Created Path: '$currentPath
}
Else{
Write-Host -ForegroundColor Red $currentPath ' already exists.'
}
If((Get-ItemProperty $currentPath -Name 'EnableAutoUpgrade' -ea 0).'EnableAutoUpgrade')
{
Write-Host -ForegroundColor Red 'EnableAutoUpgrade already exists'
}
Else{
New-ItemProperty -Path $currentPath -Name 'EnableAutoUpgrade' -PropertyType DWord -Value '0' | Out-Null
Write-Host -ForegroundColor Green 'EnableAutoUpgrade created and set to 0'
}
Output if the key/property exists:
Testing for: HKLM:\Software\Policies\Microsoft\Internet Explorer\Main
HKLM:\Software\Policies\Microsoft\Internet Explorer\Main already exists.
New-ItemProperty : The property already exists.
At C:\ps\setup\2.ps1:42 char:10
+ New-ItemProperty -Path $currentPath -Name 'EnableAutoUpgrade' -Property ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceExists: (HKEY_LOCAL_MACH...t Explorer\Main:String) [New-ItemProperty], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.NewItemPropertyCommand
EnableAutoUpgrade created and set to 0
Output of the key/property does not exist:
Testing for: HKLM:\Software\Policies\Microsoft\Internet Explorer\Main
Created Path: HKLM:\Software\Policies\Microsoft\Internet Explorer\Main
Disabling IE Auto Upgrade (EnableAutoUpgrade):
EnableAutoUpgrade created and set to 0
So, it'll create the property no problem, but can't see if it already exists.It looks to me like the If is failing on this one, but I can't figure out why. It's the same as one above it. In the full script I run a total of 14 registry entries. The ones above EnableAutoUpgrade all work. The ones below EnableAutoUpgrade do not and fail with the same error.
This is happening on multiple machines all running Win8.1 and PowerShell v4.
This is a real head scratcher. Any help would be appreciated.

Try this:
$currentPath = "HKLM:\Software\Policies\Microsoft\Internet Explorer\Main"
Write-Host -ForegroundColor Yellow "Testing for: " $currentPath
If(Test-Path "HKLM:\Software\Policies\Microsoft\Internet Explorer\Main")
{
Write-Host $currentPath " already exists." -ForegroundColor 'Red'
}
Else{
New-Item -Path $currentPath | Out-Null
Write-Host "Created Path: "$currentPath -ForegroundColor 'Green'
}

Related

Powershell not able to clear IE Browsing Cookies, Caches, etc

I am trying to clear browser data from default location C:\Users\\AppData\Local\Microsoft\Windows\INetCache. I am trying to clear Cookies, Cache or any type files located in that path but I am not sure what am I missing here
screenshot
Write-Host -ForegroundColor yellow "#######################################################"
""
Write-Host -ForegroundColor Green "Powershell commands to delete cache & cookies in Firefox, Chrome & IE browsers"
Write-Host -ForegroundColor Green "By Cesar Silva"
Write-Host -ForegroundColor Green "VERSION: 3"
""
Write-Host -ForegroundColor yellow "#######################################################"
""
Write-Host -ForegroundColor Green "CHANGE_LOG:
v2.4: - Resolved *.default issue, issue was with the file path name not with *.default, but issue resolved
v2.3: - Added Cache2 to Mozilla directories but found that *.default is not working
v2.2: - Added Cyan colour to verbose output
v2.1: - Added the location 'C:\Windows\Temp\*' and 'C:\`$recycle.bin\'
v2: - Changed the retrieval of user list to dir the c:\users folder and export to csv
v1: - Compiled script"
""
Write-Host -ForegroundColor yellow "#######################################################"
""
#########################
"-------------------"
Write-Host -ForegroundColor Green "SECTION 1: Getting the list of users"
"-------------------"
# Write Information to the screen
Write-Host -ForegroundColor yellow "Exporting the list of users to c:\users\%username%\users.csv"
# List the users in c:\users and export to the local profile for calling later
dir C:\Users | select Name | Export-Csv -Path C:\users\$env:USERNAME\users.csv -NoTypeInformation
$list=Test-Path C:\users\$env:USERNAME\users.csv
""
#########################
"-------------------"
Write-Host -ForegroundColor Green "SECTION 2: Beginning Script..."
"-------------------"
if ($list) {
"-------------------"
# Clear Internet Explorer
Write-Host -ForegroundColor Green "SECTION 5: Clearing Internet Explorer Caches"
"-------------------"
Write-Host -ForegroundColor yellow "Clearing Google caches"
Write-Host -ForegroundColor cyan
Import-CSV -Path C:\users\$env:USERNAME\users.csv | foreach {
Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Microsoft\Windows\INetCache\*.*" -Recurse -Force -EA SilentlyContinue -Verbose
Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Microsoft\Windows\WER\*" -Recurse -Force -EA SilentlyContinue -Verbose
Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Temp\*" -Recurse -Force -EA SilentlyContinue -Verbose
Remove-Item -path "C:\Windows\Temp\*" -Recurse -Force -EA SilentlyContinue -Verbose
Remove-Item -path "C:\`$recycle.bin\" -Recurse -Force -EA SilentlyContinue -Verbose
}
Write-Host -ForegroundColor yellow "Done..."
""
Write-Host -ForegroundColor Green "All Tasks Done!"
} else {
Write-Host -ForegroundColor Yellow "Session Cancelled"
Exit
}
Well if any errors are occurring, you are suppressing them with the -EA SilentlyContinue flag. I would remove that from your Remove-Item calls and see if any sneaky errors are hiding there.
I'm not sure if you intended this, but in your first Remove-Item call under INetCache:
Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Microsoft\Windows\INetCache\*.*"
You are removing only files with a . in the filename, basically only files with extensions. If you want to remove everything from that directory regardless of whether it has a file extension, just use * instead of *.* as you do for your other paths.

How to set sound Scheme to "No Sound" by powershell?

We are using approx 300+ Windows10 pc in our Network and we have to set sound scheme from "Windows Default" to "No sound" can it possible with Powershell ?
Here i Found
# Set Sound Schemes to no sound
Write-Host "`nSetting Sound Schemes to 'No Sound' .." -foregroundcolor Gray
$Path = "HKCU:\AppEvents\Schemes"
$Keyname = "(Default)"
$SetValue = ".None"
$TestPath = Test-Path $Path
if (-Not($TestPath -eq $True)) {
Write-Host " Creating Folder.. " -foregroundcolor Gray
New-item $path -force
}
if (Get-ItemProperty -path $Path -name $KeyName -EA SilentlyContinue) {
$Keyvalue = (Get-ItemProperty -path $Path).$keyname
if ($KeyValue -eq $setValue) {
Write-Host " The Registry Key Already Exists. " -foregroundcolor green
}
else {
Write-Host " Changing Key Value.. " -foregroundcolor Gray
New-itemProperty -path $Path -Name $keyname -value $SetValue -force # Set 'No Sound' Schemes
Get-ChildItem -Path "HKCU:\AppEvents\Schemes\Apps" | # Apply 'No Sound' Schemes
Get-ChildItem |
Get-ChildItem |
Where-Object { $_.PSChildName -eq ".Current" } |
Set-ItemProperty -Name "(Default)" -Value ""
Write-Host " The Registry Key Value Changed Sucessfully. " -foregroundcolor green
}
}
else {
Write-Host " Creating Registry Key.. " -foregroundcolor Gray
New-itemProperty -path $Path -Name $keyname -value $SetValue -force
Get-ChildItem -Path "HKCU:\AppEvents\Schemes\Apps" |
Get-ChildItem |
Get-ChildItem |
Where-Object { $_.PSChildName -eq ".Current" } |
Set-ItemProperty -Name "(Default)" -Value ""
Write-Host " The Registry Key Created Sucessfully. " -foregroundcolor green
}

Copy files including directory structure only if their modification date has changed since

I am trying to write a script which takes a source-path as input and copies all files that have been changed since a given date, including their directory structure:
param([string]$source,[string]$datum)
(Get-ChildItem $source -Recurse | Where-Object { $_.LastWriteTime -ge $datum }) | Copy-Item -Destination C:\tmp -Recurse
It works. The problem is, that it copies the files, including their directory structure, BUT it also copies all files from the source directories to the base path of the destination folder.
Where is the error?
First and foremost you should be using robocopy for something like this. It has switches that likely handle your query:
/e Copies subdirectories. Note that this option includes empty directories. For additional information, see Remarks.
/maxage: Specifies the maximum file age (to exclude files older than N days or date).
/l Specifies that files are to be listed only (and not copied, deleted, or time stamped).
So knowing that I would start experimenting with robocopy $source $destination /e /maxage:30 /l which should show all files in the directory tree that were modified in the last 30 days. /maxage might not be the switch you are looking for but its a fair guess.
The issue with your current logic is likely that Get-ChildItem $source -Recurse will be returning folders as well as files. So you could be passing a folder to Copy-Item which is where all the extra files are coming from. You should be able to mitigate that with the -File switch.
Get-ChildItem $source -Recurse -File
Here is an overly complicated solution. It has a lot of error handling with 5 retry attempts. You should be able to apply it toward your needs.
I would look at Line 21 to add your Where-Object and test it.
Example Use: Copy-Files -Source "C:\Path\" -Destination "C:\Path2\"
Function Retry-Command {
$Script:Counter = $Script:Counter + 1
Write-Host "Attempt #" $Script:Counter "out of 5"
if ($Script:Counter -ge 5) {
PAUSE
}
else {
Start-Sleep -Seconds 5 -Verbose
}
}
Function Copy-Files ([string]$Source, [string]$Destination ) {
[System.Collections.ArrayList]$Folder_Content = #()
[string]$Folder_Name = Split-Path $Source -Leaf
[string]$Folder_Path = ($Source -replace [regex]::Escape($Source), ($Destination + $Folder_Name + "\"))
[int]$Script:Counter = 0
while (($Folder_Content.Count -eq "0") -and ($Counter -ne 5)) {
try {
Write-Host ""
Write-Host "------------------------------" -ForegroundColor Cyan
Write-Host "Getting Content of" $Folder_Name -ForegroundColor Yellow
[System.Collections.ArrayList]$Folder_Content = #(Get-ChildItem -Path $Source -Recurse -Force -ErrorVariable Child_Error)
if ((-Not $Child_Error) -and ($Folder_Content.Count -ne 0) ) {
Write-Host "Finished Getting Content of" $Folder_Name -ForegroundColor Green
[int]$Script:Counter = 0
}
else {
Write-Host "Failed to get Content of" $Folder_Name -ForegroundColor Red
Retry-Command
}
}
catch {
Write-Host "Unexpected Error getting Content of" $Folder_Name -ForegroundColor Red
Retry-Command
}
}
if (-Not $Folder_Content.Count -eq 0) {
while ((Test-Path -Path $Folder_Path) -eq $false) {
try {
Write-Host ""
Write-Host "Creating" $Folder_Name "Folder" -ForegroundColor Yellow
Copy-Item -Path $Source -Destination $Folder_Path -Force -ErrorVariable Folder_Error
if (-Not $Folder_Error) {
Write-Host "Finished Creating" $Folder_Name "Folder" -ForegroundColor Green
[int]$Script:Counter = 0
}
else {
Write-Host "Failed to create" $Folder_Name "Folder" -ForegroundColor Red
Retry-Command
}
}
catch {
Write-Host "Unexpected Error Creating" $Folder_Name "Folder" -ForegroundColor Red
Retry-Command
}
}
foreach ($Index in $Folder_Content) {
[string]$Software_File_Name = Split-Path $Index.FullName -Leaf
[string]$Software_File_Path = ($Index.FullName -replace [regex]::Escape($Source), ($Destination + (Split-Path $Source -Leaf) + "\"))
while ((Test-Path -Path $Software_File_Path) -eq $false) {
try {
Write-Host ""
Write-Host "Copying" $Index.FullName -ForegroundColor Yellow
Copy-Item -Path $Index.FullName -Destination $Software_File_Path -Force -ErrorVariable File_Error
if (-Not $File_Error) {
Write-Host "Finished Copying" $Index.FullName -ForegroundColor Green
[int]$Script:Counter = 0
}
else {
Write-Host "Failed to Copy" $Index.FullName -ForegroundColor Red
Retry-Command
}
}
catch {
Write-Host "Unexpected Error Copying" $Index.FullName -ForegroundColor Red
Retry-Command
}
}
}
}
}

Powershell script executed on each file in a folder?

I currently have a powershell script, which print out some information regarding the files which passed in as argument..
The command for executing the script, it done as such:
.\myscript.ps1 -accessitem C:\folder
I want to apply the script on all files and folder on the drive C:, is it possible i for loop to list all files, and pass the path as argument for the script?
The script:
[CmdletBinding()]
Param (
[Parameter(Mandatory=$True,Position=0)]
[String]$AccessItem
)
$ErrorActionPreference = "SilentlyContinue"
If ($Error) {
$Error.Clear()
}
$RepPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
$RepPath = $RepPath.Trim()
$str = $AccessItem -replace ':',''
$str = $AccessItem -replace '/','.'
$FinalReport = "$RepPath\"+$str+".csv"
$ReportFile1 = "$RepPath\NTFSPermission_Report.txt"
If (!(Test-Path $AccessItem)) {
Write-Host
Write-Host "`t Item $AccessItem Not Found." -ForegroundColor "Yellow"
Write-Host
}
Else {
If (Test-Path $FinalReport) {
Remove-Item $FinalReport
}
If (Test-Path $ReportFile1) {
Remove-Item $ReportFile1
}
Write-Host
Write-Host "`t Working. Please wait ... " -ForegroundColor "Yellow"
Write-Host
## -- Create The Report File
$ObjFSO = New-Object -ComObject Scripting.FileSystemObject
$ObjFile = $ObjFSO.CreateTextFile($ReportFile1, $True)
$ObjFile.Write("NTFS Permission Set On -- $AccessItem `r`n")
$ObjFile.Close()
$ObjFile = $ObjFSO.CreateTextFile($FinalReport, $True)
$ObjFile.Close()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ObjFSO) | Out-Null
Remove-Variable ObjFile
Remove-Variable ObjFSO
If((Get-Item $AccessItem).PSIsContainer -EQ $True) {
$Result = "ItemType -- Folder"
}
Else {
$Result = "ItemType -- File"
}
$DT = Get-Date -Format F
Add-Content $ReportFile1 -Value ("Report Created As On $DT")
Add-Content $ReportFile1 "=================================================================="
$Owner = (Get-Item -LiteralPath $AccessItem).GetAccessControl() | Select Owner
$Owner = $($Owner.Owner)
$Result = "$Result `t Owner -- $Owner"
Add-Content $ReportFile1 "$Result `n"
(Get-Item -LiteralPath $AccessItem).GetAccessControl() | Select * -Expand Access | Select IdentityReference, FileSystemRights, AccessControlType, IsInherited, InheritanceFlags, PropagationFlags | Export-CSV -Path "$RepPath\NTFSPermission_Report2.csv" -NoTypeInformation
Add-Content $FinalReport -Value (Get-Content $ReportFile1)
Add-Content $FinalReport -Value (Get-Content "$RepPath\NTFSPermission_Report2.csv")
Remove-Item $ReportFile1
Remove-Item "$RepPath\NTFSPermission_Report2.csv"
Invoke-Item $FinalReport
}
If ($Error) {
$Error.Clear()
}
I would prefer a outside command doing this, as workings of the script should not be altered, it it used for single file testing..
There are two ways to do this:
Add -Recurse Flag to the script
Run the script on each directory
I'm going with option two since the script looks complicated enough that I don't want to touch it.
$path_to_script = "C:\path\to\myscript.ps1"
$start_directory = "C:\folder"
# Call Script on Parent Directory
& "$path_to_script" -AccessItem "$start_directory"
# Call Script on any Child Directories within the "$start_directory"
foreach($child in (ls "$start_directory" -Recurse -Directory))
{
$path = $child.FullName
& "$path_to_script" -AccessItem "$path"
}
Basically, I'm calling the script on the parent directory and any sub-directories within the parent directory.

how to merge multiple scripts and use functions to show output

A couple of you (Shay especially!) helped me yesterday and I have managed to come up with multiple scripts and am now merging them into one.
The problem is that I have put them all into "Functions" and one function relies on the successful check on a hotfix - if the hotfix is not installed then the script has to stop right there and then - that is the first check the script does. How do I get the next function to call the successful output of the hotfix function?
Also I have no idea how to call the functions - ie at the bottom I put the name of the functions one line after each other but ended up looping over and over!
hope someone can assist.
Write-Host "=================================="
Write-Host "Pre-Staging Script for DFSR Server"
Write-Host "=================================="
Function Service
{
Write-Host "=================================="
Write-Host "Checking Service Installation"
Write-Host "=================================="
write-host "This will check if Hotfix KB979808 is installed." -ForegroundColor Black -BackgroundColor Cyan
write-host "This is required for Windows Server 2008 R2 Robocopying" -ForegroundColor Black -BackgroundColor Cyan
Write-Host ""
$hotfix1 = Get-HotFix -id KB979808 -ErrorAction SilentlyContinue
If($hotfix1)
{
Write-Host "Hotfix is installed you may proceed" -foregroundcolor "green"
Write-Host ""
}
else
{
Write-Host "Hotfix is NOT installed - Please ensure you install this hotfix BEFORE" -ForegroundColor "red"
Write-host "Copying any data" -foregroundcolor "red"
Write-Host ""
}
}
Function Robocopy ($hotfix1)
{
Write-Host "============="
Write-Host "Robocopy Data"
Write-Host "============="
$Source = Read-Host "Please enter path of SOURCE"
$Destination = Read-Host "Please enter path of TARGET"
$Output = Read-Host "Please enter where to place output file eg c:\temp\COPY.log"
robocopy $Source $Target /b /e /copyall /r:1 /xd dfsrprivate /log:$Output /tee
}
Function Comparision
{
Write-Host "==============================================="
Write-Host "Checking Directory Count and Folder comparision" -ErrorAction SilentlyContinue -BackgroundColor Cyan -ForegroundColor Black
Write-Host "==============================================="
Write-Host ""
$Source = Read-Host "Please enter Source directory to check"
$Target = Read-Host "Please enter Target directory to check"
Write-Host ""
If($source -and (Test-Path -Path $source -PathType Container))
{
"There are $(#(Get-ChildItem $Source).Count) items in the '$Source' directory"
}
Else
{
Write-Host "Please enter a directory"
}
If($source -and (Test-Path -Path $Target -PathType Container))
{
"There are $(#(Get-ChildItem $Target).Count) items in the '$Target' directory"
}
Else
{
Write-Host "Please enter a directory"
}
Write-Host ""
$child1 = Get-ChildItem -Path $Source -Recurse -Force
$child2 = Get-ChildItem -Path $Target -Recurse -Force
Compare-Object $child1 -DifferenceObject $child2 -Property Name
Write-Host ""
Write-Host "NOTE:" -BackgroundColor Cyan -ForegroundColor Black
Write-Host "Any symbols with '=>' mean that the file Does NOT exist in SOURCE but is in the Target" -BackgroundColor Cyan -ForegroundColor Black
Write-Host "Any symbols with '<=' mean that the file Does NOT exist in TARGET but is in the Source" -BackgroundColor Cyan -ForegroundColor Black
}
To use the hotfix found in the function Service, you should return the hotfix to a variable. The function would look like this:
Function Service
{
Write-Host "=================================="
Write-Host "Checking Service Installation"
Write-Host "=================================="
write-host "This will check if Hotfix KB979808 is installed." -ForegroundColor Black -BackgroundColor Cyan
write-host "This is required for Windows Server 2008 R2 Robocopying" -ForegroundColor Black -BackgroundColor Cyan
Write-Host ""
# This will return any output.
Get-HotFix -id KB979808 -ErrorAction SilentlyContinue
}
Then the function calls would be:
$hotfix = Service
if($hotfix) {
Robocopy
}
else {
# This will exit the script.
return
}
Function Robocopy doesn't need $hotfix1 as a parameter since it's not used anywhere in the function.
The Robocopy function is probably looping because the call to robocopy.exe is the same as your Robocopy function; try adding ".exe" to the robocopy.exe call. It is important to name functions to accurately reflect their purpose. Service could be Get-HotFixKB979808 and Robocopy could be Start-MyRobocopy
Having said all that, since your functions do very specific things, they really don't need to be their own functions. You could change them to be more reusable by having them accept parameters.