how to export powershel result to csv - powershell

I want to export what I already filtered in ForEach-Object. The problem is that I can't export the filtered data.
I tried the following:
$getTapes.rows | Export-Csv C:\\123\\123456.txt but this has exported all the information without filter.
$getTapes = Invoke-RestMethod -Method GET -ContentType $content -Uri $Uri -Headers #{'Authorization' = $Authorization}
$today = Get-Date
$getTapes.rows | ForEach-Object {
$tape = $_;
if ( $tape.custom_fields.Ueberschreibschutz.value -ge $today ) {
Write-Host "Treffer ID=" $tape.asset_tag " Name=" $tape.name " SNR=" $tape.serial " Mediensatz=" $tape.custom_fields.Mediensatz.value
}
}
$getTapes.rows |export-Csv C:\\123\\123456.txt
I expect:
Treffer ID= 1 Name= 12 SNR= 12345 Mediensatz= M
Treffer ID= 2 Name= 32 SNR= 54321 Mediensatz= W

You should not use Write-Host to collect data. That's only to output pixels on the screen. Instead you should create a custom object you can use as you want later on ... like this:
$Result = $getTapes.rows | ForEach-Object {
if ( $_.custom_fields.Ueberschreibschutz.value -ge $today ) {
[PSCustomObject]#{
TrefferID = $_.asset_tag
Name = $_.name
SNR = $_.serial
Mediensatz = $_.custom_fields.Mediensatz.value
}
}
}
$Result | Export-Csv -Path C:\123\123456.csv -NoTypeInformation

Write-host do nothing except it shows you the result in the console, so it will not modify or delete the things you don't want in $getTapes.rows.
Instead you can define a variable $result and iterate over the $getTapes.rows using Foreach-Object, and add the result if it meets your if condition.
Try this:
$getTapes = Invoke-RestMethod -Method GET -ContentType $content -Uri $Uri -Headers #{'Authorization' = $Authorization}
$today = Get-Date
$getTapes.rows | ForEach-Object -begin {$result = "" } {
$tape = $_;
if ( $tape.custom_fields.Ueberschreibschutz.value -ge $today ) {
$result += "Treffer ID= $($tape.asset_tag) Name= $($tape.name) SNR= $($tape.serial) Mediensatz= $($tape.custom_fields.Mediensatz.value)`n"
}
} -end {$result | export-Csv C:\123\123456.txt}

Related

Powershell Foreach loop to return ID data

I am currently trying to create a foreach loop to take each value from a list and search for it in return data from an API. For some reason I am getting NULL data when I try to loop it.
$agentList = (Import-CSV -Path 'O:\Test\AgentList.txt')
$Params = #{
"Uri" = "https://10.245.55.88:8834/agents"
"Method" = "GET"
"Headers" = #{
"X-ApiKeys" = "accessKey=$($AccessKey); secretKey=$($SecretKey)"
}
}
$agentsNotInSC = Invoke-Restmethod #Params
$agentID = foreach ($agent in $agentList) {
$agentID = $agentsNotInSC.agents | Where-Object { $_.name -eq $agent }
$agentID.id
}
$agentID | Export-Csv -Path "O:\Test\IDAgent.CSV" -NoTypeInformation
trying to get all the return data and export it to a CSV

PowerShell & Power BI Rest API

Essentially what I'm after is the results of rest API Gateways - Get Datasource Users but retaining the ID (in this example $Line.id from my imported CSV file).
The end result should be a CSV with the following fields -
ID, emailAddress, datasourceAccessRight, displayName, identifier, principalType
I'm new to PowerShell and surprised I got this far but can't figure out this final bit.
Cheers
$webclient=New-Object System.Net.WebClient
$webclient.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$Dir = "C:\pbi_pro_user_logs\"
Login-PowerBI
$GateWayFile = Import-CSV -Path "C:\pbi_pro_user_logs\Gateway_Detail.csv"
$Output = #()
foreach ($Line in $GateWayFile){
$Item = $Line.id
$url = "https://api.powerbi.com/v1.0/myorg/gateways/HIDDEN/datasources/"+$Item+"/users"
$Output += (Invoke-PowerBIRestMethod -Url $url -Method Get | ConvertFrom-Json)
}
$Result = $Output.value
$Result | Export-Csv $Dir"GateWay_users.csv" -NoTypeInformation
Try this, using a calculated property from Select-Object:
$GateWayFile = Import-CSV -Path "C:\pbi_pro_user_logs\Gateway_Detail.csv"
$Output = Foreach ($Line in $GateWayFile){
$url = "https://api.powerbi.com/v1.0/myorg/gateways/HIDDEN/datasources/"+$Line.id+"/users"
$Item = (Invoke-PowerBIRestMethod -Url $url -Method Get | ConvertFrom-Json)
# output all properties of the item, plus the ID:
$ItemWithID = $Item | Select *,#{l='Id';e={$line.id}}
Write-Output $ItemWithID
}
# This depends on how you want your csv structured, but for example:
$Result = $Output | Select Id,Value
Or, if Value is a whole object that ID should be assigned inside of, then change the selection lines:
$ItemWithID = $Item.Value | Select *,#{l='Id';e={$line.id}}
$Result = $Output

