switch - multiple variables - powershell

I'm trying to create a script which will work assign different IP ranges depending on the choice, currently I've done something like this:
# Get DHCP Scope Start - first IP to check - End Last IP to check
$X = 0
$Y = 0
$Z = 0
$End = 0
$DHCPServer = "DHCP"
$ScopeID = "10.0.0.0"
switch (Read-Host "Choose device to add: 1 PS3,2 PS4,3 PS4Pro,4 XboxOne,") {
1 {$z = 1 $End = 20}
2 {$z = 30 $End = 50}
3 {$z = 100 $End = 255}
4 {$y = 1 $z = 1 $end = 100}
}
But no matter how I type arguments, PowerShell always return the errors like
Unexpected token $end in expression or statement
Is there a way to fix it?

Adding some semicolons should do the trick. Alternatively, you could use new lines.
# Get DHCP Scope Start - first IP to check - End Last IP to check
$X = 0
$Y = 0
$Z = 0
$End = 0
$DHCPServer = "DHCP"
$ScopeID = "10.0.0.0"
switch (Read-Host "Choose device to add: 1 PS3,2 PS4,3 PS4Pro,4 XboxOne,") {
1 {$z = 1; $End = 20}
2 {$z = 30; $End = 50}
3 {$z = 100; $End = 255}
4 {$y = 1; $z = 1; $end = 100}
}

Related

Converting C++ to PowerShell

I had an assignment for which I need to list the first 100 Prime Numbers in PowerShell Script. So I coded using C++ and try to convert to PowerShell Script. And the output in PowerShell was not what I am expected.
Note: I am new to PowerShell. Just start learning since past 2 days
I tried to understand the PowerShell syntax and convert it
C++:
int i, j, count = 1, b = 0;
for ( i = 3; i > 0; ++i )
{
for ( j = 2; j <= i / 2; ++j )
{
if ( i % j == 0 )
{
b = 1;
break;
}
}
if ( b == 0 )
{
cout << i << endl;
count++;
}
b = 0;
if ( count == 101 )
break;
}
PowerShell:
$i
$j
$count = 0
$prime = 0
for ( $i = 3; $i -lt 0; ++$i )
{
for ( $j = 2; $j -le $i / 2; ++$j )
{
if ( $i % $j -eq 0 )
{
$prime = 1
break
}
}
if ( $prime -eq 0 )
{
Write-Host("$i 'r 'n")
$count++
}
$prime = 0
if ( $count -eq 101 )
{
break
}
}
I expect the result will be first 100 prime numbers from 3 to 547
But I get 3 2 from PowerShell.
Any advice is welcomed. Thank you in advance
You were close.
> is -gt, you used -lt in your script.
$i = 0
$j = 0
$count = 0
$prime = 0
for ($i = 3; $i -gt 0; ++$i) {
for ($j = 2; $j -le $i / 2; ++$j) {
if ($i % $j -eq 0 ) {
$prime = 1
break
}
}
if ($prime -eq 0) {
Write-Output $i
$count++
}
$prime = 0
if ($count -eq 100) {
break
}
}

It there a way in powershell to make a positive number to a negative number whitout using multiplication?

