Change a value of an .ini files in multiple directories - powershell

I need to change a value in the DefaultPrint.ini file in multiple users "home" directory.
I've managed to make a powershell script to change the value on a single user, but I am struggeling making the script accept multiple users.
$User = "Max"
$IniPath = "\\Network1\Home\$User\"
foreach ($User in $User)
{
$IniFile = "$IniPath\DefaultPrint.ini"
$IniText = Get-Content -Path $IniFile
$NewText = $IniText.Replace("Old_Priter","New_Printer")
Set-Content -Path $IniFile -Value $NewText -Force
}
The directories I need to enter to find the files is based on the usernames, so I need to change the file in:
\Network1\Home\Max
\Network1\Home\John
\Network1\Home\Sophia
etc
The script above is working for a single user, and I am trying to adapt it to work with multiple users though a .csv file
I tried the following
$User = "Max","John","Sophia"
But it does not seperate the user directories but gathers them togther? (\Network1\Home\Max John Sophia)
I also tried to import via csv, as I need to do this on 200+ users
$User = (Import-Csv -Path .\Users.csv).User
But it ends up doing the same, what am I doing wrong?

You need to move this statement:
$IniPath = "\\Network1\Home\$User\"
inside the loop, so that the path is updated with the correct $user every time, and then rename the $User variable used outside the loop ($Users seems an appropriate name here):
$Users = -split "Max John Sophia"
foreach ($User in $Users)
{
$IniPath = "\\Network1\Home\$User\"
$IniFile = "$IniPath\DefaultPrint.ini"
$IniText = Get-Content -Path $IniFile
$NewText = $IniText.Replace("Old_Priter","New_Printer")
Set-Content -Path $IniFile -Value $NewText -Force
}

Related

PowerShell logging function is not writing data

I am trying to create a reusable log function for a project I am working on in PowerShell. I am a novice with PowerShell so I am having problems figuring out why my function is not producing expected results. I am attempting to create a function that send NTFS/ACL details to a log file. This function will be incorporated in to a larger script that will change some NTFS/ACL/ACE folder rights. I have excluded some of the other code for simplification (changing rights).
Below is my current stripped down code. When it runs, it creates the log file but the file is empty. If I move the line of code that creates the log inside the log function, it creates the log file with data but it is not formatted correctly - it writes the heading (object attribute names) on one line, then the data, then then a new line with the heading, then the data. I want it to write the heading, then a line of data, line of data, .... Before I created a function for this, it worked as expected. I am a novice at PowerShell so I may not understand how to pass info in and out of the function. My Code:
#variables
$rootDir = "\\server1\share1"
$logDir = "c:\temp"
$date = (Get-Date -Format "MMddyyyy-HHmm")
$logData =#()
#My Logging Function
Function CreateLog {
#create and object to store attributes
$logObj = New-Object -TypeName psobject -Property #{
FolderPath = $Folder.Fullname
IdentityReference = $ACL.IdentityReference.ToString()
folder = $Folder[0]
FileSystemRights = $ACL.FileSystemRights.ToString()
InheritanceFlags = $ACL.InheritanceFlags.ToString()
}
$Folders=(Get-ChildItem -Path $rootDir -Directory -Recurse)
foreach ($Folder in $Folders){
$ACLs = get-acl $Folder.fullname | ForEach-Object {$_.Access}
Foreach ($ACL in $ACLs){
CreateLog
if($ACL.FileSystemRights -eq "FullControl"){
Write-Host "DO SOMETHING"
}
}
$logData | select folder,IdentityReference,FileSystemRights,InheritanceFlags,FolderPath | Format-Table -Wrap | Out-File $logDir\testlog-$date.log -Append
I assume you're looking for something like this:
#variables
$rootDir = "\\server1\share1"
$logDir = "c:\temp"
$date = Get-Date -Format "MMddyyyy-HHmm"
#My Logging Function
Function CreateLog {
param(
[Parameter(Mandatory)]
[System.Security.AccessControl.FileSystemAccessRule] $AccessRule,
[Parameter(Mandatory)]
[string] $Folder
)
[pscustomobject]#{
FolderPath = $Folder
IdentityReference = $AccessRule.IdentityReference
FileSystemRights = $AccessRule.FileSystemRights
InheritanceFlags = $AccessRule.InheritanceFlags
}
}
Get-ChildItem -Path $rootDir -Directory -Recurse | ForEach-Object {
foreach($rule in ($_ | Get-Acl).Access) {
CreateLog -AccessRule $rule -Folder $_.FullName
if($rule.FileSystemRights.HasFlag([Security.AccessControl.FileSystemRights]::FullControl)) {
# Do something here
}
}
} | Export-Csv $logDir\testlog-$date.log -NoTypeInformation
Your current code has a few syntax errors (missing }), your function seem to be assigning the objects to $logObj but then $logObj is never outputted from it, hence producing no output.
Your $logData array is defined but never used, leaving aside is not needed at all in this case. Your function should, ideally, take the arguments for the Access Rules and Path, see Functions with Parameters to learn more.
Format-Table as well as the other Format-* cmdlets should be primarily used for console display, should not be used for exporting data. In this case you should use Export-Csv, this way your data preserves its structure and can be imported back at ease, be filtered and be sorted.