Can you build a hashtable dynamically from a variable with multiple data rows in powershell?

I am trying to convert the below code to a PowerShell function as I will be using it multiple times in other scripts. I am trying to figure out how I can allow the user to simply pass a SQL Query (a String) to this script that I will turn into a function and have my hash table $row define the keys dynamically based on the column headers and then assign the values when multiple rows are returned by my SQL Query variable $QueryResults. Also, I will have two common variables in each hash table, which are "DateTime" and "ServerName" so those will have to be added as well.
$endpoint = "myPowerBIEndpoint"
$Query = "
myQueryThatReturnsMultipleRecords
"
$GetDate = (Get-Date).AddMinutes(-1)
while($true)
{
if((Get-Date) -gt $GetDate)
{
#Only run the below every 5 minutes
$GetDate = (Get-Date).AddMinutes(5)
#Get list of server to iterate through
$ServerList = Invoke-DbaQuery -SqlInstance "" -Database "" -Query "
EXEC [dbo].[myProc] #MonitorType" -SqlParameters #{MonitorType = "AGHealth"}
}
$ServerResults = #() # Results from each of the servers will be stored here
foreach ($Server in $ServerList)
{
$QueryResults = Invoke-DbaQuery -SqlInstance $ServerList.Cname -Database "" -Query $Query
$DateTime = Get-Date -DisplayHint Datetime -Format "MM/dd/yyyy HH:mm:ss"
foreach ($object in $QueryResults)
{
Write-Host 'Building Payload for' $object.replica_server_name
$row = #{
"DateTime" = $DateTime
"Replica_Server" = $object.replica_server_name
"Log_Send_Queue_Size_mb" = $object.total_log_send_queue_size_mb
"Redo_Queue_Size_mb" = $object.total_redo_queue_size_mb
"Sync_Health" = $object.synchronization_health
"Is_Primary_Replica" = $object.is_primary_replica
"AG_Name" = $object.ag_name
"ServerName" = $Server.Cname
}
$ServerResults += $row
}
}
$payload = #{ "rows" = $ServerResults }
Write-Host 'Invoking Rest Method'
Invoke-RestMethod -Method Post -Uri "$endpoint" -Body (ConvertTo-Json $payload)
(ConvertTo-Json $payload)
sleep 60
}
As Invoke-DbaQueryis somehow a wrapper of Invoke-SqlCmd, we can use the schema information stored in the returned PSObject [DataRow] for each row. Each one has a Table member filled by the command describing the resulting schema for the row. In this [DataTable]Table member, we have the [DataColumnCollection]Columns which describes each column of the row as [DataColmun]. We can then use that to feed a hash with the ColumnName member as a key and use the indexed array Item of the row for this ColumnName as value.
The specific corresponding PowerShell code, we add DateTime and ServerName distinctively because they are not coming from the [DataRow] itself :
$row = #{}
$object.Table.Columns | %{ $row.Add($_.ColumnName, $object.Item($_.ColumnName) ) }
$row.Add("DateTime", $DateTime)
$row.Add("ServerName", $Server.Cname)
The resulting script :
$GetDate = (Get-Date).AddMinutes(-1)
while($true)
{
if((Get-Date) -gt $GetDate)
{
#Only run the below every 5 minutes
$GetDate = (Get-Date).AddMinutes(5)
#Get list of server to iterate through
$ServerList = Invoke-DbaQuery -SqlInstance "" -Database "" -Query "
EXEC [dbo].[myProc] #MonitorType" -SqlParameters #{MonitorType = "AGHealth"}
}
$ServerResults = #() # Results from each of the servers will be stored here
foreach ($Server in $ServerList)
{
$QueryResults = Invoke-DbaQuery -SqlInstance $ServerList.Cname -Database "" -Query $Query
$DateTime = Get-Date -DisplayHint Datetime -Format "MM/dd/yyyy HH:mm:ss"
foreach ($object in $QueryResults)
{
Write-Host 'Building Payload for' $object.replica_server_name
$row = #{}
$object.Table.Columns | %{ $row.Add($_.ColumnName, $object.Item($_.ColumnName) ) }
$row.Add("DateTime", $DateTime)
$row.Add("ServerName", $Server.Cname)
$ServerResults += $row
}
}
$payload = #{ "rows" = $ServerResults }
Write-Host 'Invoking Rest Method'
Invoke-RestMethod -Method Post -Uri "$endpoint" -Body (ConvertTo-Json $payload)
(ConvertTo-Json $payload)
sleep 60
}

