So I have the following Tk interface and I want to run my clients and servers from it.
The problem is that when I want to run the servers for example, it won't keep them opened and will execute them only once and then close them, like a normal Tcl script.
Can you tell me a way to open and run a script and keep it running without?
package require Tk
wm title . "Image Organizor"
grid [ttk::frame .c -padding "3 3 12 12"] -column 0 -row 0 -sticky nwes
grid [ttk::label .c.serverLabel -text "Servers"] -column 1 -row 1 -sticky e
grid [ttk::label .c.idServerLabel -text "Test Clients"] -column 2 -row 1 - sticky e
grid [ttk::button .c.slbl -text "Server" -command server] -column 1 -row 2 -sticky e
grid [ttk::button .c.idlbl -text "Id Server" -command idServer] -column 1 -row 3 -sticky e
grid [ttk::button .c.c1lbl -text "Client 1" -command client1] -column 2 -row 2 -sticky e
grid [ttk::button .c.c2lbl -text "Client 2" -command client2] -column 2 -row 3 -sticky e
grid [ttk::button .c.c3lbl -text "Client 3" -command client3] -column 3 -row 2 -sticky e
grid [ttk::button .c.c4lbl -text "Client 4" -command client4] -column 3 -row 3 -sticky e
grid [ttk::button .c.configlbl -text "Config" -command config] -column 1 -row 4 -sticky e
foreach w [winfo children .c] {grid configure $w -padx 5 -pady 5}
proc server {} {
source ImageOrganizor/imageOrganizorServer.tcl
}
proc config {} {
exec notepad.exe ImageOrganizor/config.txt
}
You could run the script in a separate thread using thread::create
Or simply execute the script via shell in a separate process, e.g. exec ImageOrganizor/imageOrganizorServer.tcl
Or source your code at root level and execute a proc to start your server, which might in turn either start a thread, execute or fork a new process.
Related
function param-simple {
Param([string]$user_, [string]$host_, [Parameter(position=0,ValueFromRemainingArguments)]$params_)
write-host "[*]user: $user_"
write-host "[*]host: $host_"
for($i=0; $i -lt $params_.count; $i++){ write-host " [$i] $($params_[$i])" }
}
function param-twice {
Param([string]$first_, [string]$second_, [string[]][Parameter(position=0,ValueFromRemainingArguments)]$params1_)
write-host "[-] first: $first_"
write-host "[-] second: $second_"
$params2_ = #()
$params1_ | foreach-object { $params2_ += $_ }
param-simple #params2_ # also not work for #params1_, but work for #args
}
function param-simple works properly if it's called directly, but it will not if it's called through the function param-twice
D:\MyTour\PowerShell01>param-simple -first f -second s -user u -host h 1 2
[*]user: u
[*]host: h
[0] -first
[1] f
[2] -second
[3] s
[4] 1
[5] 2
D:\MyTour\PowerShell01>param-twice -first f -second s -user u -host h 1 2
[-] first: f
[-] second: s
[*]user:
[*]host:
[0] -user
[1] u
[2] -host
[3] h
[4] 1
[5] 2
Would you kindly look into it?
I have script D, C and B :
ScriptD.ps1 ← caller
ScriptC.ps1 ← script path without space
Script B.ps1 ← script path with space
Script B & ScriptC:
Param([int]$Major, [int]$Minor, [String[]]$Output = #())
Write-Host "`n_______________________________________________________________________________________`n"
Write-Host "Script C:`nMajor = $Major ($($Major.GetType()))`nMinor = $Minor ($($Minor.GetType()))`nOutput = $Output (Type: $($Output.GetType()), Length: $($Output.Length))" -ForegroundColor Green
foreach($string in $Output) {
Write-Host "`t- $string"
}
Then I call ScriptC.ps1, Script B.ps1 from ScriptD.ps1:
$cmd1 = "C:\ScriptTest\ScriptC.ps1 -Major 1 -Minor 2 -Output A,B"
powershell -Command $cmd1 #WORK
$cmd2 = "C:\ScriptTest\Script B.ps1 -Major 1 -Minor 2 -Output A,B"
powershell -Command $cmd2 #DON'T WORK
$cmd2 = "'C:\ScriptTest\Script B.ps1' -Major 1 -Minor 2 -Output A,B" #DON'T WORK
$cmd2 = '"C:\ScriptTest\Script B.ps1" -Major 1 -Minor 2 -Output A,B' #DON'T WORK
$cmd2 = $('"{0}"' -f ("C:\ScriptTest\Script B.ps1")) + " -Major 1 -Minor 2 -Output A,B" #DON'T WORK
If there are spaces in the script path or in a variable the call don't work. Adding single quotes will not solve that problem.
What's wrong?
How could I use the -Command parameter with spaces in path and passed variables?
Don't do what you're doing. There is zero reason to invoke PowerShell scripts from another PowerShell script the way you do.
Change
$cmd1 = "C:\ScriptTest\ScriptC.ps1 -Major 1 -Minor 2 -Output A,B"
powershell -Command $cmd1
$cmd2 = "C:\ScriptTest\Script B.ps1 -Major 1 -Minor 2 -Output A,B"
powershell -Command $cmd2
into
C:\ScriptTest\ScriptC.ps1 -Major 1 -Minor 2 -Output A,B
& "C:\ScriptTest\Script B.ps1" -Major 1 -Minor 2 -Output A,B
and everything will work.
Even if you needed to start the other scripts in a separate process you wouldn't use the approach you chose, but something like this:
$paramsc = '-File', 'C:\ScriptTest\ScriptC.ps1',
'-Major', 1, '-Minor', 2, '-Output', 'A,B'
Start-Process 'powershell.exe' -ArgumentList $paramsc
$paramsb = '-File', '"C:\ScriptTest\Script B.ps1"',
'-Major', 1, '-Minor', 2, '-Output', 'A,B'
Start-Process 'powershell.exe' -ArgumentList $paramsb
The ugly nested quotes in the second example are required because the script path contains a space and must thus be in double quotes for the creation of the external process. However, I doubt that you'll be able to pass output variables back to the caller across process boundaries.
$sImageMagickHome = "C:\ImageMagick"
$sImageMagickConv = "$sImageMagickHome\convert.exe"
$sImageMagickArgs = #( '--%',
'-background transparent',
'-fill hsb(0,0,0)',
'-font Arial',
'-pointsize 18',
'-size 18x26',
'-gravity center')
for ( $i = 0x01; $i -le 0x05; $i++ )
{
$y = [char]$i
& $sImageMagickConv $sImageMagickArgs label:$y $sCharsDir\$y.png
#Write-Host $sImageMagickConv $sImageMagickArgs label:$y $sCharsDir\$y.png
}
Using Write-Host I can get an example to copy paste into the command line and I find it does run correctly if I run this single line from the PowerShell prompt:
C:\ImageMagick\convert.exe --% -background transparent -fill hsb(0,0,0) -font Arial -pointsize 18 -size 18x26 -gravity center label:☺ C:\Users\erics_000\Desktop\Output\Chars\☺.png
Using the call operator '&' from inside the script does not work at all however and leads to some error messages:
convert.exe: UnableToOpenBlob `--%': No such file or directory # error/blob.c/OpenBlob/2697.
convert.exe: NoDecodeDelegateForThisImageFormat `' # error/constitute.c/ReadImage/501.
convert.exe: UnrecognizedOption `-background transparent' # error/convert.c/ConvertImageCommand/858.
The article I have been reading is:
http://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx
Thank you...
The following script works for me:
$sImageMagickHome = "C:\dev\im"
$sImageMagickConv = "$sImageMagickHome\convert.exe"
$sImageMagickArgs = #('-background', 'transparent',
'-fill', 'hsb(0,0,0)',
'-font', 'Arial',
'-pointsize', '18',
'-size', '18x26',
'-gravity', 'center')
for ( $i = 65; $i -le 67; $i++ )
{
$y = [char]$i
& $sImageMagickConv $sImageMagickArgs label:$y c:\dev\$y.bmp
}
Note that you cannot just Write-Host the arguments and try running it from command line, Powershell does special processing for & operator (adds quotes where needed), which it does not when you pass same arguments to Write-Host.
You'd probably want to install PSCX and play around with echoargs utility bundled with it to gain better understanding of how arguments are passed.
I am extremely new to PowerShell tool making so forgive my ignorance. I imported the WPK module and am trying to create a box with multiple fields. One of those fields is a password field but it shows the password as it's being typed. I am unsure of how to make it so that while typing the text is hidden.
New-TextBlock -Text "Database Login Name" `
-Row 2 -Column 0 -VerticalAlignment Center -Margin 5
New-TextBox -Name DbLoginId `
-Row 2 -Column 1 -Margin 4
New-TextBlock -Text "Db Login Password" `
-Row 3 -Column 0 -VerticalAlignment Center -Margin 5
New-TextBox -Name DbLoginPassword `
-Row 3 -Column 1 -Margin 4
Just a heads up, I am not a programmer what so ever. I am a Database Administrator but I have been thrown into this development project so I am literally learning on the fly right about now.
Change your password TextBox to a PasswordBox.
New-PasswordBox -Name DbLoginPassword `
-Row 3 -Column 1 -Margin 4
In an example script, I want to execute one block of code if my variable matches 1, another one if it matches 2, 3, 5, or 8, and a different block for 4, 6, or 7.
I'd like to do something like this:
switch($x)
{
1 {'Condition 1'}
2 -or 3 -or -5 -or 8 {'Condition 2'}
4 -or 6 -or 7 {'Condition 3'}
}
But this doesn't work. Is there a way to do this sort of work with switch, without having to spell out all 8 options individually, or are multiple if statements the only way to go?
Another option, if you want to treat the values as numbers instead of strings:
switch ($x)
{
1 {'Condition 1'}
{$_ -in 2,3,5,8} {'Condition 2'}
{$_ -in 4,6,7} {'Condition 3'}
}
You can use the -Regex option and do something like this:
switch -Regex ($x)
{
'1' {'Condition 1'}
'[2358]' {'Condition 2'}
'[467]' {'Condition 3'}
}