Powershell: ForEach Copy-Item doesn't rename properly when retrieving data from array

I am pretty new to PowerShell and I need some help. I have a .bat file that I want to copy as many times as there are usernames in my array and then also rename at the same time. This is because the code in the .bat file remains the same, but for it to work on the client PC it has to have the username as a prefix in the filename.
This is the code that I have tried:
$usernames = Import-Csv C:\Users\Admin\Desktop\usernames.csv
$file = Get-ChildItem -Path 'C:\Users\Admin\Desktop\generatedbat\' -Recurse
foreach ($username in $usernames)
{
ForEach-Object {Copy-Item $file.FullName ('C:\Users\Admin\Desktop\generatedbat\' + $username + $File.BaseName + ".bat")}
}
This copies everything and it kind of works but I have one problem.
Instead of having this filename: JohnR-VPNNEW_up.bat
I get this: #{Username=JohnR}-VPNNEW_up.bat
Any help? Thanks!
So you have one .bat file C:\Users\Admin\Desktop\generatedbat\VPNNEW_up.bat you want to copy to the same directory with new names taken from the usernames.csv --> Username column.
Then try
# get an array of just the UserNames column in the csv file
$usernames = (Import-Csv -Path 'C:\Users\Admin\Desktop\usernames.csv').Username
# get the file as object so you can use its properties
$originalFile = Get-Item -Path 'C:\Users\Admin\Desktop\generatedbat\VPNNEW_up.bat'
foreach ($username in $usernames) {
$targetFile = Join-Path -Path $originalFile.DirectoryName -ChildPath ('{0}-{1}' -f $username, $originalFile.Name)
$originalFile | Copy-Item -Destination $targetFile -WhatIf
}
I have added switch -WhatIf so you can first test this out. If what is displayed in the console window looks OK, then remove that -WhatIf safety switch and run the code again so the file is actually copied
I kept the code the same but instead of using a .csv file I just used a .txt file and it worked perfectly.

PowerShell updating a csv file based from a csv file as a source

I am new to PowerShell or any scripting stuff.
I have here a DataResources(CSV File) which contains of bunch of data's that needs to be inserted into a Results.CSV
Here is my DataResources
For my Result.csv looks like this.
My goal is to export a NEW csv file based from a results.csv as a template
and if a HostName/Host match the data contains a value equivalent to UA and PWD will be inserted/updated from ExportResources CSV file to Exported new CSV File
after executing scripts that I have created it only modifies 1 row not all.
This is what I've done so far.
$DataSource = Import-Csv -Path D:\coding\Powershell\csv\Resources\ExportResources.csv
$DataResults = Import-Csv -Path D:\coding\Powershell\csv\Result\results.csv
foreach ($ItemDataResults in $DataResults)
{
$HostName = $ItemDataResults.HostName
$UA = $ItemDataResults.UA
$PASSWD = $ItemDataResults.PWD
}
$ItemDataSource = $DataSource | ? {$_.Host -eq $HostName}
if ($UA -eq "" -and $PASSWD -eq "")
{
$ItemDataResults.UA = $ItemDataSource.UA
$ItemDataResults.PWD = $ItemDataSource.Passwd
}
$DataResults | Export-Csv D:\coding\Powershell\csv\new.csv -NoTypeInformation
The result almost meet my expectation but the problem here that it only fills one hostname the rest are empty.
The issue with your script is that you loop through $DataResults once, but you have to iterate through it once for each item in $DataSource if you use the method that you're employing. I believe that a better method is to create a hashtable from one CSV, using the host name as the key, and the whole object as the value, then loop through the second array updating the value for each host. That would look something like this:
$DataSource = Import-Csv -Path D:\coding\Powershell\csv\Resources\ExportResources.csv
$DataResults = Import-Csv -Path D:\coding\Powershell\csv\Result\results.csv
$DataHT = #{}
$DataResults | ForEach-Object { $DataHT.Add($_.HostName,$_) }
ForEach( $Record in $DataSource ){
$DataHT[$Record.Host].UA = $Record.UA
$ItemDataResults.PWD = $Record.Passwd
}
$DataHT.Values | Export-Csv D:\coding\Powershell\csv\new.csv -NoTypeInformation

Create multiple files from one CSV, one files from each value in a column [Powershell]

I am new to PowerShell, and I have an issue figuring out how to create from one or multiple .csv files, one file for each value finding in a column, with all the rows that contains in that value.
Let me explain with a example:
I have this source CSV:
I need to create a file for each App in the file. the output of the script should be something like this.
App1.csv
App2.CSV
That for each app that appear in the Original CSV, a new file with all row that have such value, in this case App.
I want to do it in PowerShell so in can be automated, I try with Group-object, then foreach with the values, without luck. I wasn't even remotely close to found the solution.
Thanks in advance and happy coding!
I do not have the most elegant solution, but it works, I checked it on your files, but I ask you to upload the contents of the file as text next time to make it easier to copy. And don't forget choose delimiter in code (I usually use ';')
$some=Import-Csv "D:\testdir\file1.csv" -Delimiter ';'|
Sort-Object header2|
Group-Object -Property header2
foreach ($i in $some){
$i.Group|
Export-Csv -Delimiter ';' -Encoding UTF8 -NoTypeInformation -Force -Path ("D:\testdir\"+$i.Name+".csv")
}
Import the CSV.
Select all the unique values from the column that contains the App name.
Loop through the app names and get all rows where the app name matches.
Export to CSV.
$Path = "./MyFile.csv"
$DestinationDir = "./"
$CSV = Import-CSV -Path $Path
$AppNames = $CSV.H2 | Select -Unique
Foreach ($App in $AppNames)
{
$DestinationPath = Join-Path -ChildPath $App -Path $DestinationDir
$CSV | Where {$_.H2 -eq $APP} | Export-Csv -NoTypeInformation -Path $DestinationPath
}
Example CSV:
H1,H2,H3,H4
Data,App1,Data,Data
Data,App1,Data,Data
Data,App1,Data,Data
Data,App2,Data,Data
Data,App2,Data,Data
For performance reasons, you probably want to use the steppable pipeline here:
$Pipeline = #{}
Import-Csv .\Source.csv |
ForEach-Object -Process {
if (!$Pipeline.Contains($_.Header2)) {
$Pipeline[$_.Header2] = { Export-CSV -notype -Path .\$($_.Header2).csv }.GetSteppablePipeline()
$Pipeline[$_.Header2].Begin($True)
}
$Pipeline[$_.Header2].Process($_)
} -End {
foreach ($Key in $Pipeline.Keys) { $Pipeline[$Key].End() }
}
For a detailed explanation, see: Mastering the (steppable) pipeline

Powershell script to delete folders from list

To piggyback onto this question, PowerShell script to delete files from list and output list of deleted file, I am trying to accomplish something similar. I have a list of usernames that match the names of some folders on our network file server. Not all of the usernames in the list are going to have home folders created, some may simply not exist.
My psuedocode looks something like this:
Load the list of users
For each user check to see if they have a directory or not
If they have a directory, forcefully and recursively remove it
Here is some code that I have been working unsuccessfully with:
$Termed_Users = "C:\Data\Termed_Users.csv"
$Home_Folders = "X:"
$UserList = Import-Csv $Termed_Users
$UserList | ForEach-Object {
$ID = $_.ID
$User_Home = $Home_Folders + "\" + $_.ID }
If ( Test-Path $User_Home ) { Remove-Item -Recurse -Force $User_Home }
The issue is in your ForEach-Object pipe.
You are continually reassigning the $User_Home variable, and cycle through the whole list before attempting any deletes. Move your deletion into that script block:
$UserList | ForEach-Object {
$ID = $_.ID
$User_Home = $Home_Folders + "\" + $_.ID
Remove-Item -recurse -force $User_Home -erroraction silentlycontinue }
I also removed the test since it won't matter - you will try to delete them all and ignore the errors.