Powershell Array with Time Datestamp

I have the following script that will deploy an Octopus Deploy release based on the parameters I provide it.
param(
[string] $releaseVersion,
[array] $future
)
foreach($line in Get-Content C:\admin\customers.txt) {
$ErrorActionPreference = "Stop";
# Define working variables
$octopusURL = "http://10.2.2.62:8022/api"
$octopusAPIKey = "API-Key"
$headers = #{ "X-Octopus-ApiKey" = $octopusAPIKey }
$spaceName = "Default"
$projectName = "C9-Deployment"
$environmentName = "LabFarm2"
$tenantNames = $line
$date = get-date -Format yyyy-MM-dd
$expiredate = $(date).AddDays(1).ToString("yyyy-MM-dd")
# Get space id
$spaces = Invoke-WebRequest -Uri "$octopusURL/spaces/all" -Headers $headers -ErrorVariable octoError | ConvertFrom-Json
$space = $spaces | Where-Object { $_.Name -eq $spaceName }
Write-Host "Using Space named $($space.Name) with id $($space.Id)"
# Get project by name
$projects = Invoke-WebRequest -Uri "$octopusURL/projects/all" -Headers $headers -ErrorVariable octoError | ConvertFrom-Json
$project = $projects | Where-Object { $_.Name -eq $projectName }
Write-Host "Using Project named $($project.Name) with id $($project.Id)"
# Create space specific url
$octopusSpaceUrl = "$octopusURL/$($space.Id)"
# Get release by version
$releases = Invoke-RestMethod -Uri "$octopusSpaceUrl/projects/$($project.Id)/releases" -Headers $headers -ErrorVariable octoError
$release = $releases.Items | Where-Object { $_.Version -eq $releaseVersion }
Write-Host "Using Release version $($release.Version) with id $($release.Id)"
# Get environment by name
$environments = Invoke-RestMethod -Uri "$octopusSpaceUrl/environments?partialName=$([uri]::EscapeDataString($environmentName))&skip=0&take=100" -Headers $headers -ErrorVariable octoError
$environment = $environments.Items | Where-Object { $_.Name -eq $environmentName }
Write-Host "Using Environment named $($environment.Name) with id $($environment.Id)"
$tenants = Invoke-WebRequest -Uri "$octopusSpaceUrl/tenants/all" -Headers $headers -ErrorVariable octoError | ConvertFrom-Json
$tenantNames | ForEach-Object {
$name = $_
$tenant = $tenants | Where-Object { $_.Name -eq $name }
if ($future -eq $null) {
write-host "This deployment is for tonight"
$deploymentBody = #{
ReleaseId = $release.Id
EnvironmentId = $environment.Id
TenantId = $tenant.Id
QueueTime = "${date}T23:00:00"
QueueTimeExpiry = "${expiredate}T05:00:00"
} | ConvertTo-Json
}
if ($future -ne $null) {
write-host "This deployment will take place on $future"
#Problem Line 64 below
$expirefuturedate = (get-date $future).Adddays(1).ToString("yyyy-MM-dd")
$deploymentBody = #{
ReleaseId = $release.Id
EnvironmentId = $environment.Id
TenantId = $tenant.Id
QueueTime = "${future}T23:00:00"
#problem line 70 below
QueueTimeExpiry = "${expirefuturedate}T05:00:00"
} | ConvertTo-Json
}
Write-Host "Creating deployment with these values: $deploymentBody"
$deployment = Invoke-WebRequest -Uri $octopusSpaceUrl/deployments -Method POST -Headers $headers -Body $deploymentBody -ErrorVariable octoError
}
}
So the problem is on line 64 and 70 where I try to take add one day to the Future parameter. If I run this with only the ReleaseVersion parameter set it will run fine without issues. But if I add a parameter for future like "-Future 2021-03-11" I get the following error:
PS C:\Users\bbelden.CLOUD9\Documents\powershell\Octopus> .\Deploycustom_parm.ps1 -releaseversion 8.1.2103.193 -future 20
21-03-11
Using Space named Default with id Spaces-1
Using Project named C9-Deployment with id Projects-101
Using Release version 8.1.2103.193 with id Releases-12243
Using Environment named LabFarm2 with id Environments-161
This deployment will take place on 2021-03-11
ForEach-Object : Cannot convert 'System.Object[]' to the type 'System.DateTime' required by parameter 'Date'.
Specified method is not supported.
At C:\Users\bbelden.CLOUD9\Documents\powershell\Octopus\Deploycustom_parm.ps1:47 char:16
+ $tenantNames | ForEach-Object {
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [ForEach-Object], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.ForEachObjectCommand
Now if I just remove the line 64 completely and manually set a time date stamp in line 70 like the following:
if ($future -ne $null) {
write-host "This deployment will take place on $future"
#$expirefuturedate = (get-date $future).Adddays(1).ToString("yyyy-MM-dd")
$deploymentBody = #{
ReleaseId = $release.Id
EnvironmentId = $environment.Id
TenantId = $tenant.Id
QueueTime = "${future}T23:00:00"
QueueTimeExpiry = "2021-03-11T05:00:00"
} | ConvertTo-Json
}
It will work fine.
So I am not really sure what I am missing here. Please let me know if there is something I am doing wrong. I believe it has to do with the Array, because if I comment that line out the issue will go away, but I need a way to transform the $future variable to adding one day to it.
Thanks
This should explain your error:
PS /home/> $future=[array]'2021-03-11'
PS /home/> (get-date $future).Adddays(1).ToString("yyyy-MM-dd")
Get-Date: Cannot convert 'System.Object[]' to the type 'System.DateTime' required by parameter 'Date'. Specified method is not supported.
PS /home/> $future=[datetime]'2021-03-11'
PS /home/> (get-date $future).Adddays(1).ToString("yyyy-MM-dd")
2021-03-12

