Reputation: 33
I'm trying to generate an image based on a 6 char hex code (color code) that's being generated in powershell, but I'm getting an error for System.String when I add the non-digit characters, script is as follows:
# Generate random hex code for the background color
$backgroundColor = "#" + [System.String]::Join("", (Get-Random -Count 6 -InputObject (0..9 + "a".."f") | ForEach-Object { $_ }))
# Generate random hex code for the text color
$textColor = "#" + [System.String]::Join("", (Get-Random -Count 6 -InputObject (0..9 + "a".."f") | ForEach-Object { $_ }))
The error I'm receiving is this:
Cannot convert value "a" to type "System.Int32". Error: "Input string was not in a correct format."
At line:5 char:1
+ $backgroundColor = "#" + [System.String]::Join("", (Get-Random -Count ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastFromStringToInteger
When I remove the "a".."f" portion, it generates a 6 digit hex just fine, but I need to have the alphas as well for the full spectrum, not sure how to include those characters in these snippits.
Any advice would be greatly appreciated.
I've really only tried removing the alphas to test the rest of the script which works fine, but only generates a code with the integers 0-9 which works, but isn't desired.
Upvotes: 3
Views: 858
Reputation: 2368
Corrected Version - repeating characters:
As @max630 pointed out in the comments, when using Get-Random -Count
, Each randomly selected item is returned only once. To solve this, I decided to wrap Get-Random
in a for
loop. There is probably a better way to do this, but at the moment I'm not see it.
$backgroundColor = '#'+ ($(for($i=0; $i -lt 6; $i++){Get-Random -InputObject ([char[]]"0123456789ABCDEF")}) -join '')
$textColor = '#'+ ($(for($i=0; $i -lt 6; $i++){Get-Random -InputObject ([char[]]"0123456789ABCDEF")}) -join '')
or:
$textColor = '#'+ ((1..6 | .{Process{ Get-Random -InputObject ([char[]]"0123456789ABCDEF") }}) -join '')
Alternate method - greatly simplified:
Instead of trying to create random chars, this method simple gets a random number in the correct range and converts it to a color code.
$backgroundColor = '#{0:X6}' -f (Get-Random -Maximum 0x1000000)
$textColor = '#{0:X6}' -f (Get-Random -Maximum 0x1000000)
Yet Another Version - repeating characters:
$textColor = '#{0:X}{1:X}{2:X}{3:X}{4:X}{5:X}' -f (1..6 | ForEach-Object { Get-Random -InputObject ([char[]]"0123456789ABCDEF") })
$textColor = '#{0:X}{1:X}{2:X}{3:X}{4:X}{5:X}' -f (1..6 | .{Process{ Get-Random -InputObject ([char[]]"0123456789ABCDEF") }})
RGB Versions - similar to above alternate method:
The advantage of this method is the flexibility to set either one, or two, of the R, G, or B value(s) to a predetermined value while the other(s) is/are random.
$textColor = '#{0:X2}{1:X2}{2:X2}' -f (Get-Random -Maximum 256), (Get-Random -Maximum 256), (Get-Random -Maximum 256)
$textColor = '#{0:X2}{1:X2}{2:X2}' -f 128, (Get-Random -Maximum 256), 23
$textColor = '#{0:X2}{1:X2}{2:X2}' -f (Get-Random -Maximum 256), 222, 255
$textColor = '#{0:X2}{1:X2}{2:X2}' -f 0, 0, (Get-Random -Maximum 256)
Not sure the value of this RGB version, just wanted to try it and it did work.
$textColor = '#{0:X2}{1:X2}{2:X2}' -f (1..3 | .{Process{(Get-Random -Maximum 256)}})
Old Version - non repeating:
Use [char[]]"0123456789ABCDEF"
instead of 0..9 + "a".."f"
.
$backgroundColor = "#" + [System.String]::Join("", (Get-Random -Count 6 -InputObject ([char[]]"0123456789ABCDEF") | ForEach-Object { $_ }))
$textColor = "#" + [System.String]::Join("", (Get-Random -Count 6 -InputObject ([char[]]"0123456789ABCDEF") | ForEach-Object { $_ }))
Shorter Old Version - non repeating:
$backgroundColor = '#'+ (([char[]]"0123456789ABCDEF" | Get-Random -Count 6) -join '')
$textColor = '#'+ (([char[]]"0123456789ABCDEF" | Get-Random -Count 6) -join '')
Upvotes: 3
Reputation: 27428
To work in powershell 5.1 with the [char[]] cast. I don't think you need the foreach-object.
[int][char]'a'
97
[int][char]'f'
102
"#" + [System.String]::Join("", (Get-Random -Count 6 -InputObject (0..9 +
[char[]](97..102))))
#d1b5a8
Or
"#" + -join (0..9 + [char[]]([char]'a'..[char]'f') | Get-Random -Count 6)
Upvotes: 0
Reputation: 59798
Your code as is will succeed in PowerShell Core, however isn't compatible with Windows PowerShell. Main reason is, the range operator ..
on characters (i.e.: 'a'..'f'
) became a thing in PowerShell v6:
To overcome this you can change your logic a bit so it is compatible with both versions:
$map = [char] '0'..[char] '9' + [char] 'a'..[char] 'f'
'#' + [string]::new((Get-Random -Count 6 -InputObject $map))
Upvotes: 1