I'm trying to concatenate value imported from CSV with a timestamp (to create a filename).
It seems that when I try to use foreach with the $csv it loops through all values within one iteration.
$csv = Import-Csv .\servers.csv
function LogTime {return Get-Date -Format "yyyymmdd_HHmmss"}
foreach ($server in $csv)
{
$filename = $(LogTime) + "_" + $csv.SERVERNAME + ".log"
$filename
}
This results in.
20191024_091007_server1 server2.log
20191024_091007_server1 server2.log
What I'm looking for:
20191024_091007_server1.log
20191024_091007_server2.log
The foreach loop is not using the $server variable
$csv = Import-Csv .\servers.csv
function LogTime {return Get-Date -Format "yyyymmdd_HHmmss"}
foreach ($server in $csv)
{
$filename = $(LogTime) + "_" + $server.SERVERNAME + ".log"
$filename
}
Related
Trying to write a function to create a new line to be added to a table for export. The following outputs the correct values to the console but the CSV is empty.
If I place the code to create $newline at various point in the script it works fine but not when I call it as a function.
$report = #()
Function CreateNewLine
{
$lineproperties = #{
Cluster = $cluster
Node = $node
Database = $d.Name
LogCount = $logcount
LogPath = $p
}
$newline = New-Object PSObject -property $lineproperties
}
# Loop to create values for $cluster etc...
CreateNewLine
$report += $newline
# End loop
$report | Export-CSV 'pathto file' -notype
You have a scope issue here. $newline has no context outside the function. Therefore you would just be adding $null to the $report array. Make the function return the value which can then be captured.
Function CreateNewLine
{
$lineproperties = #{
Cluster = $cluster
Node = $node
Database = $d.Name
LogCount = $logcount
LogPath = $p
}
New-Object PSObject -property $lineproperties
}
# Loop to create values for $cluster etc...
$report += CreateNewLine
The function should have access to those other variables as long as they are in the parent scope of the function.
The function CreateNewLine never returns a value. You need to do the following:
Function CreateNewLine
{
$lineproperties = [PSCustomObject]#{
Cluster = $cluster
Node = $node
Database = $d.Name
LogCount = $logcount
LogPath = $p
}
$lineProperties
}
You can create an object in much easier manner (as Matt said, this works in Powershell 3.0 and later):
Function CreateNewLine
{
[pscustomobject]#{
Cluster = $cluster
Node = $node
Database = "name"
LogCount = $logcount
LogPath = $p
}
}
Then, in any place you want you can use this function:
$cluster = "cluster 1"
$report += createnewline
$cluster = "cluster 2"
$report += createnewline
$report | Export-CSV 'pathto file' -notype
I'm trying to apply a table formatting to my table when it is emailed out, but cannot seem to figure how to do so. I'm pretty sure the problem is related to how the $html variable is set, or maybe when I try to set $EmailTable to $html with $a as the table formatting. Any help is appreciated!
$ProgramA = "A-1"
$MonikerA = "A-2"
$CountA = "1"
$ProgramB = "B-1"
$MonikerB = "B-2"
$CountB = "2"
$ProgramC = "C-1"
$MonikerC = "C-2"
$CountC = "3"
# Create a DataTable
$table = New-Object system.Data.DataTable "TestTable"
$col1 = New-Object system.Data.DataColumn Program,([string])
$col2 = New-Object system.Data.DataColumn Moniker,([string])
$col3 = New-Object system.Data.DataColumn Cases,([string])
$table.columns.add($col1)
$table.columns.add($col2)
$table.columns.add($col3)
# Add content to the DataTable
$row = $table.NewRow()
$row.Program = $ProgramA
$row.Moniker = $MonikerA
$row.Cases = $CountA
$table.Rows.Add($row)
$row = $table.NewRow()
$row.Program = $ProgramB
$row.Moniker = $MonikerB
$row.Cases = $CountB
$table.Rows.Add($row)
$row = $table.NewRow()
$row.Program = $ProgramC
$row.Moniker = $MonikerC
$row.Cases = $CountC
$table.Rows.Add($row)
$row = $table.NewRow()
# Create an HTML version of the DataTable
$html = "<table><tr><td>Program</td><td>Moniker</td><td>Cases</td></tr>"
foreach ($row in $table.Rows)
{
$html += "<tr><td>" + $row[0] + "</td><td>" + $row[1] + "</td><td>" + $row[2] + "</td></tr>"
}
$html += "</table>"
# Here is the formatting I'm trying to apply (which doesn't work)
$a = "<style>BODY{font-family: Verdana; font-size: 9pt;}"
$a = $a + "BODY{background-color:white;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse; }"
$a = $a + "TH{border-width: 2px;padding: 7px;border-style: solid;border-color: black;background-color:lightblue;padding-right: 2px;}"
$a = $a + "TD{border-width: 2px;padding: 5px;border-style: solid;border-color: black;background-color:white; padding-right: 2px;}"
$a = $a + "</style>"
$EmailTable = $html ConvertTo-HTML -head $a
$EmailTable = $html ConvertTo-HTML -head $a
This is not how ConvertTo-Html works. Not only is the statement missing a | before ConvertTo-Html, but $html already contains a (manually constructed) HTML table. The purpose of ConvertTo-Html is to do the conversion of a list of objects into an HTML table for you. Change the above to this:
$EmailTable = $table | ConvertTo-Html -Head $a
Not outputting anything in csv file. Please help!!
This print_r($list).
outputs everything in the database in the right format But when i try to put the into a csv file only one line gets outputted.
$sql = "select * from " . TABLE_ORDERS . "";
$result = $db->Execute($sql);
if ($result->RecordCount() > 0) {
while (!$result->EOF) {
$file_date = date("d_m_Y_G_i_s");
$filename = "../weight/weightExport_".$file_date .".csv";
$customers_Name = $result->fields['customers_name'];
$list = array($customers_Name);
//print_r($list)."<br/>";
$handle = fopen($filename, 'w+');
fputcsv($handle, array('Username'));
fputcsv($handle, $list);
fclose($handle);
$result->MoveNext();
}
}
Change $handle = fopen($filename, 'w+');
to $handle = fopen($filename, 'a+');
It's only one line, because w+ is doing a truncate on that file.
a+ is the append mode.
I'm having trouble understanding how Powershell treats functions. In the following script all functions are called, even if I never actually call the main function. Does powershell not have a concept of call chain?
param([string]$directory)
[string]$global:sqlscript;
$global:types = #{
"double" = "DOUBLE PRECISION";
"int" = "INTEGER";
"QString" = "INTEGER";
"Ignored" = "1";
"Normal" = "2";
"Critical" = "3" }
function resultToSql($element)
{
$global:sqlscript += ('"')
$global:sqlscript += ($element.name + '" ')
$global:sqlscript += ($global:types.Get_Item($element.type))
$global:sqlscript += (',' + [Environment]::Newline)
$global:sqlscript += ('"' + $element.name + "_metric_group" + " " + $global:types.Get_Item($element.metric_group.type))
$global:sqlscript += (',' + [Environment]::Newline)
}
function xmlToSql($source)
{
Write-Host "Parsing...";
$global:sqlscript += "CREATE TABLE IF NOT EXISTS " + '"' + $source.spec.task.ToLower() + '"'+ [Environment]::NewLine
$global:sqlscript += '"' + "id" + '"' + " SERIAL NOT NULL" + [Environment]::NewLine
foreach ($node in $source.spec.measure) {
resultToSql $node
}
foreach ($m in $source.spec.error) {
resultToSql $m
}
$global:sqlscript += '"' + "weighted_sum" + '" ' + $global:types.Get_Item("double") + [Environment]::Newline;
}
function main
{
if ($directory -eq $null) { exit }
else
{
$xmlfiles = Get-ChildItem -Path $directory -include *Spec.xml
foreach ($xmlfile in $xmlfiles)
{
Write-Host "Filename:" $xmlfile;
[xml]$spec = Get-Content $file;
xmlToSql $spec;
Write-Host $script;
}
}
}
PowerShell cant magically detect changes to scripts, close the ISE and re-open it then run your script again. If that fails take the contents of your script paste it in the ISE and click the execute button, i just did that and main didnt run.
Unlike a C/C++/C# program, "you" need to call the Main function - at the bottom of this script. When you run the script above all it does is create the functions you've defined. It doesn't run any of them. You have to do that by calling them in the script and one of those calls has to be at the script level (outside any functions).
Remove the main function container so it resembles the code below:
if ($directory -eq $null) { exit }
else
{
$xmlfiles = Get-ChildItem -Path $directory -include *Spec.xml
foreach ($xmlfile in $xmlfiles)
{
Write-Host "Filename:" $xmlfile;
[xml]$spec = Get-Content $file;
xmlToSql $spec;
Write-Host $script;
}
}
Powershell doesn't execute from Main like C#/C++. It executes what statements are first received outside functions. In this case above it will execute the if statement first as it appears outside the function box.
I would like to automatically script out all SQL Server 2008 policies and conditions on a server each night and compare the files to my version control system. In the UI, I can script out individual policies by right-clicking the policy and selecting Export Policy. Is it possible to script out policies and conditions via SMO or PowerShell?
Ideally, I would like to incorporate this into my existing PowerShell script that generates scripts for all of my other server and database objects. Here's the script that currently does this action:
# Load needed assemblies
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMOExtended")| Out-Null;
#Specify target server and databases.
$sql_server = "SomeServerName"
$SMOserver = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server -ArgumentList "$sql_server"
$databases = $SMOserver.Databases
$BaseSavePath = "T:\SomeFilePath\" + $sql_server + "\"
#Remove existing objects.
Remove-Item $BaseSavePath -Recurse
#Script server-level objects.
$ServerSavePath = $BaseSavePath
$ServerObjects = $SMOserver.BackupDevices
$ServerObjects += $SMOserver.Endpoints
$ServerObjects += $SMOserver.JobServer.Jobs
$ServerObjects += $SMOserver.LinkedServers
$ServerObjects += $SMOserver.Triggers
foreach ($ScriptThis in $ServerObjects | where {!($_.IsSystemObject)})
{
#Need to Add Some mkDirs for the different $Fldr=$ScriptThis.GetType().Name
$scriptr = new-object ('Microsoft.SqlServer.Management.Smo.Scripter') ($SMOserver)
$scriptr.Options.AppendToFile = $True
$scriptr.Options.AllowSystemObjects = $False
$scriptr.Options.ClusteredIndexes = $True
$scriptr.Options.DriAll = $True
$scriptr.Options.ScriptDrops = $False
$scriptr.Options.IncludeHeaders = $False
$scriptr.Options.ToFileOnly = $True
$scriptr.Options.Indexes = $True
$scriptr.Options.Permissions = $True
$scriptr.Options.WithDependencies = $False
<#Script the Drop too#>
$ScriptDrop = new-object ('Microsoft.SqlServer.Management.Smo.Scripter') ($SMOserver)
$ScriptDrop.Options.AppendToFile = $True
$ScriptDrop.Options.AllowSystemObjects = $False
$ScriptDrop.Options.ClusteredIndexes = $True
$ScriptDrop.Options.DriAll = $True
$ScriptDrop.Options.ScriptDrops = $True
$ScriptDrop.Options.IncludeHeaders = $False
$ScriptDrop.Options.ToFileOnly = $True
$ScriptDrop.Options.Indexes = $True
$ScriptDrop.Options.WithDependencies = $False
<#This section builds folder structures. Remove the date folder if you want to overwrite#>
$TypeFolder=$ScriptThis.GetType().Name
if ((Test-Path -Path "$ServerSavePath\$TypeFolder") -eq "true") `
{"Scripting Out $TypeFolder $ScriptThis"} `
else {new-item -type directory -name "$TypeFolder"-path "$ServerSavePath"}
$ScriptFile = $ScriptThis -replace ":", "-" -replace "\\", "-"
$ScriptDrop.Options.FileName = $ServerSavePath + "\" + $TypeFolder + "\" + $ScriptFile.Replace("]", "").Replace("[", "") + ".sql"
$scriptr.Options.FileName = $ServerSavePath + "\" + $TypeFolder + "\" + $ScriptFile.Replace("]", "").Replace("[", "") + ".sql"
#This is where each object actually gets scripted one at a time.
$ScriptDrop.Script($ScriptThis)
$scriptr.Script($ScriptThis)
} #This ends the object scripting loop at the server level.
#Script database-level objects.
foreach ($db in $databases)
{
$DatabaseObjects = $db.ApplicationRoles
$DatabaseObjects += $db.Assemblies
$DatabaseObjects += $db.ExtendedStoredProcedures
$DatabaseObjects += $db.ExtendedProperties
$DatabaseObjects += $db.PartitionFunctions
$DatabaseObjects += $db.PartitionSchemes
$DatabaseObjects += $db.Roles
$DatabaseObjects += $db.Rules
$DatabaseObjects += $db.Schemas
$DatabaseObjects += $db.StoredProcedures
$DatabaseObjects += $db.Synonyms
$DatabaseObjects += $db.Tables
$DatabaseObjects += $db.Triggers
$DatabaseObjects += $db.UserDefinedAggregates
$DatabaseObjects += $db.UserDefinedDataTypes
$DatabaseObjects += $db.UserDefinedFunctions
$DatabaseObjects += $db.UserDefinedTableTypes
$DatabaseObjects += $db.UserDefinedTypes
$DatabaseObjects += $db.Users
$DatabaseObjects += $db.Views
#Build this portion of the directory structure out here. Remove the existing directory and its contents first.
$DatabaseSavePath = $BaseSavePath + "Databases\" + $db.Name
new-item -type directory -path "$DatabaseSavePath"
foreach ($ScriptThis in $DatabaseObjects | where {!($_.IsSystemObject)})
{
#Need to Add Some mkDirs for the different $Fldr=$ScriptThis.GetType().Name
$scriptr = new-object ('Microsoft.SqlServer.Management.Smo.Scripter') ($SMOserver)
$scriptr.Options.AppendToFile = $True
$scriptr.Options.AllowSystemObjects = $False
$scriptr.Options.ClusteredIndexes = $True
$scriptr.Options.DriAll = $True
$scriptr.Options.ScriptDrops = $False
$scriptr.Options.IncludeHeaders = $False
$scriptr.Options.ToFileOnly = $True
$scriptr.Options.Indexes = $True
$scriptr.Options.Permissions = $True
$scriptr.Options.WithDependencies = $False
<#Script the Drop too#>
$ScriptDrop = new-object ('Microsoft.SqlServer.Management.Smo.Scripter') ($SMOserver)
$ScriptDrop.Options.AppendToFile = $True
$ScriptDrop.Options.AllowSystemObjects = $False
$ScriptDrop.Options.ClusteredIndexes = $True
$ScriptDrop.Options.DriAll = $True
$ScriptDrop.Options.ScriptDrops = $True
$ScriptDrop.Options.IncludeHeaders = $False
$ScriptDrop.Options.ToFileOnly = $True
$ScriptDrop.Options.Indexes = $True
$ScriptDrop.Options.WithDependencies = $False
<#This section builds folder structures. Remove the date folder if you want to overwrite#>
$TypeFolder=$ScriptThis.GetType().Name
if ((Test-Path -Path "$DatabaseSavePath\$TypeFolder") -eq "true") `
{"Scripting Out $TypeFolder $ScriptThis"} `
else {new-item -type directory -name "$TypeFolder"-path "$DatabaseSavePath"}
$ScriptFile = $ScriptThis -replace ":", "-" -replace "\\", "-"
$ScriptDrop.Options.FileName = $DatabaseSavePath + "\" + $TypeFolder + "\" + $ScriptFile.Replace("]", "").Replace("[", "") + ".sql"
$scriptr.Options.FileName = $DatabaseSavePath + "\" + $TypeFolder + "\" + $ScriptFile.Replace("]", "").Replace("[", "") + ".sql"
#This is where each object actually gets scripted one at a time.
$ScriptDrop.Script($ScriptThis)
$scriptr.Script($ScriptThis)
} #This ends the object scripting loop.
} #This ends the database loop.
You have a couple of choices from SMO/Powershell.
1: SQLPS/PowerShell with SQL loaded
SQLSERVER:\SQLPolicy\\DEFAULT\Policies
you can then dig through it, i didnt see an "export" but you can certianly get the info out of it.
2: SMO
basically SMO has a Microsoft.SqlServer.Management.DMF namespace that has severial policy objects (what you end up with in the PowerShell side of things) Policy, PolicyStore, PolicyCondition etc, rather than write out an example, you can find one here.
http://rdbmsexperts.com/Blogs/archives/295
again i didnt see an "export" method anywhere, but you could probably spit out what you needed easily enough.