Reputation: 41
The documentation for the Powershell Get-Random
cmdlet suggests that the seed is the system tick count but, if the following test is performed, the value of $rand1
is not replicated in the output of the for()
loop and so appears to be independent of TickCount
. Why is this so?
# generate a random int32 - should automatically use the tickcount as seed?
$tick1 = ([Environment]::TickCount)
$rand1 = Get-Random
Write-Host $rand1
$tick2 = ([Environment]::TickCount)
# generate seeded randoms with all possible values used to generate $rand1
for ($i = $tick1; $i -le $tick2; $i++) {
$rand2 = Get-Random -SetSeed $i
Write-Host $rand2
}
Upvotes: 4
Views: 3082
Reputation: 25
So, I was curious about this today and now that PowerShell is open source I thought I'd just go look at the source code...
Get-Random does not use [Environment]::TickCount
as the seed. In fact the only time it doesn't use [System.Security.Cryptography.RandomNumberGenerator]::Create()
is when you manually specify a seed.
It has 2 constructors...
internal class PolymorphicRandomNumberGenerator
{
public PolymorphicRandomNumberGenerator()
{
_cryptographicGenerator = RandomNumberGenerator.Create();
_pseudoGenerator = null;
}
internal PolymorphicRandomNumberGenerator(int seed)
{
_cryptographicGenerator = null;
_pseudoGenerator = new Random(seed);
}
...
It only calls the constructor with a seed if SetSeed has a value in the Begin process:
/// <summary>
/// This method implements the BeginProcessing method for get-random command.
/// </summary>
protected override void BeginProcessing()
{
if (SetSeed.HasValue)
{
Generator = new PolymorphicRandomNumberGenerator(SetSeed.Value);
}
...
That would set _pseudoGenerator
using System.Random
Otherwise it only ever calls the public constructor without a seed...which sets _cryptographicGenerator
using System.Security.Cryptography.RandomNumberGenerator
Upvotes: 2
Reputation: 354576
Get-Random
isn't necessarily seeded directly when you use it (certainly not every time you use it), it could be either at process startup, or when you first use it in a session. PRNGs shouldn't be seeded more than once, usually.
Also, as Mathias notes in a comment, it doesn't necessarily use the value of Environment.TickCount
directly. You could use ILSpy to look at the source of the relevant assembly to find out how exactly it's done. I won't do that for you since I'm a contributor to an open-source PowerShell implementation.
Upvotes: 3