Donnerstag, 3. Juli 2014

Two workarounds to the PowerShell Workflow Problem

I got two workarounds to the problem in previous post.

Frank Peter Schultze ‏@fpschultze proposed to use inlinescript

 Workflow Strange
{
    param(
        [string]$folder
        )

    inlinescript
    {
    !(Test-Path -path $using:folder)
    }
}

and I found the following solution

Workflow Strange
{
    param(
        [string]$folder
        )
    $a = Test-Path -path $folder
    ! $a
}

Test-Path in PowerShell Workflow Problem

Hello PowerShell World.
I'm back an my current focus is PowerShell WorkFlows.

And I just found a strange example I can't explain.

Workflow Strange
{
    param(
        [string]$folder
        )


    if (Test-Path -path $folder)
    {
        "Folder $folder exists"
    }
    if (!(Test-Path -path $folder))
    {
        "Folder $folder seenms not exists"
        "But Get-Item shows it is there"
        Get-item -path $folder

    }

    $a = (Test-Path -path $folder)
    ! $a
}

Strange -folder 'C:\temp' -PSComputerName  MAGV-2012AKTDE
And here is its output

Folder C:\temp exists
Folder C:\temp seenms not exists
But Get-Item shows it is there


    Verzeichnis: C:\


Mode                LastWriteTime     Length Name                                                                          PSComputerName                                                             
----                -------------     ------ ----                                                                          --------------                                                             
d----        22.08.2013     10:53            temp                                                                          MAGV-2012AKTDE                                                             
True






All involved machines running PowerShell V3.0.

Sonntag, 19. August 2012

Screenshot of Windows 8 Pseudo Start Menu


Here is a screenshot of my Windows 8 RTM machine with the pseudo start menu. Click into the picture to see the complete desktop of my machine. And read my last post, to see how it was done.

How to build a Windows 8 Start Menu

Recently I read  How to Get the Classic Start Menu Back in Windows 8 from How-To-Geek.

Having my toolbar attached to the left it creates a menu near the left bottom corner. That is great.

The only problem is, that there are two start menu folder

%ProgramData%\Microsoft\Windows\Start Menu\Programs

and

%AppData%\Microsoft\Windows\Start Menu\Programs

To combine the two folders into one I create this little PowerShell function, which creates or updates a combined version at C:\Startmenu.

All to do to complete the trick is to use this path instead of the above pathes given by How-To-Geek to create the toolbar.

PS.: the new Windows 8 UI (formerly called Metro ) is just the backside of the desktop, it is nearly useless for Desktop Users.





Sonntag, 22. Juli 2012

Bookreview


Microsoft® SQL Server® 2012 T-SQL Fundamentals



By 
Publisher: Microsoft Press
Released: June 2012
Pages: 448



A succinct introduction for beginners and a profound reference for experienced users.

This is a fresh book about T-SQL. Its title references SQL-Server version 2012, but it is well suited to work with older versions, say back to SQL-Server 2005. Features not present in all versions are clearly tagged.

The book targets at beginners, but I can can assure you, that even after more than 10 years practise with  sql-scripts, it is an excellent reading.

Let us look at the contents, which is currently missing on O'Reilly's link below.

Chapter 1 Background to T-SQL Querying and Programming
Beside some theoretical background, here you learn what is new, like the ABC. These are acronyms standing for the flavors of SQL Server: Appliance, Box and Cloud. Box is the new name for what I knew as SQL Server from versions 6.0 to 2008. Now I know about A and C too.

Chapter 2 Single-Table Queries.
I didn't learn new features, but a better presentation of the order of the logical steps, which are done, when a query is executed. This helps later to understand some restrictions, which I though of a bit artificial until now.

Chapters 3 Joins
No new features since SQL Server 2005. But rather exhaustive, well suited for beginners.

Chapter 4 Subqueries
Here the section Dealing with Misbehaving Subqueries contains stuff I had learned the hard way, i.e. by doing.

Chapter 5 Table Expressions
I got the confirmation that some coding variants perform equally well and it is best to choose the most readable. For example Common Table Expressions (CTEs) often increase the readability and no measurable impact on the performance.

Chapter 6 Set Operators 
Here the understanding of the logical steps from chapter 2 bear fruits.

Chapter 7 Beyond the Fundamentals of Querying
This starts with Window Functions. Obviously a new name, for something I knew as Analytical functions. And there are a few new functions here to learn with SQL Server 2012. You also find Pivoting, Unpivoting and Grouping Sets here.