I was wondering if there is a way to make a positive number into a negative number whitout using a multiplication like $b = $a * -1
I'm looking for the most cost sensible way because I'm gonna do this a lot of times in a script.
-edit
At this point I'm using this, but lookes very costly computation wise:
$temp_array = New-Object 'object[,]' $this.row,$this.col
for ($i=0;$i -le $this.row -1 ; $i++) {
for ($j=0;$j -le $this.col -1 ; $j++) {
$digit = $this.data[$i,$j] * -1
$temp_array[$i,$j] = 1 / ( 1 + [math]::exp( $digit ) )
#[math]::Round( $digit ,3)
}
}
$this.data = $temp_array
To unconditionally turn a positive number into its negative equivalent (or, more generally, flip a number's sign), simply use the unary - operator:
PS> $v = 10; -$v
-10
Applied to your case:
$digit = -$this.data[$i,$j]
As an aside: If performance matters, you can speed up your loops by using .., the range operator to create the indices to iterate over:
$temp_array = New-Object 'object[,]' $this.row,$this.col
for ($i in 0..($this.row-1)) {
for ($j in 0..($this.col-1)) {
$digit = - $this.data[$i,$j]
$temp_array[$i,$j] = 1 / ( 1 + [math]::exp( $digit ) )
}
}
$this.data = $temp_array

Minimum bytes required to represent a signed hexadecimal value

Can anyone tell me is there any function in Perl which converts signed decimal to Hex with minimum number of bytes.
ex: -555(dec) => FFFFFDD5(hex) [ converted using $Hex = sprintf( "%X", -555 )]
I want the result to be FDD5 instead of FFFFFDD5.
2 bytes are enough to represent -555.But i am getting 4 bytes conversion.
Please help!
There are two problems with your approach.
It's unparsable.
For example, even if you only know you have two numbers,
Bytes 12 34 56 7816 could refer to 1216 and 34567816.
Bytes 12 34 56 7816 could refer to 123416 and 567816.
Bytes 12 34 56 7816 could refer to 12345616 and 7816.
You could use some external means of identifying the length of the encoded number, but that would nullify some or all of the savings.
It's ambiguous.
For example,
Bytes FD D516 could refer to 6498110 (Bytes 00 00 FD D516 as an int32).
Bytes FD D516 could refer to -55510 (Bytes FF FF FD D516 as an int32).
One solution is to use a length prefix (like UTF-8).
-2^13..2^13-1 2 bytes 00xx xxxx xxxx xxxx
-2^21..2^21-1 3 bytes 01xx xxxx xxxx xxxx xxxx xxxx
-2^29..2^29-1 4 bytes 10xx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
-2^31..2^31-1 5 bytes 1100 0000 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
The optimal scheme will depend on the distribution of your numbers.
The packing/encoding function for the above scheme could be written as follows:
sub pack_vint32 {
my $n = shift;
my $nn = $n >= 0 ? $n : ~$n;
return substr(pack('L>', ($n & 0x3FFF ) | 0x0000 ), -2) if !($nn & ~0x1FFF);
return substr(pack('L>', ($n & 0x3FFFFF ) | 0x400000 ), -3) if !($nn & ~0x1FFFFF);
return substr(pack('L>', ($n & 0x3FFFFFFF) | 0x80000000), -4) if !($nn & ~0x1FFFFFFF);
return "\xC0".pack('L>', $n);
}
And the unpacking/decoding function for the above scheme could be written as follows:
sub unpack_vint32 {
for (shift) {
if (/^[\x00-\x3F]/) {
return if length() < 2;
my $n = unpack('L>', "\x00\x00".substr($_, 0, 2, '')) & 0x3FFF;
$n -= 0x4000 if $n & 0x2000;
return $n;
}
elsif (/^[\x40-\x7F]/) {
return if length() < 3;
my $n = unpack('L>', "\x00".substr($_, 0, 3, '')) & 0x3FFFFF;
$n -= 0x400000 if $n & 0x200000;
return $n;
}
elsif (/^[\x80-\xBF]/) {
return if length() < 4;
my $n = unpack('L>', substr($_, 0, 4, '')) & 0x3FFFFFFF;
$n -= 0x40000000 if $n & 0x20000000;
return $n;
}
elsif (/^\xC0/) {
return if length() < 5;
return unpack('xl>', substr($_, 0, 5, ''));
}
elsif (length() == 0) {
return;
}
}
croak("Bad data");
}
Test:
my $s =
join '',
map { pack_vint32($_) }
map { $_, -$_ }
130, 555, 0x12, 0x345678, 0x12345678;
say length($s);
say sprintf("%v02X", $s);
while ( my ($n) = unpack_vint32($s) ) {
say $n;
}
croak("Bad data") if length($s);
Output:
28
00.82.3F.7E.02.2B.3D.D5.00.12.3F.EE.80.34.56.78.BF.CB.A9.88.92.34.56.78.AD.CB.A9.88
----- ----- ----- ----- ----- ----- ----------- ----------- ----------- -----------
130 | | | | | | | | |
-130 ---+ | | | | | | | |
555 ----------+ | | | | | | |
-555 ---------------+ | | | | | |
18 -----------------------+ | | | | |
-18 ----------------------------+ | | | |
3430008 ---------------------------------+ | | |
-3430008 --------------------------------------------+ | |
305419896 -------------------------------------------------------+ |
-305419896 ------------------------------------------------------------------+
I think the question wants the string (ASCII) representation in hexadecimal that takes the minimum number of bytes in two's complement. I agree with comments and another answer regarding this being ambiguous, but it may be fine for "human" consumption. In this case:
sub min_bytes {
my $n = shift;
my $s = 256; # Fits in one byte
my $i = 1; # Bytes counter
while( 1 ) {
if( $n < 0 && -$n <= $s / 2 ) {
return $i;
}
elsif( $n >= 0 && $n < ($s / 2) - 1 ) {
return $i;
}
$s *= 256;
$i++;
}
}
sub to_hex {
my $n = shift;
my $l = min_bytes($n);
my $h = $n > 0 ? $n : (256 ** $l) + $n;
my $s = '';
for( my $i = 0; $i < $l; $i++ ) {
$s = unpack('H2', pack('C', $n % 256)) . $s;
$n = $n >> 8;
}
return $s;
}
# Let's try a few numbers
my #numbers = (-10, -555, -100000, -100000000, -10000000000, -10000000000000);
for my $n (#numbers) {
my $l = min_bytes($n);
my $h = to_hex($n);
print $n, " takes ", $l, " byte(s) and looks like ", uc $h, "\n";
}
I have tried not to use anything complicated. The bit unpack('H2', pack('C', $n % 256)) converts a single byte decimal number into hex.
This prints:
-10 takes 1 byte(s) and looks like F6
-555 takes 2 byte(s) and looks like FDD5
-100000 takes 3 byte(s) and looks like FE7960
-100000000 takes 4 byte(s) and looks like FA0A1F00
-10000000000 takes 5 byte(s) and looks like FDABF41C00
-10000000000000 takes 6 byte(s) and looks like F6E7B18D6000
The code uses Perl arithmetic, which may give wrong results for bigger numbers than the internal representation's precision.

Autoit - Get Window Class by PID

I want Autoit to press a certain key on a program, but the programs window has no title and changes its class everytime I start it. The only thing that stays consistently the same is the process name.
So my question is simply: How do I get a Windows Class by using only the PID?
Does this help?
#include <Array.au3>
#include <WinAPI.au3>
Opt("WinDetectHiddenText", 1) ;0=don't detect, 1=do detect
Opt("WinSearchChildren", 1) ;0=no, 1=search children also
Opt("WinTextMatchMode", 2) ;1=complete, 2=quick
Opt("WinTitleMatchMode", 2) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase
$a = ProcessGetId('firefox.exe')
For $i = 1 To UBound($a) - 1
ConsoleWrite(ProcessGetWindow($a[$i]) & #CRLF)
Next
Func ProcessGetWindow($PId)
If IsNumber($PId) = 0 Or ProcessExists(ProcessGetName($PId)) = 0 Then
SetError(1)
Else
Local $WinList = WinList()
Local $i = 1
Local $WindowTitle = ""
While $i <= $WinList[0][0] And $WindowTitle = ""
If WinGetProcess($WinList[$i][0], "") = $PId Then
$WindowTitle = $WinList[$i][0]
Else
$i += 1
EndIf
WEnd
Return $WindowTitle
EndIf
EndFunc ;==>ProcessGetWindow
Func ProcessGetId($Process)
If IsString($Process) = 0 Then
SetError(2)
ElseIf ProcessExists($Process) = 0 Then
SetError(1)
Else
Local $PList = ProcessList($Process)
Local $i
Local $PId[$PList[0][0] + 1]
$PId[0] = $PList[0][0]
For $i = 1 To $PList[0][0]
$PId[$i] = $PList[$i][1]
Next
Return $PId
EndIf
EndFunc ;==>ProcessGetId
Func ProcessGetName($PId)
If IsNumber($PId) = 0 Then
SetError(2)
ElseIf $PId > 9999 Then
SetError(1)
Else
Local $PList = ProcessList()
Local $i = 1
Local $ProcessName = ""
While $i <= $PList[0][0] And $ProcessName = ""
If $PList[$i][1] = $PId Then
$ProcessName = $PList[$i][0]
Else
$i = $i + 1
EndIf
WEnd
Return $ProcessName
EndIf
EndFunc ;==>ProcessGetName

How does Perl decide which order to evaluate terms in an expression?

Given the code:
my $x = 1;
$x = $x * 5 * ($x += 5);
I would expect $x to be 180:
$x = $x * 5 * ($x += 5); #$x = 1
$x = $x * 5 * 6; #$x = 6
$x = 30 * 6;
$x = 180;
180;
But instead it is 30; however, if I change the ordering of the terms:
$x = ($x += 5) * $x * 5;
I do get 180. The reason I am confused is that perldoc perlop says very plainly:
A TERM has the highest precedence in Perl. They include variables,
quote and quote-like operators, any expression in parentheses, and any
function whose arguments are parenthesized.
Since ($x += 5) is in parentheses, it should be a term, and therefore executed first, regardless of the ordering of the expression.
The act of typing out the question yielded the answer to me: terms have the highest precedence. That means that the $x in the first chunk of code is evaluated and yields 1, then 5 is evaluated and yields 5, then ($x += 5) is evaluate and yields 6 (with a side-effect of setting $x to 6):
$x = $x * 5 * ($x += 5);
address of $x = $x * 5 * ($x += 5); #evaluate $x as an lvalue
address of $x = 1 * 5 * ($x += 5); #evaluate $x as an rvalue
address of $x = 1 * 5 * ($x += 5); #evaluate 5
address of $x = 1 * 5 * 6; #evaluate ($x += 5), $x is now 6
address of $x = 1 * 5 * 6; #evaluate 1 * 5
address of $x = 5 * 6; #evaluate 1 * 5
address of $x = 30; #evaluate 5 * 6
30; #evaluate address of $x = 30
Similarly, the second example reduces like this:
$x = ($x += 5) * $x * 5;
address of $x = ($x += 5) * $x * 5; #evaluate $x as an lvalue
address of $x = 6 * $x * 5; #evaluate ($x += 5), $x is now 6
address of $x = 6 * 6 * 5; #evaluate $x as an rvalue
address of $x = 6 * 6 * 5; #evaluate 5
address of $x = 36 * 5; #evaluate 6 * 6
address of $x = 180; #evaluate 36 * 5
180; #evaluate $x = 180
Whenever I have confusion about stuff like this I first pull out perldoc perlop, and then if I'm still not sure, or want to see how a particular block of code will get executed, I use B::Deparse:
perl -MO=Deparse,-p,-q,-sC
my $x = 1;
$x = $x * 5 * ($x += 5);
^D
gives:
(my $x = 1);
($x = (($x * 5) * ($x += 5)));
- syntax OK
So substituting values at each stage gives:
($x = (($x * 5) * ($x += 5)));
($x = ((1 * 5) * ($x += 5)));
($x = ((5) * (6))); # and side-effect: $x is now 6
($x = (5 * 6));
($x = (30));
($x = 30);
$x = 30;
So the fact that $x was temporarily set to 6 doesn't really affect anything, because the earlier value (1) was already substituted into the expression, and by the end of the expression it is now 30.
$x by itself is also a TERM. Since it is encountered first (in your first example), it is evaluated first.
The associativity of the * operator is leftward, so the left most term is always evaluated before the right most term. Other operators, such as ** are right associative and would have evaluated ($x += 5) before the rest of the statement.