4

I have a VBScript that looks like this

Randomize
Dim oAPI, oBag
Set oAPI = CreateObject("MOM.ScriptAPI")
Set oBag = oAPI.CreatePropertyBag()
Call oBag.AddValue("Random Performance", Int(Rnd*100)+1)
Call oAPI.Return(oBag)

Now, multiple instances of this script run at the same exact time, so they're probably all being seeded at the same time. As a result, they all give the same random number at a time. Is there possibly a way to make them give different random values at the same time?

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
naman1901
  • 305
  • 4
  • 16
  • You can reduce the probability of getting the same random number across multiple instances by generating the random number 2 or 3 times in the script and add all those random numbers. The chances of getting the same random number will be less in such a case. However, there will always be some probability(although lesser than the current scenario) of getting the same number. – Gurmanjot Singh Jul 26 '17 at 06:55
  • Will try and let you know if it works – naman1901 Jul 26 '17 at 06:59
  • @Kira No this doesn't seem to work. I'm getting the same results as before. – naman1901 Jul 26 '17 at 07:31
  • Okay. Just another suggestion. If you are running this script on multiple machines at the same time, then you can read some numeric data from a LOCALLY stored text/excel file(may be in c:\temp folder on each workstation) and add that value to the random number generated in the script. But it will work only if that text file has different number for different machines. – Gurmanjot Singh Jul 26 '17 at 07:37
  • 1
    The [Randomize reference](https://msdn.microsoft.com/en-us//library/38d7ckek(v=vs.84).aspx) says you can supply a seed – oracle certified professional Jul 26 '17 at 07:50
  • But if I do that, all the script instances have the same seed, again defeating the purpose, as this script will be called from deep inside the codebase, with no way to insert another argument. – naman1901 Jul 26 '17 at 08:24
  • Perhaps you can use the output from `Mid(CreateObject("Scriptlet.TypeLib").Guid, 2, 36)` to generate a new seed? I would hope the guid would be unique per process – oracle certified professional Jul 26 '17 at 09:13
  • @oraclecertifiedprofessional `Randomize` expects a numeric argument, not a string, so using a GUID won't work in and by itself. It might be possible to use the GUID for determining the [process ID](https://stackoverflow.com/a/8438209/1630171) and then use that as input for `Randomize`, though. – Ansgar Wiechers Jul 26 '17 at 09:35

2 Answers2

4

I had some success with this, although I don't know how you're running the scripts I reproduced your problem using start /b

' create a number from the Guid
dim g
g = Mid(CreateObject("Scriptlet.TypeLib").Guid, 2, 36)

dim i, c, s
s = 0
for i = 1 to len(g)
    c = Mid(g, i, 1)
    if not IsNumeric(c) then
        c = Asc(c)  
    end if
    s = CInt(c) + s
next

randomize s

for i = 0 to 5 
    WScript.Echo(WScript.Arguments(0) & " " & g & " " & CInt(Rnd*100))
next

Running it thus

start /b cscript test.vbs //nologo 1
start /b cscript test.vbs //nologo 2
start /b cscript test.vbs //nologo 3
start /b cscript test.vbs //nologo 4
start /b cscript test.vbs //nologo 5

sample output

2D1F39B7-6158-4C77-893B-5C749CF5537F 32 1
2D1F39B7-6158-4C77-893B-5C749CF5537F 13 1
2D1F39B7-6158-4C77-893B-5C749CF5537F 49 1
2D1F39B7-6158-4C77-893B-5C749CF5537F 51 1
2D1F39B7-6158-4C77-893B-5C749CF5537F 84 1
2D1F39B7-6158-4C77-893B-5C749CF5537F 59 3
DC29EDBD-9C63-495B-AFB6-A4A18F65C7F8 35 3
DC29EDBD-9C63-495B-AFB6-A4A18F65C7F8 86 3
DC29EDBD-9C63-495B-AFB6-A4A18F65C7F8 80 3
DC29EDBD-9C63-495B-AFB6-A4A18F65C7F8 3 3
DC29EDBD-9C63-495B-AFB6-A4A18F65C7F8 90 3
DC29EDBD-9C63-495B-AFB6-A4A18F65C7F8 49 4
DC7D2269-436F-4053-B008-F9375BA50F30 34 4
DC7D2269-436F-4053-B008-F9375BA50F30 88 4
DC7D2269-436F-4053-B008-F9375BA50F30 85 4
DC7D2269-436F-4053-B008-F9375BA50F30 60 4
DC7D2269-436F-4053-B008-F9375BA50F30 5 4
DC7D2269-436F-4053-B008-F9375BA50F30 52 2
22F2D6A9-CBF4-48D5-919B-05798FC1BFB1 7 2
22F2D6A9-CBF4-48D5-919B-05798FC1BFB1 89 2
22F2D6A9-CBF4-48D5-919B-05798FC1BFB1 14 2
22F2D6A9-CBF4-48D5-919B-05798FC1BFB1 68 2
22F2D6A9-CBF4-48D5-919B-05798FC1BFB1 89 2
22F2D6A9-CBF4-48D5-919B-05798FC1BFB1 73 5
B13E0D1A-1F93-4387-8CFE-70EEF7FB9B4F 60 5
B13E0D1A-1F93-4387-8CFE-70EEF7FB9B4F 71 5
B13E0D1A-1F93-4387-8CFE-70EEF7FB9B4F 48 5
B13E0D1A-1F93-4387-8CFE-70EEF7FB9B4F 31 5
B13E0D1A-1F93-4387-8CFE-70EEF7FB9B4F 3 5
B13E0D1A-1F93-4387-8CFE-70EEF7FB9B4F 19 5

2

I would use the process ID as the seed for Randomize (for determining the PID see e.g. this answer from Kul-Tigin).

Function GetMyPID
    ppid = 0
    Set sh  = CreateObject("WScript.Shell")
    Set wmi = GetObject("winmgmts://./root/cimv2")

    cmd = "/k " & Mid(CreateObject("Scriptlet.TypeLib").Guid, 2, 36)
    sh.Run "%comspec% " & cmd, 0, False
    WScript.Sleep 100

    qry = "SELECT * FROM Win32_Process WHERE CommandLine LIKE '%" & cmd & "'"
    For Each p In wmi.ExecQuery(qry)
        ppid = p.ParentProcessId
        p.Terminate
        Exit For
    Next

    GetMyPID = ppid
End Function

Randomize GetMyPID
...
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • This looks a little heavy to run. Do you know if this'll affect my script a lot, because its a small simple script that'll run periodically, so I don't want to make it too heavy. – naman1901 Jul 26 '17 at 09:56
  • I've posted the entire script in the question. There is nothing more to it. – naman1901 Jul 26 '17 at 09:59
  • Well, you create and terminate an additional process, so there will be some minor performance impact. If you're concerned about that I suggest you go with the answer [oracle certified professional](https://stackoverflow.com/a/45323168/1630171) provided. – Ansgar Wiechers Jul 26 '17 at 10:04