Chapter 8 Data Modification
Besides INSERT, UPDATE and DELETE, you find truncate, bulk insert and merge here too.

Chapter 9 Transactions and Concurrency. 
I have to reread this later again. Just found out, that I have some gaps here.

Chapter 10 Programmable Objects 
This is about batches, functions and store procedures.

And there is an appendix showing how to do an install, to try all the things out.

Let me resume in 10 chapters, you have all the basic stuff to write correct T-SQL scripts. Even some hints concerning performance are included.

If T-SQL is new to you, you find lots of exercises and solutions in the book. 
I only threw a short look on them.

To me this is a valuable reference book and a resource to fill some gaps.

I got my team leader to order a copy of the book for my two younger co-workers. I think it is good to have things in place in one book we all have read, than having to collect each bit from the web when need arises.


More info about the book you find here:
I review for the O'Reilly Blogger Review Program

Sonntag, 20. Mai 2012

Small Framework to load sql scripts simultaniously to several Servers

I use the following framework to run scripts calling sqlcmd simultaneously as PowerShell jobs during some MsBuild Task. My Buildagents are running Server 2003 and there are some linitations cf. StackOverflow.
But just calling sqlcmd works fine. In fact I'm dropping and recreating my test databases and running a lot of sql scripts completly within such background jobs. I didn't try it with the Oracle part using sqlplus which I run in the main script and after whose termination I wait for jobs to terminate in time or terminate them. 

$workdir = Split-Path $MyInvocation.MyCommand.Path            
$logdir = 'C:\temp\log'            
$server1 = 'my_sql2008'            
$server2 = 'my_sql2005'            
$datbase = 'PowerShellTest'            
            