powershell webscrape into columns

Im attempting to scrape a website.
When testing I can get the values I'm looking for by doing...
$WebResponse = Invoke-WebRequest -Uri https://www.livesquawk.com/latest-news
($WebResponse.ParsedHtml.DocumentElement.GetElementsByTagName('div') | Where { $_.ClassName -match 'latest_news_each_title'}).InnerText
($WebResponse.ParsedHtml.DocumentElement.GetElementsByTagName('div') | Where { $_.ClassName -match 'latest_news_each_time'}).InnerText
But when I try to put it into a two column return, I get errors and multiple lines of same data?
What am I doing wrong? I'm out of ideas. Thanks in advance.
$WebResponse = Invoke-WebRequest -Uri https://www.livesquawk.com/latest-news
$lists = $WebResponse.ParsedHtml.DocumentElement.GetElementsByTagName('div')
$nodes = $lists[0].childNodes
$r = $lists | % {
[pscustomobject]#{
Time = $_.getElementsByClassName('latest_news_each_time')[0].innerText.Substring(0) | Where-Object { $_ -match "\d+.*" } | foreach { $Matches.Values }
News = $_.getElementsByClassName('latest_news_each_title')[0].innerText
}
}
$R
Since they aren't really grouped together and you already have the logic to get each, you could two arrays and a simple for loop to build the objects.
$WebResponse = Invoke-WebRequest -Uri https://www.livesquawk.com/latest-news
$title = ($WebResponse.ParsedHtml.DocumentElement.GetElementsByTagName('div') | Where { $_.ClassName -match 'latest_news_each_title'}).InnerText
$time = ($WebResponse.ParsedHtml.DocumentElement.GetElementsByTagName('div') | Where { $_.ClassName -match 'latest_news_each_time'}).InnerText
for($i = 0; $i -le $title.count; $i++)
{
[PSCustomObject]#{
Time = $time[$i]
News = $title[$i]
}
}