powershell export variable to txt file - string

I need to extract a variable on a single line in a txt file like so;
Write-Host "Select RDS Collection to migrate"
$AllCollections.Keys | Sort-Object | ForEach-Object { Write-Verbose "[$_] - $($AllCollections.$_)" -Verbose }
Write-Output ''
$Collection = $AllCollections.$((Read-Host -Prompt 'Choose collection number') -as [int])
$oldrdscb = "RDSCB01N01"
$newrdscb = "RDSCB02N01"
$newrdscbsmb = "\\$newrdscb\C$\temp\migrationvariables.txt"
echo "$collection" = "$Collection" | Out-File -FilePath $newrdscbsmb -append -width 200
txt file \RDSCB02N01\c$\temp\migrationvariables.txt now containts:
RDS-FSLOGIXTEST
=
RDS-FSLOGIXTEST
this because it reads the first $collection and the gives the output of $collection variable, which makes sense.
How can i get the result without the variable of the first $collection and send it as text instead of a variable so the end result in the txt would be:
$collection = TEST
The txt is emtpy before running this code.
The Goal here is to read the variables on my new rds server to migrate theme.
Any tips? thank you!

You just need to escape the dollar signs using the backtick (`). It is usually above the tab key on the keyboard.
$oldrdscb = "RDSCB01N01"
$newrdscb = "RDSCB02N01"
$newrdscbsmb = "\\$newrdscb\C$\temp\migrationvariables.txt"
echo "`$collectioname" = "`$Collection" | Out-File -FilePath $newrdscbsmb -append -width 200

Related

PowerShell :: Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel.DatabaseName [duplicate]

This question already has answers here:
How can you use an object's property in a double-quoted string?
(5 answers)
Closed 5 months ago.
I wrote a script that allows me to query the whole Azure database park:
#$ErrorActionPreference = 'SilentlyContinue'
# Connect to Azure
$azureAccount = Connect-AzAccount
# Get Azure Access Token (we will use this to query the databasees)
#$azureToken = Get-AzAccessToken -ResourceUrl https://database.windows.net
$access_token = (Get-AzAccessToken -ResourceUrl https://database.windows.net).Token
# Queries will be picked up from here
$folderPath = '.\Queries'
# Choose how to format each date ("yyyy-MM-dd") or ("yyyy-MM-dd HH:mm:ss")
$DateTime = (Get-Date).ToString("yyyy-MM-dd")
# List Azure Sunscriptions
Get-Azsubscription | ForEach-Object -Begin { $a = 1 } -Process {"$a $($_.Name)"; $a++}
$SubscriptionChoice = Read-Host -Prompt "Copy/paste the name of the Subscription that you want to investigate. If more than one separate them by a coma, Type `"All`" if you want to target all of them"
# Iterate into subscriptoins and print names
foreach ($gs in $SubscriptionChoice) {
Select-Azsubscription -Subscription "$gs" | Out-Null
Write-Host "Let's browse into Azure Sunscription: " -NoNewline
Write-Host (Get-AzContext).Subscription.Name -ForegroundColor green
# Fins all Azure SQL Server
Get-AzSqlServer | ForEach-Object -Begin { $a = 1 } -Process {"$a $($_.ServerName)"; $a++}
$SqlServerChoice = Read-Host -Prompt "Copy/paste the name of the SQL Server that you want to investigate. If more than one separate them by a coma, Type `"All`" if you want to target all of them"
if ($SqlServerChoice = "All"){
$SqlServerChoice = Get-AzSqlServer
}
Foreach ($server in $SqlServerChoice){
$DatabaseChoice = Get-AzSqlDatabase -ServerName $server.ServerName -ResourceGroupName $server.ResourceGroupName | Where-Object DatabaseName -NE "master"
Foreach ($database in $DatabaseChoice){
(Get-ChildItem $folderPath | sort-object {if (($i = $_.BaseName -as [int])) {$i} else {$_}} ).Foreach{
Invoke-Sqlcmd -ServerInstance $server.FullyQualifiedDomainName -Database $database.DatabaseName -AccessToken $access_token -InputFile $psitem.FullName | Export-Csv -Path ".\Results\$psitem.csv" -Append -NoTypeInformation
write-host "Executing $psitem on $database.DatabaseName"
}
}
}
}
However each time the query is executed against a database the Write-Hosts returns:
Executing DTU_to_vCore.sql on Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel.DatabaseName
Here a picture:
This Write-Hosts comes from the line:
write-host "Executing $psitem on $database.DatabaseName"
In which you can find the two variables:
$psitem : which is the name of the file that contains the query
$database.DatabaseName : which should be the database name but instead of printing the database name is printing Microsoft.Azure.Commands.Sql.Database.Model.AzureSqlDatabaseModel.DatabaseName
Why one of the two variable is not interpreted?
You need to encapsulate your variable property in a subexpression operator $().
write-host "Executing $psitem on $($database.DatabaseName)"
This is because only simple variables get expanded in an expandable string.
References
Only simple variable references can be directly embedded in an
expandable string. Variables references using array indexing or member
access must be enclosed in a subexpression.
Source: about_Quoting_Rules
Subexpression operator $( )
Returns the result of one or more statements. For a single result,
returns a scalar. For multiple results, returns an array. Use this
when you want to use an expression within another expression. For
example, to embed the results of command in a string expression.
PS> "Today is $(Get-Date)"
Today is 12/02/2019 13:15:20
PS> "Folder list: $((dir c:\ -dir).Name -join ', ')"
Folder list: Program Files, Program Files (x86), Users, Windows
Source: about_Operators

Powershell Separate csv data into separate rows

I have the following script and it gets me the info I need.
$Monitors = Get-WmiObject WmiMonitorID -Namespace root\wmi
$LogFile = "d:\monitors.csv"
"Manufacturer,Name,Serial" | Out-File $LogFile
ForEach ($Monitor in $Monitors)
{
$Manufacturer = ($Monitor.ManufacturerName|where {$_ -ne 0}|ForEach{[char]$_}) -join ""
$Name = ($Monitor.UserFriendlyName |where {$_ -ne 0}| ForEach{[char]$_}) -join ""
$Serial = ($Monitor.SerialNumberID |where {$_ -ne 0}| ForEach{[char]$_}) -join ""
"$Manufacturer,$Name,$Serial" | Out-File $LogFile -append
}
My problem is the data is exported to the excel spreadsheet like this..
Manufacturer,Name,Serial.
ACI,VE248,K8LMQS048382
HWP,HP P232,6CM8122DXL
HWP,HP P232,6CM7241DRB
I need it to be:
Manufacturer Name Serial
in the spreadsheet, and when I do the next pc, it adds to the next line and so on.
I have looked online and the examples just don't match.
Does anyone have any advice?
As others already commented, use Export-Csv to write out the wanted data in csv format, rather than constructing it manually.
That means your ForEach-Object loop should emit objects instead of lines of concatenated strings.
Also, nowadays, I would use the newer Get-CimInstance instead of Get-WmiObject (What's the difference)
Try
$LogFile = "d:\monitors.csv"
Get-CimInstance -ClassName WmiMonitorID -Namespace root\wmi | ForEach-Object {
[PsCustomObject]#{
Manufacturer = [string]::new($_.ManufacturerName, 0, $_.ManufacturerName.Length).Trim("`0")
Name = [string]::new($_.UserFriendlyName, 0, $_.UserFriendlyName.Length).Trim("`0")
Serial = [string]::new($_.SerialNumberID, 0, $_.SerialNumberID.Length).Trim("`0")
}
} | Export-Csv -Path $LogFile -NoTypeInformation -UseCulture
The -UseCulture switch makes sure the output csv file uses the same delimiter characters your locally installed Excel would expect, so you can simply double-click the file to open it in Excel

