PowerShell and MySQL - Leave connection open for multiple queries? - mysql

I am using the MySQL connector with PowerShell and I have the need to do a query, then scrub the data a little bit and then dump the remainder to another table on the same MySQL DB. How could I leave the connection open to make this all run a bit faster?
[void][System.Reflection.Assembly]::LoadWithPartialName("MySql.Data")
$Connection = New-Object MySql.Data.MySqlClient.MySqlConnection
$Connection.ConnectionString = $ConnectionString
$Connection.Open()
$Command = New-Object MySql.Data.MySqlClient.MySqlCommand($Query, $Connection)
$DataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter($Command)
$DataSet = New-Object System.Data.DataSet
$RecordCount = $dataAdapter.Fill($dataSet, "data")
return $DataSet.Tables[0]

Create the connection object in the function that calls this function. The called function will inherit whatever objects the calling function is maintaining, so $Connection will be valid in the called function.
function RunMe(){
[void][System.Reflection.Assembly]::LoadWithPartialName("MySql.Data")
$Connection = New-Object MySql.Data.MySqlClient.MySqlConnection
$Connection.ConnectionString = $ConnectionString
$Connection.Open()
# Call the function that executes the MySQL code
ExecuteMySQL
# If needed, call another function that executes the MySQL code
ExecuteSomeOtherMySQL
# Close the connection after all MySQL operations are complete
$Connection.Close()
}
function ExecuteMySQL(){
$Command = New-Object MySql.Data.MySqlClient.MySqlCommand($Query, $Connection)
$DataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter($Command)
$DataSet = New-Object System.Data.DataSet
$RecordCount = $dataAdapter.Fill($dataSet, "data")
return $DataSet.Tables[0]
}

Related

No mapping exists objecttype: Arraylist to native type

