3

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.

3 Answers 3

3

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 '')
Sign up to request clarification or add additional context in comments.

6 Comments

Worked a charm.
@adam, Just realized I made a mistake and added the letter "G" to the list. I corrected the code in the answer, and please correct any code you are using this in.
@adam, FYI: Accidently found a shorter version I had used sometime time ago.
All these answers are wrong. Get-Random -Count ... returns not repeating elements from the input. This is not a truly sequence of a random characters.
@max630, thank you for pointing that out. Updated with a corrected version using a for loop, but seems a little longer and more convoluted than it should be. If I have some inspiration, may update with a more condensed version.
|
1

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:

rangeop

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))

1 Comment

Thanks, this as well as the others work perfectly!
0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.