$cmd1 = [scriptblock]::Create(". $workdir\script_containing_function_for_background_job.ps1
Some_function -server $server1 -database $datbase $logdir -asJob" )            
            
                
$cmd1 = [scriptblock]::Create(". $workdir\script_containing_function_for_background_job.ps1
Some_function -server $server2 -database $datbase $logdir -asJob" )            
            
            
"...Starting the background jobs"            
$SQLJobStartTime = Get-date            
$jnr1 = (Start-Job -ScriptBlock $cmd1).Id            
$jnr2 = (Start-Job -ScriptBlock $cmd2).Id            
# *****************************************            
            
' Doing something slow here (it happens to be with an Oracle Server'            
<#
....
#>            
            
function Get-WaitTime             
{            
    param(            
        [DateTime]$start,            
        $dauer            
    )            
    $rest = $dauer - ((Get-Date) - $start).Totalseconds             
    if ($rest -lt 0) {$rest = 0}            
    $rest            
}            
            
'...Waiting for job on  SQL Server 2008'            
Wait-job -id $jnr1 -timeout ( Get-WaitTime $SQLJobStartTime 960 )   # max 16 min            
if ((Get-job -id $jnr1).state -eq 'Running')            
{            
    Stop-job -id $jnr1            
}             
Receive-Job -id $jnr1            
$state1 = (Get-job -id $jnr1).State            
$dauer1 = ((get-date) - $SQLJobStartTime).Totalseconds            
            
"$(Get-date -f d)  $(Get-date -f t) Release $release($build) Einspielen auf SQl-Server 2008 $state1 $dauer1 secs"            
            
'...Waiting for job  SQL Server 2005'            
Wait-job -id $jnr2 -timeout ( Get-WaitTime $SQLJobStartTime 960 )   # max 16 min            
if ((Get-job -id $jnr2).state -eq 'Running')            
{            
    Stop-job -id $jnr2            
}             
Receive-Job -id $jnr2            
$state2 = (Get-job -id $jnr2).State            
$dauer2 = ((get-date) - $SQLJobStartTime).Totalseconds            
            
"$(Get-date -f d)  $(Get-date -f t) Release $release($build) Einspielen auf SQl-Server 2005 $state2 $dauer2 secs"            

Displaying the builds of a given build-definition since the latest succesfull one

When it comes to fixing broken builds, the first step is to determine when the last successful build run and which builds failed afterwards.
In practice I'm looking for the state of 20 build definitions each morning, but here I reduce the script to a single one.

# adapt the following 4 lines to your environment            
Add-Type -Path "C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.Build.Client.dll"            
            
$tfsuri = 'your tfs server'            
$project = "your prpject"            
$buildDefinition = 'Main'            
            
function Get-BuildInfo            
{            
    param(            
        $buildDefinition,             
        $MaxBuildsPerDefinition = 5,            
        [switch]$DontBreakOnSuccess,            
        [switch]$Starttime            
        )            
            
    #Write-Host "Using MaxBuildsPerDefinition $MaxBuildsPerDefinition"            
    $tfs = [Microsoft.TeamFoundation.Client.TeamFoundationServerFactory]::GetServer($tfsuri)            
    $buildServerType = [Microsoft.TeamFoundation.Build.Client.IBuildServer]            
    $buildServer = $tfs.GetService($buildServerType);            
            
    $buildDetailSpec = $buildServer.CreateBuildDetailSpec($project, $buildDefinition);            
    if ($Starttime)            
    {            
        $buildDetailSpec.QueryOrder = [Microsoft.TeamFoundation.Build.Client.BuildQueryOrder]::StartTimeDescending            
    } else {            
        $buildDetailSpec.QueryOrder = [Microsoft.TeamFoundation.Build.Client.BuildQueryOrder]::FinishTimeDescending            
    }            
    $buildDetailSpec.MaxBuildsPerDefinition = $MaxBuildsPerDefinition            
            
            
    try            
    {            
     $buildQueryResult = $buildServer.QueryBuilds($buildDetailSpec)            
            
        foreach ($build in $buildQueryResult.builds)            
        {                
            # [Microsoft.TeamFoundation.Build.Client.IBuildDetail]$buildDetail = $buildQueryResult.builds[0]             
            $tfsBuildNumber = $build.BuildNumber            
            $shortBuildNumber = $tfsBuildNumber.Substring($tfsBuildNumber.LastIndexOf('_')+1)            
            
    #         #$shortBuildNumber            
    #         $buildQueryResult.failures.length            
    #         $buildQueryResult.builds.length            
    #         $buildQueryResult.builds[0].BuildNumber            
    #         #$buildQueryResult.builds[0].Status            
    #         #$buildQueryResult.builds[0].BuildDefinitionUri.AbsolutePath            
    #         $buildQueryResult.builds[0].StartTime            
    #         $buildQueryResult.builds[0].FinishTime            
              
              $buildAgent = '??'            
              $build.Information | % {            
                $_.nodes | % {            
                    try             
                    {            
                    $buildAgent = $_.children.nodes[2].fields['ReservedAgentName']            
                    }            
                    catch            
                    {            
                    }            
                }             
            }            
                
            New-Object PSObject -Property @{             
                Buildnumber = $build.BuildNumber;             
                Status = $build.Status;            
                CompilationStatus = $build.CompilationStatus;            
                Start = $build.StartTime;            
                End = $build.FinishTime;            
                DropLocation = $build.DropLocation;            
                SourceGetVersion = $build.SourceGetVersion;            
                BuildAgent = $buildAgent            
                }            
            if ($build.Status -eq 'Succeeded' -and ! $DontBreakOnSuccess) { break  }                
                            
        }            
    }            
    catch [Exception]            
    {            
     throw "TFS nicht erreichbar."            
    }            
            
}            
            
            
$a = @(Get-BuildInfo $buildDefinition)            
$a | % {            
    if ($_.Status -eq 'InProgress') { $end = Get-Date } else { $end = $_.End }            
    "{0,-32} {1,18}  {2:ddd} {3} - {4:T} {5,5:0} {6} {7,6} {8}" -f $_.Buildnumber, $_.Status, $_.Start, $_.Start, $End, ($End -$_.Start).Totalminutes, $_.SourceGetVersion, $_.buildAgent, $Droplocation            
}

The result tells me start time, end time, duration, included change set  and drop location.
In the case of failed builds I some further checks on the log files not included here to dispatch the problem as quick as possible to the developer  who caused the problem.




Mittwoch, 27. April 2011

Search for Firefox Bookmarks with given combination of 1 to 3 keywords

When I found that Firefox stores its bookmarks in a sqlite database places.sqlite I wrote the following PowerShell script to search for bookmark by keyword combination.

Here is the code:

ipmo WPK            
            
if (! $sqlitedll)            
{            
    $sqlitedll = [System.Reflection.Assembly]::LoadFrom("C:\Program Files\System.Data.SQLite\bin\System.Data.SQLite.dll")             
}            
            
$ConnectionString = "Data Source=C:\Var\sqlite_ff4\places.sqlite"            
            
$conn = new-object System.Data.SQLite.SQLiteConnection             
$conn.ConnectionString = $ConnectionString             
$conn.Open()             
            
function Invoke-sqlite            
{            
    param( [string]$sql,            
           [System.Data.SQLite.SQLiteConnection]$connection            
           )            
    $cmd = new-object System.Data.SQLite.SQLiteCommand($sql,$connection)            
    $ds = New-Object system.Data.DataSet            
    $da = New-Object System.Data.SQLite.SQLiteDataAdapter($cmd)            
    $da.fill($ds) | Out-Null            
    return $ds.tables[0]            
}            
            
function Show-Bockmarks ($resource) {            
    New-Grid -Rows 2 -Columns 1 -width 1400 -hight 1000  {            
            
        New-StackPanel -Orientation horizontal -column 0 -row 0 -Children {            
             New-Label    '1. Keyword'            
             New-TextBox  -Name tag1 -width 200            
             New-Label    '2. Keyword'            
             New-TextBox  -Name tag2 -width 200            
             New-Label    '3. Keyword'            
             New-TextBox  -Name tag3 -width 200            
             New-Button -Name Search "search" -On_Click {            
            $text1 = $window | Get-ChildControl Tag1            
            $tag1 = $text1.Text            
            $text2 = $window | Get-ChildControl Tag2            
            $tag2 = $text2.Text            
            $text3 = $window | Get-ChildControl Tag3            
            $tag3 = $text3.Text            
            if ( $tag2 -ne '') {            
$clause2 = @"            
    join moz_bookmarks l2 on b.fk = l2.fk and b.id <> l2.id
    join moz_bookmarks t2 on l2.parent = t2.id and  t2.parent = 4 and upper(t2.title) = upper('$tag2')
"@                                    
            } else { $clause2 = '' }                    
            
            if ( $tag3 -ne '') {            
$clause3 = @"            
    join moz_bookmarks l3 on b.fk = l3.fk and b.id <> l3.id
    join moz_bookmarks t3 on l3.parent = t3.id and  t3.parent = 4 and upper(t3.title) = upper('$tag3')
"@                                    
            } else { $clause3 = '' }                    
            
$ff_sql = @"
SELECT b.title, datetime (b.dateAdded / 1000000, 'unixepoch', 'localtime') dateAdded , p.url
    from moz_bookmarks b
    join moz_bookmarks l1 on b.fk = l1.fk and b.id <> l1.id
    join moz_bookmarks t1 on l1.parent = t1.id and  t1.parent = 4 and upper(t1.title) = upper('$tag1')
    join moz_places p  on b.fk = p.id $clause2 $clause3
where b.title is not null and b.type = 1
"@            
            $conn = $resource.conn            
            $window.Title = "$($conn.database) Database Browser"            
            $TableView = $window | Get-ChildControl TableView            
            $TableView.ItemsSource = @(Invoke-sqlite -sql $ff_sql -connection $conn)            
             }             
             New-Button -Name Cancel "Close" -On_Click {$window.Close()}             
        }            
        New-ListView -Column 0 -Row 1 -Name TableView -View {            
           New-GridView -AllowsColumnReorder -Columns {            
               New-GridViewColumn "title"             
               New-GridViewColumn "dateAdded"             
               New-GridViewColumn "url"             
           }            
        }   -On_SelectionChanged {            
             start $this.selecteditem.url            
        }            
        #}            
            
    } -asjob -Resource $resource            
}            
            
Show-Bockmarks -resource @{conn = $conn}            

You have to install System.Data.SQLite
from http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki

I had problems when I checked the install in GAC option. Therefore I installed it without that option and supply the absolute path in my script.

Note: You can't open places.sqlite while Firefox is running. I copied it and coded the path of the copy into my script.

Now I can enter a keyword, press search and the grid fills. Double clicking starts the bookmark in the default browser.

Samstag, 20. November 2010

Eval-Selection in ISE editor, result in editor pane

Here is a little demo showing, who to use ISEs editor pane to display untruncated, unwrapped results.

Run the script in ISE.
Open a new editor.
Tpye dir and press F7:



            
            
function Eval-Selection            
{            
    # Bernd Kriszio 2010-11-21            
    # http://pauerschell.blogspot.com/            
    # twitter @bernd_k            
                
                    
    $editor = $psise.CurrentFile.Editor            
            
    if ($editor.SelectedText)            
    {            
        $inputScript = $editor.SelectedText            
        $editor.InsertText('')            
        $editor.InsertText($inputScript)            
        $result = Invoke-expression $inputScript | out-String            
        $editor.insertText("`r`n")            
        $editor.InsertText($result)            
            
    }            
    else            
    {            
        $inputScript = $editor.Text            
        $EndLine =  $editor.LineCount             
        $EndColumn = $editor.GetLineLength($EndLine) + 1            
        $editor.SetCaretPosition($EndLine, $EndColumn)            
        $result = Invoke-expression $inputScript | out-String            
        $editor.insertText("`r`n")            
        $editor.InsertText($result)            
    }            
}                    
                    
             
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Eval-Selection", {Eval-Selection} ,  'f7')

Edited
After playing a while, I modified the rules for the case, when nothing is selected. Now I use just the single line, the caret is in. Further I added the -width 1000 parameter to make it realy an improvement about usual output-pane results.

And I have a lot of crazy ideas, what to do if the caret is in an empty line. I don't implement them. Next month I wouldn't remember them myself.

Keep things simple

Bernd

This is the version, I added to my profile:

function Eval-Selection            
{            
    # Bernd Kriszio 2010-11-21            
    # http://pauerschell.blogspot.com/            
    # twitter @bernd_k            
                
                    
    $editor = $psise.CurrentFile.Editor            
                
    # if nothing is selected just use the line the caret is in            
    if (!$editor.SelectedText)            
    {            
        $caretLine = $editor.CaretLine            
        $caretLineEnd = $editor.GetLineLength($caretLine) + 1                
                    
        $editor.Select($caretLine, 1, $caretLine, $caretLineEnd)            
    }            
            
    # if something is selected use it.            
    if ($editor.SelectedText)            
    {            
        $inputScript = $editor.SelectedText            
        $editor.InsertText('')            
        $editor.InsertText($inputScript)            
        $result = Invoke-expression $inputScript | out-String -width 1000            
        if ($editor.CaretColumn -ne 1)            
        {            
            $editor.insertText("`r`n")            
        }            
        $editor.InsertText($result)            
            
    }            
}            

Dienstag, 16. November 2010

Determine Start and End of a Selection in PowerShell Ise

Hello, I' m just working on a new inline outpout mode for SQLPSX a very ambious project to access SQL databases based on PowerShell.

There ISEs Output pane doesn't always satisfy my needs, because it truncates and wraps output but you can put your Output into the current or new Editor panes and that works fine. Today I focus on using the current editor pane. 

My goal is to insert the output exactly at the starting of the line below the selection if there is one or at the end of the editor.

First I found it difficult to get the start and end of a selection, but than I found a clever work around. I can even determine, if a selection was done from left to right or from right to left.

But don't use this possibility. It would be really confusing.

Here is my test code, with which I designed (honestly redesigned) the logic to evaluate the output location in SQLPSX (next release).

Have fun studying it. Just put the code below it into an ISE editor, select some text (or nothing) and press F5.

Bernd


function Get-InfoAboutCurentFilesEditor            
{            
    $editor          = $psIse.CurrentFile.Editor            
    $LineCount       = $editor.LineCount            
    $CaretLine       = $editor.CaretLine            
    $caretColumn     = $editor.CaretColumn            
    $CaretLineLength = $editor.GetLineLength($CaretLine)            
    $CaretAtLineEnd  = $caretColumn -eq $CaretLineLength + 1            
    $CaretInLastLine = $CaretLine -eq $LineCount            
    $SelectedText    = $editor.SelectedText            
    $hasSelection    = $SelectedText -ne ''            
                
    if ($hasSelection)            
    {            
        # delete selected text            
        $editor.InsertText('')            
        $StartLine =  $editor.CaretLine            
        $StartColumn = $editor.CaretColumn            
        # reinsert the text            
        $editor.InsertText($SelectedText)            
        $EndLine =  $editor.CaretLine            
        $EndColumn = $editor.CaretColumn            
        # restore the selection            
        $editor.select($StartLine, $StartColumn, $EndLine, $EndColumn)             
        $reverse =  $CaretLine -eq  $StartLine -and $caretColumn -eq $StartColumn            
    }            
    else            
    {            
        $StartLine =  $EndLine = $LineCount            
        $StartColumn = $EndColumn = $editor.GetLineLength($EndLine) + 1            
        $reverse = $False            
    }            
                
    if (  $EndLine -lt  $LineCount)            
    {            
        $outputLine = $EndLine + 1            
        $outputColumn = 1            
        $NeedsNewLine = $False            
    }            
    else            
    {            
        $outputLine = $EndLine            
        $outputColumn = $EndColumn            
        if ($EndColumn -ne 1)            
        {            
            $NeedsNewLine = $True            
            $outputColumn = $editor.GetLineLength($EndLine) + 1            
        }            
        else            
        {            
            $NeedsNewLine = $False            
        }            
    }            
@"
DisplayName:     $($psIse.CurrentFile.DisplayName) 
LineCount:       $LineCount

CaretLine:       $CaretLine
CaretColumn:     $caretColumn
CaretLineLength: $CaretLineLength
CaretAtLineEnd:  $CaretAtLineEnd
CaretInLastLine: $CaretInLastLine

hasSelection:    $hasSelection
reverse:         $reverse

outputLine:      $outputLine
outputColumn:    $outputColumn
NeedsNewLine:    $NeedsNewLine
"@            
}            
            
Get-InfoAboutCurentFilesEditor

Montag, 15. November 2010

New ISE work arounds -- determine start and end of textselection

I just guess that ISE is made by some Trappist monks. One never hears anything about future versions.
At most some closed Change Request at Microsoft Commit.
I get a little tired hoping, they will release anything soon.
If I need something, I'm going to write some dirty workaround.
Current problem: you can select text within the editor from left to right or from right to left ending with the caret at different positions.
Only the holy men didn't publish the API to get the start and the end of the selection. You can query only the caret position.
What I want acchieve, is to be able to insert in the line just below the current selection.
Well the following work around sets the caret to the beginning of the selection.
Put the code into an ise editor select testa and press f5, than repeat it by selecting the tesxt in the oposite direction and press again f5:


$editor = $psise.CurrentFile.Editor            
 $currentselection = $editor.SelectedText            
 if ($currentselection)            
 {            
    $initialCaretLine = $editor.CaretLine            
    $initialCaretColumn = $editor.CaretColumn            
    $editor.InsertText('')            
    $selstartline  = $editor.CaretLine            
    $selstartColumn = $editor.CaretColumn             
    $editor.InsertText($currentselection)            
    $selEndline  = $editor.CaretLine            
    $selEndColumn = $editor.CaretColumn             
    $editor.Select($selstartline, $selstartColumn, $selEndline, $selEndColumn)            
                
    "Selection is ($selstartline, $selstartColumn, $selEndline, $selEndColumn)"            
    "Initial Caret Position ($initialCaretLine, $initialCaretColumn)"            
 }            
            
            
# testa            
# testb            



Hope this really helps

Bernd


Sonntag, 14. November 2010

I can code Bad Influenced style too

I hope there is a better way to do this, but if PowerShell enforces the use of work arounds, I'll use them.
Please, if you find something more elegant, please drop a note.

Well to make SQLPSX one of the most powerfull tools to extract data from SQL-Server or Oracle databases I just want to transform a datarow into a tabular representation.


$datarow | Format-Table -auto

seems a good start, but as described in http://poshoholic.com/2010/11/11/powershell-quick-tip-creating-wide-tables-with-powershell/

you need to pass the result to Out-String -width 10000 or as many characters you want.
Sorry can't say -1 for unlimited. (Perhaps in V3, if we cry load enough?)

Oops not all columns included, lets add -property *

$datarow | Format-Table -auto -property * | Out-String -width 10000

Oops what happens now?  At the end you get some unwanted addition columns:

RowError, RowState, Table, ItemArray,  HasErrors

A problem well described in https://connect.microsoft.com. With no work around supplied.

Go there and vote for it.

And here is the code, that gives me the wanted result. I agree, it is ugly, but its result is fine:


$columns = ''            
            
                            foreach ($i in 0.. ($res[0].Table.columns.count -1))            
                            {            
                                if ($columns) { $columns +=  ', '+ $res[0].Table.Columns[$i].ColumnName }            
                                else { $columns = $res[0].Table.Columns[$i].ColumnName}            
                            }            
            
                            $c = '($res | ft -Property ' + $columns + ' -auto | Out-string -width 10000 -stream ) -replace " *$", ""-replace "\.\.\.$", "" -join "`r`n" '            
                            $text = Invoke-expression $c            

I hope this helps

Bernd