I have an arraylist filled with data from a cmdlet (from the BEMCLI module) and want to store the data in a database. Declaring every column is just to specify the error.
There are some questions about a similar error code but I don't know how to get the solution work for me.
Errorcode:
No mapping exists from object type System.Data.Arraylist to a known managed
provider native type
In C:\**\test.ps1:68 Zeichen:1
+ $SqlCmd.executenonquery()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentException
Script:
$JobHistory = Invoke-Command -ComputerName $ServerName -ScriptBlock {
Import-Module BEMCLI;
Get-BEJobHistory -FromStartTime (Get-Date).AddDays(-1)
}
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True;"
$SqlConnection.Open()
for ($i=0; $i -lt $JobHistory.Length; $i++) {
$SqlCmd.Parameters.Add("#Name", [System.Data.SqlDbType]::string).Value = $JobHistory[$i].Name
$SqlCmd.Parameters.Add("#ID", [System.Data.SqlDbType]::UniqueIdentifier).Value = $JobHistory[$i].ID
$SqlCmd.Parameters.Add("#JobName", [System.Data.SqlDbType]::String).Value = $JobHistory[$i].JobName
$SqlCmd.Parameters.Add("#JobStatus", [System.Data.SqlDbType]::String).Value = $JobHistory[$i].JobStatus
$SqlCmd.Parameters.Add("#Job", [System.Data.SqlDbType]::String).Value = $JobHistory[$i].Job
$SqlCmd.Parameters.Add("#JobId", [System.Data.SqlDbType]::UniqueIdentifier).Value = $JobHistory[$i].JobId
$SqlCmd.Parameters.Add("#JobType", [System.Data.SqlDbType]::String).Value = $JobHistory[$i].JobType
$SqlCmd.Parameters.Add("#StartTime", [System.Data.SqlDbType]::DateTime).Value = $JobHistory[$i].StartTime
$SqlCmd.Parameters.Add("#ElapsedTime", [System.Data.SqlDbType]::TimeSpan).Value = $JobHistory[$i].ElapsedTime
$SqlCmd.Parameters.Add("#EndTime", [System.Data.SqlDbType]::DateTime).Value = $JobHistory[$i].EndTime
$SqlCmd.Parameters.Add("#PercentComplete", [System.Data.SqlDbType]::Real).Value = $JobHistory[$i].PercentComplete
$SqlCmd.Parameters.Add("#AgentServer", [System.Data.SqlDbType]::String).Value = $JobHistory[$i].AgentServer
$SqlCmd.Parameters.Add("#AgentServerIdList", [System.Data.SqlDbType]::String).Value = $JobHistory[$i].AgentServerIdList
$SqlCmd.Parameters.Add("#BackupExecServerName", [System.Data.SqlDbType]::String).Value = $JobHistory[$i].JobLogFilePath
$SqlCmd.Parameters.Add("#JobLogFilePath", [System.Data.SqlDbType]::String).Value = $JobHistory[$i].JobLogFilePath
$SqlCmd.Parameters.Add("#DeduplicationRatio", [System.Data.SqlDbType]::Real).Value = $JobHistory[$i].DeduplicationRatio
$SqlCmd.Parameters.Add("#JobRateMBPerMinute", [System.Data.SqlDbType]::Real).Value = $JobHistory[$i].JobRateMBPerMinute
$SqlCmd.Parameters.Add("#StorageName", [System.Data.SqlDbType]::String).Value = $JobHistory[$i].StorageName
$SqlCmd.Parameters.Add("#TotalDataSizeBytes", [System.Data.SqlDbType]::BigInt).Value = $JobHistory[$i].TotalDataSizeBytes
$SqlCmd.Parameters.Add("#ErrorCategory", [System.Data.SqlDbType]::Int).Value = $JobHistory[$i].ErrorCategory
$SqlCmd.Parameters.Add("#ErrorCode", [System.Data.SqlDbType]::Int).Value = $JobHistory[$i].ErrorCode
$SqlCmd.Parameters.Add("#ErrorCategory", [System.Data.SqlDbType]::String).Value = $JobHistory[$i].ErrorCategory
$SqlCmd.Parameters.Add("#ErrorMessage", [System.Data.SqlDbType]::Int).Value = $JobHistory[$i].ErrorMessage
$SqlQuery = "INSERT INTO JobHistory(Nr,Name,ID,JobName,JobStatus,Job,JobId,JobType,StartTime,ElapsedTime,EndTime,PercentComplete,AgentServer,AgentServerIdList,BackupExecServerName,JobLogFilePath,DeduplicationRatio,JobRateMBPerMinute,StorageName,TotalDataSizeBytes,ErrorCategory,ErrorCode,ErrorCategory,ErrorMessage) VALUES (#Nr,#Name,#ID,#JobName,#JobStatus,#Job,#JobId,#JobType,#StartTime,#ElapsedTime,#EndTime,#PercentComplete,#AgentServer,#AgentServerIdList,#BackupExecServerName,#JobLogFilePath,#DeduplicationRatio,#JobRateMBPerMinute,#StorageName,#TotalDataSizeBytes,#ErrorCategory,#ErrorCode,#ErrorCategory,#ErrorMessage)"
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlCmd.ExecuteNonQuery()
}
Thanks to Richard for giving the right hint.
Collections cause the problem (AgentServer and AgentServerIdList)
i fixed the code from above, adding $SqlCmd.Parameters.Clear() in the loop to clear the parameters in every loop. It was something like 'cannot declare #Variable twice'.
Commandline gave me another error - so i decided to switch to .Parameters.AddWithValue-Command.
Script works fine now. Thank you!
$JobHistory = invoke-command -ComputerName $ServerName -ScriptBlock { import-module BEMCLI; Get-BEJobHistory -FromStartTime (get-date).AddDays(-1) }
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True;"
$SqlCmd.Connection = $SqlConnection
$SqlConnection.Open()
for($i=0; $i -lt $JobHistory.Length; $i++){
$SqlCmd.Parameters.Clear()
$SqlCmd.Parameters.AddWithValue("#Nr", $JobHistory[$i].Nr)
$SqlCmd.Parameters.AddWithValue("#Name",$JobHistory[$i].Name)
$SqlCmd.Parameters.AddWithValue("#ID", $JobHistory[$i].ID)
$SqlCmd.Parameters.AddWithValue("#JobName", $JobHistory[$i].JobName)
$SqlCmd.Parameters.AddWithValue("#JobStatus", $JobHistory[$i].JobStatus)
$SqlCmd.Parameters.AddWithValue("#Job", $JobHistory[$i].Job)
$SqlCmd.Parameters.AddWithValue("#JobId", $JobHistory[$i].JobId)
$SqlCmd.Parameters.AddWithValue("#JobType", $JobHistory[$i].JobType)
$SqlCmd.Parameters.AddWithValue("#StartTime", $JobHistory[$i].StartTime)
$SqlCmd.Parameters.AddWithValue("#ElapsedTime", $JobHistory[$i].ElapsedTime)
$SqlCmd.Parameters.AddWithValue("#EndTime", $JobHistory[$i].EndTime)
$SqlCmd.Parameters.AddWithValue("#PercentComplete", $JobHistory[$i].PercentComplete)
$SqlCmd.Parameters.AddWithValue("#BackupExecServerName", $JobHistory[$i].BackupExecServerName)
$SqlCmd.Parameters.AddWithValue("#JobLogFilePath", $JobHistory[$i].JobLogFilePath)
$SqlCmd.Parameters.AddWithValue("#DeduplicationRatio", $JobHistory[$i].DeduplicationRatio)
$SqlCmd.Parameters.AddWithValue("#JobRateMBPerMinute", $JobHistory[$i].JobRateMBPerMinute)
$SqlCmd.Parameters.AddWithValue("#StorageName", $JobHistory[$i].StorageName)
$SqlCmd.Parameters.AddWithValue("#TotalDataSizeBytes", $JobHistory[$i].TotalDataSizeBytes)
$SqlCmd.Parameters.AddWithValue("#ErrorCode", $JobHistory[$i].ErrorCode)
$SqlCmd.Parameters.AddWithValue("#ErrorCategory", $JobHistory[$i].ErrorCategory)
$SqlCmd.Parameters.AddWithValue("#ErrorCategoryType", $JobHistory[$i].ErrorCategoryType)
$SqlCmd.Parameters.AddWithValue("#ErrorMessage", $ValueForJobHistory[$i].ErrorMessage)
$SqlQuery = "Insert into JobHistory(Nr,Name,ID,JobName,JobStatus,Job,JobId,JobType,StartTime,ElapsedTime,EndTime,PercentComplete,BackupExecServerName,JobLogFilePath,DeduplicationRatio,JobRateMBPerMinute,StorageName,TotalDataSizeBytes,ErrorCode,ErrorCategory,ErrorCategoryType) Values(#Nr,#Name,#ID,#JobName,#JobStatus,#Job,#JobId,#JobType,#StartTime,#ElapsedTime,#EndTime,#PercentComplete,#BackupExecServerName,#JobLogFilePath,#DeduplicationRatio,#JobRateMBPerMinute,#StorageName,#TotalDataSizeBytes,#ErrorCode,#ErrorCategoryType,#ErrorCategory)"
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.executenonquery()
}

