Strings concatenate out of order

Part of a script has a line to concatenate strings. The strings are concatenating out of order.

Suggestions to fix greatly appreciated.

This…

$uId = "8"
$uName = "Corbin Dallas"
$uCompany = "The 5th Element"
write-host $uId; $uName; $uCompany

…works as expected and produces this (but of course it isn’t a new variable that can be used elsewhere)
8 Corbin Dallas The 5th Element

However I need to add some additional elements to the strings and have been getting unexpected results. So, I’ve pared down what I’m doing to try and isolate the problem and that’s when I found the strings concatenating out of order.

this…

$cmd = $uId, """", $uName, """", $uCompany -join ""
Write-Host $cmd

produces this…
8 Corbin Dallas The 5th Element""

and this…

$cmd2 = $uId + $uName + """" + $uCompany + """"
Write-Host $cmd2

produces the same thing…
8 Corbin Dallas The 5th Element""

This is what things look like at the moment

And here’s the complete code listing

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

function call_browser {

    param ( [string]$uId, [string]$uName, [string]$uCompany )
    $folder = New-Object System.Windows.Forms.FolderBrowserDialog
    $folder.Description = "Select where to save file."
    $dest = $folder.ShowDialog()

    if ($dest -eq "OK" ) 
        { 
        write-host "This path was selected - " """" $($folder.SelectedPath) """" -Separator ""
        write-host $uId; $uName; $uCompany
        $cmd = $uId, """", $uName, """", $uCompany -join ""
        Write-Host $cmd
        $cmd2 = $uId + $uName + """" + $uCompany + """"
        Write-Host $cmd2
        } 
        else 
        { write-host "$dest selected" } 
}

$form = New-Object System.Windows.Forms.Form
$form.Text = 'My Form'
$form.Size = New-Object System.Drawing.Size(300,270)
$form.StartPosition = 'CenterScreen'

$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(75,190)
$okButton.Size = New-Object System.Drawing.Size(75,23)
$okButton.Text = 'Select Path'
$okButton.Add_Click({call_browser( $textBoxID.Text, $textBoxName.Text, $textBoxCompany.Text )})
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)

$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(150,190)
$cancelButton.Size = New-Object System.Drawing.Size(75,23)
$cancelButton.Text = 'Quit'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)

$labelID = New-Object System.Windows.Forms.Label
$labelID.Location = New-Object System.Drawing.Point(10,20)
$labelID.Size = New-Object System.Drawing.Size(280,20)
$labelID.Text = "ID"
$form.Controls.Add($labelID)

$textBoxID = New-Object System.Windows.Forms.TextBox
$textBoxID.Location = New-Object System.Drawing.Point(10,40)
$textBoxID.Size = New-Object System.Drawing.Size(260,20)
$form.Controls.Add($textBoxID)

$labelName = New-Object System.Windows.Forms.Label
$labelName.Location = New-Object System.Drawing.Point(10,70)
$labelName.Size = New-Object System.Drawing.Size(280,20)
$labelName.Text = 'Name:'
$form.Controls.Add($labelName)

$textBoxName = New-Object System.Windows.Forms.TextBox
$textBoxName.Location = New-Object System.Drawing.Point(10,90)
$textBoxName.Size = New-Object System.Drawing.Size(260,20)
$form.Controls.Add($textBoxName)

$labelCompany = New-Object System.Windows.Forms.Label
$labelCompany.Location = New-Object System.Drawing.Point(10,120)
$labelCompany.Size = New-Object System.Drawing.Size(280,20)
$labelCompany.Text = 'Company:'
$form.Controls.Add($labelCompany)

$textBoxCompany = New-Object System.Windows.Forms.TextBox
$textBoxCompany.Location = New-Object System.Drawing.Point(10,140)
$textBoxCompany.Size = New-Object System.Drawing.Size(260,20)
$form.Controls.Add($textBoxCompany)

$form.Add_Shown({$textBoxID.Select()})
$form.Topmost = $true

$form.ShowDialog()

Not entirely clear but I’m guessing you want to output this:

8 Corbin Dallas "The 5th Element"

Why not do this?

$uId = "8"
$uName = "Corbin Dallas"
$uCompany = "The 5th Element"
$newString = "$uID $uName ""$uCompany"""
Write-Output $newString
8 Corbin Dallas "The 5th Element"

If that’s not the expected output please let us know and we can amend it accordingly.

Ultimately the string I want to encode (to be passed to cmd.exe to do the work) is the following with variables expanded.

qrencode -m 8 -o $path\$uName.png "Id=$uId;Name=$uName;Company=$uCompany"

Expanded and typed in the cmd window it would look like
C:\> qrencode -m 8 -o "C:\Corbin Dallas.png" "Id=8;Name=Corbin Dallas;Company=The 5th Element"

All my attempts at producing the above gave such unexpected results that, for the post, I simplified it to the most basic problem, order of string concatenation.

Solve that and then on to the next problem. It works in bash but I need it in Windows.

Regarding what output is expected of Write-Output $cmd and Write-Output $cmd2 that would be
8 " Corbin Dallas " The 5th Element, exactly the order as written in the example.

The problem is the strings are not concatenating in the order they are written in the command.

For what it is worth, I tried your suggestion. Inserted the following after line 18 in the listing

$newString = "$uID $uName ""$uCompany"""
Write-Host $newString

The output still had the strings concatenated out of order. This is what was produced…
8 Corbin Dallas The 5th Element ""

What I’m starting to see is the variables are expanded and concatenated then the text strings concatenated to the end regardless what order the elements appear in the expression concatenating them.

Ok, so what’s happening here is that your function call
call_browser( $textBoxID.Text, $textBoxName.Text, $textBoxCompany.Text )

is actually passing an array of Strings to the first parameter $uId of your function and the other two parameters aren’t populated.

You need to call the function with the following syntax:

$okButton.Add_Click({call_browser $textBoxID.Text $textBoxName.Text $textBoxCompany.Text })

Simple code to compare:

function testOne {

    param ( [string]$uId, [string]$uName, [string]$uCompany )

    Write-Host "`n"
    Write-Host "uId = $uId"
    Write-Host "uName = $uName"
    Write-Host "uCompany = $uCompany"
    Write-Host "$uId ""$uName"" $uCompany"
}

testOne('a','b','c')

function testTwo {

    param ( [string]$uId, [string]$uName, [string]$uCompany )

    Write-Host "`n"
    Write-Host "uId = $uId"
    Write-Host "uName = $uName"
    Write-Host "uCompany = $uCompany"
    Write-Host "$uId ""$uName"" $uCompany"
    
}

testTwo 'a' 'b' 'c'
1 Like

Thank you. THANK YOU.
matt-bloomfield

Your instruction is the solution.