Powershell: Extract several strings from txt and create table out of it

I need to create a csv file out of values that are spread over many txt files. Here is an example for one of the txt files (they are all formatted the same way and stored in one folder, lets say c:\user\txtfiles):
System: asdf
Store: def
processid: 00001
Language: english
prodid: yellowshoes12
email: asdf#asdf.com
prodid: blueshoes34
some
other
text blabla
The result csv should look like this (i added values from another sample txt just to make it clear):
processid, prodid
00001, yellowshoes12
00001, blueshoes34
00002, redtshirt12
00002, greensocks34
That means that every product ID in the txt should be assigned to the one processid in the txt and added as single line to the csv.
I tried to reach the result as follows:
$pathtofiles = Get-ChildItem c:\user\txtfiles | select -ExpandProperty FullName
$parsetxt = $pathtofiles |
ForEach {
$orderdata = Import-Csv $_ |
Where-Object {($_ -like '*processid*') -or ($_ -like '*prodid*')} |
foreach {
write-output $orderdata -replace 'processid: ','' -replace 'prodid: ',''
}
}
$orderdata
So my intention was to isolate the relevant lines, delete everything that is not wanted, assign the values to variables and build a table out of it. One problem is that if I replace $orderdata from the end of the code into the end of the first foreach-loop nothing is printed. But after deliberating quite a while I am not sure if my approach is a good one anyway. So any help would be very appreciated!
Daniel
I think this is best done using a switch -Regex -File construct while iterating over the files in your folder.
# get the files in the folder and loop over them
$result = Get-ChildItem -Path 'c:\user\txtfiles' -Filter '*.txt' -File | ForEach-Object {
# the switch processes each line of a file and matches the regex to it
switch -Regex -File $_.FullName {
'^processid:\s+(\d+)' { $id = $matches[1] }
'^prodid:\s+(\w+)' { [PsCustomObject]#{'processid' = $id; 'prodid' = $matches[1]}}
}
} | Sort-Object processid, prodid
# output on console screen
$result
# output to CSV file
$result | Export-Csv -Path 'c:\user\txtfiles\allids.csv'
Result on screen:
processid prodid
--------- ------
00001 blueshoes34
00001 yellowshoes12
00002 greenshoes56
00002 purpleshoes88

Powershell comparing data in a CSV against files in a folder

I'm fairly new to powershell.
I'm trying to compare data in a CSV File against random files in a specific folder.
I want to see if and what has changed and then log that in another column called "Changed".
Here's what I've done below, it seems to create a new column called 'Changed' but doesn't input the changes in it.
$Spreadsheet = 'C:\Powershell\CSV\inv.csv'
$SpreadSheetPath = "C:\Powershell\CSV"
Import-Csv $Spreadsheet -Delimiter "|" -Encoding Default | ForEach-Object -
{
$Path += $_.Path
$Filename += $_.Filename
$DateModified += $_.DateModified
$FileSize += $_.FileSize
$MD5Hash += $_.MD5Hash
}
{
$Msg1 = "Path changed"
$Msg2 = "File Name changed"
$Msg3 = "Date Modified changed"
$Msg4 = "File Size changed"
$Msg5 = "MD5 changed"
$Msg6 = "Files are the same"
$psdata = "D:\ps-test\data\*.*"
}
If (($Path -eq $psdata))
{
Import-Csv C:\Powershell\CSV\inv.csv |
Select-Object *,#{Name='Changed';Expression={$Msg6}} |
Export-Csv C:\Powershell\CSV\NewSpreadsheet4.csv
}
Else
{
Import-Csv C:\Powershell\CSV\inv.csv |
Select-Object *,#{Name='Changed';Expression={$Msg1}} |
Export-Csv C:\Powershell\CSV\NewSpreadsheet4.csv
}
Here is an example of what the CSV looks like:
Path Filename Date Modified File Size MD5 Hash
D:\ps-test\data adminmodeinfo.htm 03/11/2010 22:42 1079 BD1C9468D71FD33BB35716630C4EC6AC
E:\ps-test\data admintoolinfo.htm 03/11/2010 22:42 868 24B99B6316F0C49C23F27FEA6FF1C6AC
E:\ps-test\data admin_ban.bmp 03/11/2010 22:42 63480 C856F1F3C58962B456E749F2EA9C933A
E:\ps-test\data baseline.dat 03/20/2010 03:18:33 173818 F13183D88AABD1A725437802F8551A06
E:\ps-test\data blueRule.gif 03/11/2010 22:42 815 D1AEFE884935095DAB42DAFD072AA46F
E:\ps-test\data deffactory.dat 03/20/2010 03:18:33 706 862D4DFD2F49021BB7C145BDAFE62F6F
E:\ps-test\data dividerArt.jpg 03/11/2010 22:42 367 F7050C596C097C0B01A443058CD15E35
There are many issues with your code.I will try to highlight a few of the issues, link to documentation and point you in the right direction so that you can resolve your issues. A proper solution would require getting many more requirements, or writing code (off-topic for StackOverflow)
Change
| ForEach-Object -
{
to
| ForEach-Object {
In the Foreach-Object, you are concatenating values from each line because you are using +=.
On the first run, $Path contains D:\ps-test\data.
After the second run, it contains D:\ps-test\dataE:\ps-test\data.
At the end of your test data, it contains D:\ps-test\dataE:\ps-test\dataE:\ps-test\dataE:\ps-test\dataE:\ps-test\dataE:\ps-test\dataE:\ps-test\data
The messages are contained in a script block, but it does not look like this is intentional as this is never executed. So after the scriptblock, the variable $Msg1 has not been created; it's blank.
If (($Path -eq $psdata))
double brackets not required.
will always be false because the variable $psdata does not exist as it was stated inside a script block.
will always be false because you are attempting to equate the strings; your input does not literally contain "D:\ps-test\data\*.*". You probably want -like instead of -eq.
will always be inaccurate because even if the paths are compared, there is no check that the file actually exists on the system.
Useful links
Test-Path to check if file exists.
Get-FileHash to get MD5 hash and compare to file.
Get-ChildItem to get a list of directories/files in a directory.
Write-Output so that you can print variables and make sure they contain what you expect.
about_comparison_operators - -in and -contains will help you.
This is a suggestion to help you get started. It's not complete and not tested! Let me know if it works as expected and if you have any questions.
Import-Csv 'C:\Powershell\CSV\inv.csv' -Delimiter "|" -Encoding Default | foreach {
$Path += $_.Path
$Filename += $_.Filename
$DateModified += $_.DateModified
$FileSize += $_.FileSize
$MD5Hash += $_.MD5Hash
$file = [System.IO.FileInfo](Join-Path $Path $Filename)
if (-not $file.Exists) {
$message = "File does not exist"
}
elseif ($file.LastWriteTime -ne [DateTime]$DateModified) {
$message = "Dates differ"
}
elseif ($file.Length -ne [int]$FileSize) {
$message = "Sizes differ"
}
# and so on...
# (You cannot really compared a changed file name btw)
New-Object -Type PSObject -Prop #{
Path = $Path
Filename = $Filename
DateModified = $DateModified
FileSize = $FileSize
MD5Hash = $MD5Hash
Message = $message
}
} | Export-CSV 'C:\Powershell\CSV\NewSpreadsheet4.csv'

Capture Get-ChildItem results into string array for HTML output

I'm writing a PowerShell script and I want to capture the list of files in a directory and store into a variable. Once captured I'd like to print it to an HTML file. I've captured the data like this:
$listDownloads = Get-ChildItem -Force "C:\Users\Someuser\Downloads"
Now, I want to convert $listDownloads into a string and split it. How do I go about doing that?
I've tried this:
$listSplit = $listDownloads.ToString().Split(" ")
but I get this output:
System.Object[]
Updated:
$html = '<html>'
$body = '<body>'
$p = '<p>'
$pClose = '</p>'
$StatusDownloads = 'Directory of the Downloads Folder'
$pTags = $p.ToString() + $StatusDownloads + $pClose.ToString();
$listDownloads = (Get-ChildItem -Force "C:\Users\Someuser\Downloads").Name;
function createHTML($addtoFile){
$addtoFile | Add-Content 'status.html'
}
function printData($printData){
Write-Output $printData
}
$html | Set-Content 'status.html'
createHTML($html)
createHTML($body)
createHTML($pTags)
createHTML($listDownloads)
When I try to print $listDownloads it gives me the data all on the same line (i.e. File 1 File 2) I want each file or folder displayed on a new line. How would I do that? If I were to type Get-ChildItem -Force "C:\Users\Someuser\Downloads" into Powershell it would give the list of files line by line. I want that type of output on my HTML page.
The only reason I can think you want to split is to get an array of filenames.
If that's the case, you can do:
$list = (Get-ChildItem -Force "C:\Users\Someuser\Downloads").FullName
From your update you would need to pass into your function as:
createHTML($listDownloads -join "`n")

Resources