Function returns value to console but not to file

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

Converting Body to HTML Not Working

I am trying to make my body of text convert to HTML so it does not show as plain text in my email.
Here is the code
$From = ""
$To = ""
$SMTPServer = ""
$SMTPPort = "587"
$Username = ""
$Password = ""
$subject = "Test Powershell"
$body = $htmlreport
$bodyAsHtml = $true
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.Send($From, $To, $subject, $body);
I cant see to get the report to send as HTML.
Instead of passing the individual strings to $smtp.Send(), you should create a MailMessage object and send that instead:
$msg = New-Object System.Net.Mail.MailMessage
$msg.From = $From
$msg.To = $To
$msg.Subject = $subject
$msg.Body = $body
$msg.IsBodyHtml = $true # this is where the magic happens
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort)
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password)
$smtp.Send($msg) # and then send the message we just composed above
$bodyAs contains `enter code here`. You should remove that. You also don't set it anywhere.
Maybe try the Send-MailMessage cmdlet instead:
Send-MailMessage -SmtpServer $SMTPServer -To $To -From $From -Subject $subject -Body $body -BodyAsHtml

Can't call PowerShell script for database access (MYSQL)

Using this database connection script I have found here. I have modified it and did the proper setting to let the script run but don't understand the error I am getting.
The script code is here:
Param(
[Parameter(
Mandatory = $true,
ParameterSetName = '',
ValueFromPipeline = $true)]
[string]$Query
)
$MySQLAdminUserName = 'myName'
$MySQLAdminPassword = 'myPass'
$MySQLDatabase = 'myDatabase'
$MySQLHost = 'HostingServerForMyDatabase'
$ConnectionString = server= + $MySQLHost + ;port=3306;uid= + $MySQLAdminUserName + ;pwd= + $MySQLAdminPassword + ;database=+$MySQLDatabase+
Try {
[void][System.Reflection.Assembly]LoadWithPartialName(MySql.Data)
$Connection = New-Object MySql.Data.MySqlClient.MySqlConnection
$Connection.ConnectionString = $ConnectionString
$Connection.Open()
$Command = New-Object MySql.Data.MySqlClient.MySqlCommand($Query, $Connection)
$DataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter($Command)
$DataSet = New-Object System.Data.DataSet
$RecordCount = $dataAdapter.Fill($dataSet, data)
$DataSet.Tables[0]
}
Catch {
Write-Host ERROR Unable to run query $query `n$Error[0]
}
Finally {
$Connection.Close()
}
And so, this is the error I recieve with the following command -
COMMAND: .\MySQL.ps1 -Query "select GUID FROM MYTABLE"
ERROR:Parameter declerations are a comma-serperated list of variable names with optional initializer expressions. At (my script file path)\MySQL.ps1:5 char:30 + ValueFromPipeline = $true)] <<<<
Apparently the error is not from running the script as in shown in the question nor in the link, but some unknown other script.
The error message shows you are missing the closing parentheses.
Parameter declerations are a comma-serperated list of variable names
with optional initializer expressions. At (my script file
path)\MySQL.ps1:5 char:30 + ValueFromPipeline = $true>] <<<<
The code you posted here and in the link does have it correct.
Param(
[Parameter(
Mandatory = $true,
ParameterSetName = '',
ValueFromPipeline = $true)]
[string]$Query
)
Notice $true)]
Correct MySQL.ps1 so it is exactly the same as in your link.

Script Exporting Policies and Conditions

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.