Discussion:
GUID (Globally Unique Identifier)
(too old to reply)
Ted
2008-09-14 20:03:13 UTC
Permalink
Has anyone created a GUID (Globally Unique Identifier) program that would
be willing to share the code for it?

Thanks,
Ted
Andrew Shimmin
2008-09-15 05:28:56 UTC
Permalink
FUNCKy has one:

f = new FUNCKy()
cGUID = f.createGUID()

Writing one in dBase is not a trivial exercise as the CoCreateGuid() API returns a 128bit integer and the StringFromGUID2() API requires the 128bit integer to be provided as a 128bit integer. I could not get dBase to do that.

regards, andrew
Post by Ted
Has anyone created a GUID (Globally Unique Identifier) program that
would be willing to share the code for it?
Thanks,
Ted
Marc VdB
2008-09-15 08:17:57 UTC
Permalink
Hi Ted,
i found the following in my archive..

HTH, Marc
Post by Ted
Has anyone created a GUID (Globally Unique Identifier) program that
would be willing to share the code for it?
/* mv_GUID.cc

Get GUID from system

Usage : g= new mv_guid()
g.get_guid()
if g.error = 0
? g.c_val
else
? "Error occured"
endif
g.release()

Programmer : Marc VdB
*/

Class mv_GUID of string

extern chandle CoCreateGuid(cptr) ole32

this.c_val = space(38) // holds the string representation
this.string = Replicate(Chr(0),8) // holds the 128-bit integer
this.error = 0 // S_OK = 0

function getLong(nIndex) // get the long(dword) value
local n
n = this.getByte(nIndex) + ;
bitlshift(this.getByte(nIndex + 1), 8) + ;
bitlshift(this.getByte(nIndex + 2), 16) + ;
bitlshift(this.getByte(nIndex + 3), 24)
return n

function release() // cleanup
this.string = ''
this.c_val = ''
release object this
return

function getWord(nIndex) // get the word value
local n
n = this.getByte(nIndex) + ;
bitlshift(this.getByte(nIndex + 1), 8)
return n

function get_guid() // this assumes that the guid starts at pos 0
local zw,buffer // which seems to be the case every time
buffer = this.string
this.error = cocreateguid(buffer)
if this.error # 0
return ''
endif
this.string = buffer
zw="{"+itoh(this.getlong(0),8)+"-"+itoh(this.getword(4),4)+"-"
zw+=itoh(this.getword(6),4)+"-"+itoh(this.getbyte(8),2)+itoh(this.getbyte(9),2)+"-"
for i=10 to 15
zw+=itoh(this.getbyte(i),2)
endfor
zw+="}"
this.c_val = zw
return zw

endclass
Andrew Shimmin
2008-09-15 09:30:40 UTC
Permalink
Marc,

Thanks ...

regards, andrew
Post by Marc VdB
Hi Ted,
i found the following in my archive..
HTH, Marc
Ted
2008-09-16 16:51:09 UTC
Permalink
Hi Marc,

Thank You!
Rich posted a single command GUID generator:
(new oleautoclient("Scriptlet.TypeLib").Guid.left(38))
Do you know which would be most likely to generate unique values over time?

I've got another app that uses numeric Job Numbers. Is there a way to edit
mv_guid.cc to return all numbers?

I played around with it a little by multiplying the ASC() values of each
character of the GUID. Would this return equally unique numbers?

Ted
Post by Marc VdB
Hi Ted,
i found the following in my archive..
HTH, Marc
Post by Ted
Has anyone created a GUID (Globally Unique Identifier) program that
would be willing to share the code for it?
/* mv_GUID.cc
Get GUID from system
Usage : g= new mv_guid()
g.get_guid()
if g.error = 0
? g.c_val
else
? "Error occured"
endif
g.release()
Programmer : Marc VdB
*/
Class mv_GUID of string
extern chandle CoCreateGuid(cptr) ole32
this.c_val = space(38) // holds the string representation
this.string = Replicate(Chr(0),8) // holds the 128-bit integer
this.error = 0 // S_OK = 0
function getLong(nIndex) // get the long(dword) value
local n
n = this.getByte(nIndex) + ;
bitlshift(this.getByte(nIndex + 1), 8) + ;
bitlshift(this.getByte(nIndex + 2), 16) + ;
bitlshift(this.getByte(nIndex + 3), 24)
return n
function release() // cleanup
this.string = ''
this.c_val = ''
release object this
return
function getWord(nIndex) // get the word value
local n
n = this.getByte(nIndex) + ;
bitlshift(this.getByte(nIndex + 1), 8)
return n
function get_guid() // this assumes that the guid starts at pos 0
local zw,buffer // which seems to be the case every time
buffer = this.string
this.error = cocreateguid(buffer)
if this.error # 0
return ''
endif
this.string = buffer
zw="{"+itoh(this.getlong(0),8)+"-"+itoh(this.getword(4),4)+"-"
zw+=itoh(this.getword(6),4)+"-"+itoh(this.getbyte(8),2)+itoh(this.getbyte(9),2)+"-"
for i=10 to 15
zw+=itoh(this.getbyte(i),2)
endfor
zw+="}"
this.c_val = zw
return zw
endclass
Marc VdB
2008-09-17 11:31:51 UTC
Permalink
@ Rich
Ted, I believe the oleautoclient version is just an activeX wrapper for
the DLL calls as Mark posted them.
Yes, i think you are right.

@Ted,
If I'm not mistaken cocreateguid returns an 128 bit interger into the
buffer. Try looking at the value of the buffer. Maybe try removing the
itoh() and dashes from where Mark is creating the variable zw. One of
these may give you what you are looking for.
The buffer holds the 128bit integer in its binary form, but you can't use it
as it is.
Therefor the translation to the GUID. Per definition, a Guid is a hex
representation of the 128 bit integer, together with some "-" to make it
more readable.

{8F08545A-8BE7-41E7-A9FA-36323450D344} is indeed, if you leave out the "-" :

8F08545A8BE741E7A9FA36323450D344

which is about 19*10E37 in decimal notation

To be sure to have a unique number, you have to take all cyphers. It is not
enough to take lets say the last 16 digits, because they could repeat after
a certain time.

However the advantage of that large number is that it is said to be unique
worldwide and more, you can easily use it as a key-value, because it has
always the same length (interesting for an index)

HTH, Marc
Rich - AutoTraker Inc.
2008-09-17 22:05:55 UTC
Permalink
Post by Marc VdB
@ Rich
Ted, I believe the oleautoclient version is just an activeX wrapper for
the DLL calls as Mark posted them.
Yes, i think you are right.
@Ted,
If I'm not mistaken cocreateguid returns an 128 bit interger into the
buffer. Try looking at the value of the buffer. Maybe try removing the
itoh() and dashes from where Mark is creating the variable zw. One of
these may give you what you are looking for.
The buffer holds the 128bit integer in its binary form, but you can't use
it as it is.
Therefor the translation to the GUID. Per definition, a Guid is a hex
representation of the 128 bit integer, together with some "-" to make it
more readable.
8F08545A8BE741E7A9FA36323450D344
which is about 19*10E37 in decimal notation
To be sure to have a unique number, you have to take all cyphers. It is
not enough to take lets say the last 16 digits, because they could repeat
after a certain time.
However the advantage of that large number is that it is said to be unique
worldwide and more, you can easily use it as a key-value, because it has
always the same length (interesting for an index)
HTH, Marc
Maybe something like this would help. If he strips out all the dashes then
converts it to an interger.
This little function will turn it into a string without the scientific
notation.
Rich...

n = HtoI("8F08545A8BE741E7A9FA36323450D344")

? LtoString(n)

function LtoString
parameters n
local all; private m
c = new string(""+n)
if c.lastIndexOf("E") > 0
x = val(c.right(c.length-c.lastIndexOf("E")-1))
m = 'transform( '+n+', "@( '+replicate("9",x+1)+ '" )'
c = &m.
endif
return c
unknown
2008-09-18 12:36:14 UTC
Permalink
On Thu, 18 Sep 2008 09:31:14 +0200 Marc VdB
Sender: Marc VdB <***@web.de>
wrote the following in:
Newsgroup: dbase.programming
Thereby finding out, that imho, you can't trust the transform function
when it comes to that big numbers...
Although you construct the correct macro expression in your function,
the execution of themacro yields "wrong" results...
To see it in action, run the attached prg a few times...
Marc,

I noticed a new addition to the BigMath family :-)

Are you going to mail Ken a copy for inclusion in the next duflp version?


Ivar B. Jessen
Marc VdB
2008-09-18 15:15:03 UTC
Permalink
Hi Ivar,
Post by unknown
I noticed a new addition to the BigMath family :-)
Nothing gets passed your eagle-eyes <g>
Post by unknown
Are you going to mail Ken a copy for inclusion in the next duflp version?
Yep, will do...

CU, Marc
Marc VdB
2008-09-18 15:16:42 UTC
Permalink
Yea, the transform function does have its limitations. Its all I could think
of in just a few minutes using dBASE built in functions.
I like your "complete" translation and I'm going to save the code for future
inclusion in another program I'm working on that needs to add a couple of
128bit intergers.
Are those functions already bundled in a CC?
Yes, they are in the duflp as bigmath.cc
However the bightoi is not yet included there...

CU, Marc
Ted
2008-09-18 18:04:11 UTC
Permalink
Hi Marc, Rich

You guys are incredible.
Using your guid.prg, this number was generated:
331714552188822262129259267790039431444

This is probably a dumb question but...how do you use a number this large as
a numeric key?
dBase fields will only hold a number 20 digits long.
Can it be converted and entered as scientific notation or hexadecimal?
I couldn't get a numeric field to accept either one.
or
since the maximum number of IDs used by the program would be a few million
rather that trillions, could a subset of it be used with a fair amount of
confidence that it would be unique?
All the numbers used will be placed in a table with a distinct index field
so if a duplicate did present itself another number could be generated.

Thank you very much for your help.
Ted
Post by Marc VdB
Yea, the transform function does have its limitations. Its all I could
think of in just a few minutes using dBASE built in functions.
I like your "complete" translation and I'm going to save the code for
future inclusion in another program I'm working on that needs to add a
couple of 128bit intergers.
Are those functions already bundled in a CC?
Yes, they are in the duflp as bigmath.cc
However the bightoi is not yet included there...
CU, Marc
*Lysander*
2008-09-18 18:52:38 UTC
Permalink
Post by Ted
This is probably a dumb question but...how do you use a number this
large as a numeric key?
how about splitting it up into several fields.
You can have a composite primary key built from several fields.
Geoff Wass [dBVIPS]
2008-09-19 04:55:53 UTC
Permalink
In article <***@news-server>, ***@gmail.com
says...
Post by Ted
Hi Marc, Rich
You guys are incredible.
331714552188822262129259267790039431444
This is probably a dumb question but...how do you use a number this large as
a numeric key?
dBase fields will only hold a number 20 digits long.
Can it be converted and entered as scientific notation or hexadecimal?
I couldn't get a numeric field to accept either one.
or
since the maximum number of IDs used by the program would be a few million
rather that trillions, could a subset of it be used with a fair amount of
confidence that it would be unique?
All the numbers used will be placed in a table with a distinct index field
so if a duplicate did present itself another number could be generated.
Thank you very much for your help.
Ted
Ted,

Use it as a string. You avoid any math issues regarding all those
important digits. Generally, unless you are going to do math with a
"number" it should be stored as a character string. Don't worry about
the extra few bytes it might take.
--
Geoff Wass [dBVIPS]
Montréal, Québec, Canada

.|.|.| dBASE info at http://geocities.com/geoff_wass |.|.|.
.|.|.| ---------------------------------------------------------- |.|.|.
.|.|.| IT Consultant http://Geoff_Wass.com |.|.|.
Rich - AutoTraker Inc.
2008-09-19 17:13:50 UTC
Permalink
Since you only need a 20 digits long, why even bother with a GUID
Just generate a number using the datetime with a random numeric at the end.
This should always give you 20 digit interger and it should never repeat
Rich...

random(-1)
? val(""+year(date()) +;
str(month(date()),2,0,"0") +;
str(day(date()),2,0,"0") +;
str(int((seconds() * 100)),7,0,"0") +;
str((random()*100000),5,0,"0"))
Post by Ted
Hi Marc, Rich
You guys are incredible.
331714552188822262129259267790039431444
This is probably a dumb question but...how do you use a number this large
as a numeric key?
dBase fields will only hold a number 20 digits long.
Can it be converted and entered as scientific notation or hexadecimal?
I couldn't get a numeric field to accept either one.
or
since the maximum number of IDs used by the program would be a few million
rather that trillions, could a subset of it be used with a fair amount of
confidence that it would be unique?
All the numbers used will be placed in a table with a distinct index field
so if a duplicate did present itself another number could be generated.
Thank you very much for your help.
Ted
Post by Marc VdB
Yea, the transform function does have its limitations. Its all I could
think of in just a few minutes using dBASE built in functions.
I like your "complete" translation and I'm going to save the code for
future inclusion in another program I'm working on that needs to add a
couple of 128bit intergers.
Are those functions already bundled in a CC?
Yes, they are in the duflp as bigmath.cc
However the bightoi is not yet included there...
CU, Marc
bigMike
2008-09-22 05:57:02 UTC
Permalink
Gee - sounds mighty like my suggestion from 3 days ago :-) ... but only 14
digits and never a repeat. !4 is just fine probably, but 20 might be
better <g>

bigMike
Post by Rich - AutoTraker Inc.
Since you only need a 20 digits long, why even bother with a GUID
Just generate a number using the datetime with a random numeric at the end.
This should always give you 20 digit interger and it should never repeat
Rich...
random(-1)
? val(""+year(date()) +;
str(month(date()),2,0,"0") +;
str(day(date()),2,0,"0") +;
str(int((seconds() * 100)),7,0,"0") +;
str((random()*100000),5,0,"0"))
Post by Ted
Hi Marc, Rich
You guys are incredible.
331714552188822262129259267790039431444
This is probably a dumb question but...how do you use a number this large
as a numeric key?
dBase fields will only hold a number 20 digits long.
Can it be converted and entered as scientific notation or hexadecimal?
I couldn't get a numeric field to accept either one.
or
since the maximum number of IDs used by the program would be a few
million rather that trillions, could a subset of it be used with a fair
amount of confidence that it would be unique?
All the numbers used will be placed in a table with a distinct index
field so if a duplicate did present itself another number could be
generated.
Thank you very much for your help.
Ted
Post by Marc VdB
Yea, the transform function does have its limitations. Its all I could
think of in just a few minutes using dBASE built in functions.
I like your "complete" translation and I'm going to save the code for
future inclusion in another program I'm working on that needs to add a
couple of 128bit intergers.
Are those functions already bundled in a CC?
Yes, they are in the duflp as bigmath.cc
However the bightoi is not yet included there...
CU, Marc
Rich - AutoTraker Inc.
2008-09-22 21:42:53 UTC
Permalink
Yea, with all this playing around he finally said he was limited to 20
digits. There is just no way to stuff a 128bit number into only 20 digits.
Since a GUID is based on the datetime, why not just base the 20 digit number
on datetime. Personally, I gust generate a 20 digit number, check to make
sure it hasn't already been used and I've yet to have a problem.
Ahhh, and I learned more about GUIDs....
Rich...
Post by bigMike
Gee - sounds mighty like my suggestion from 3 days ago :-) ... but only
14 digits and never a repeat. !4 is just fine probably, but 20 might be
better <g>
bigMike
Post by Rich - AutoTraker Inc.
Since you only need a 20 digits long, why even bother with a GUID
Just generate a number using the datetime with a random numeric at the end.
This should always give you 20 digit interger and it should never repeat
Rich...
random(-1)
? val(""+year(date()) +;
str(month(date()),2,0,"0") +;
str(day(date()),2,0,"0") +;
str(int((seconds() * 100)),7,0,"0") +;
str((random()*100000),5,0,"0"))
Post by Ted
Hi Marc, Rich
You guys are incredible.
331714552188822262129259267790039431444
This is probably a dumb question but...how do you use a number this
large as a numeric key?
dBase fields will only hold a number 20 digits long.
Can it be converted and entered as scientific notation or hexadecimal?
I couldn't get a numeric field to accept either one.
or
since the maximum number of IDs used by the program would be a few
million rather that trillions, could a subset of it be used with a fair
amount of confidence that it would be unique?
All the numbers used will be placed in a table with a distinct index
field so if a duplicate did present itself another number could be
generated.
Thank you very much for your help.
Ted
Post by Marc VdB
Yea, the transform function does have its limitations. Its all I could
think of in just a few minutes using dBASE built in functions.
I like your "complete" translation and I'm going to save the code for
future inclusion in another program I'm working on that needs to add a
couple of 128bit intergers.
Are those functions already bundled in a CC?
Yes, they are in the duflp as bigmath.cc
However the bightoi is not yet included there...
CU, Marc
bigMike
2008-09-23 16:45:56 UTC
Permalink
I use an "access" number, which is really a customer number, for searches.
What else would you use the GUID for? I just add 1 to the last used number
when I get a new customer/student and it tells me how many students we have
had. No problems in the last 3 years the program has been running.

bigMike
Post by Rich - AutoTraker Inc.
Yea, with all this playing around he finally said he was limited to 20
digits. There is just no way to stuff a 128bit number into only 20 digits.
Since a GUID is based on the datetime, why not just base the 20 digit
number on datetime. Personally, I gust generate a 20 digit number, check
to make sure it hasn't already been used and I've yet to have a problem.
Ahhh, and I learned more about GUIDs....
Rich...
Post by bigMike
Gee - sounds mighty like my suggestion from 3 days ago :-) ... but only
14 digits and never a repeat. !4 is just fine probably, but 20 might be
better <g>
bigMike
Post by Rich - AutoTraker Inc.
Since you only need a 20 digits long, why even bother with a GUID
Just generate a number using the datetime with a random numeric at the end.
This should always give you 20 digit interger and it should never repeat
Rich...
random(-1)
? val(""+year(date()) +;
str(month(date()),2,0,"0") +;
str(day(date()),2,0,"0") +;
str(int((seconds() * 100)),7,0,"0") +;
str((random()*100000),5,0,"0"))
Post by Ted
Hi Marc, Rich
You guys are incredible.
331714552188822262129259267790039431444
This is probably a dumb question but...how do you use a number this
large as a numeric key?
dBase fields will only hold a number 20 digits long.
Can it be converted and entered as scientific notation or hexadecimal?
I couldn't get a numeric field to accept either one.
or
since the maximum number of IDs used by the program would be a few
million rather that trillions, could a subset of it be used with a fair
amount of confidence that it would be unique?
All the numbers used will be placed in a table with a distinct index
field so if a duplicate did present itself another number could be
generated.
Thank you very much for your help.
Ted
Post by Marc VdB
Yea, the transform function does have its limitations. Its all I
could think of in just a few minutes using dBASE built in functions.
I like your "complete" translation and I'm going to save the code for
future inclusion in another program I'm working on that needs to add
a couple of 128bit intergers.
Are those functions already bundled in a CC?
Yes, they are in the duflp as bigmath.cc
However the bightoi is not yet included there...
CU, Marc
Rich - AutoTraker Inc.
2008-09-23 21:49:22 UTC
Permalink
I do the same for customer, invoice numbers etc.
I do use a randomly generated number for a license plate or VIN if they
don't know the actual numbers when the start an invoice.
Plates can be up to 10 characters and VINs are 17 character. I test for
dupes before using them.
Haven't had a problem in 8 years....
I do however use a GUID like number to identify a computer.
Rich...
Post by bigMike
I use an "access" number, which is really a customer number, for searches.
What else would you use the GUID for? I just add 1 to the last used number
when I get a new customer/student and it tells me how many students we have
had. No problems in the last 3 years the program has been running.
bigMike
Andrew Shimmin
2008-09-28 02:22:32 UTC
Permalink
Rich,
Post by Rich - AutoTraker Inc.
I do however use a GUID like number to identify a computer.
How do you deal with the configuration (system fingerprint) changing slightly. Such things as:

A new CPU is added.
Memory is added/removed.
A new hard drive is added.
A pen drive is inserted.
A NIC is replaced or another NIC added.
A new OS service pack is installed.
The OS is upgraded say from W2K to WXP.
The Netbios name is changed.

How do you know it is the same system?

regards, andrew
Post by Rich - AutoTraker Inc.
I do the same for customer, invoice numbers etc.
I do use a randomly generated number for a license plate or VIN if they
don't know the actual numbers when the start an invoice.
Plates can be up to 10 characters and VINs are 17 character. I test for
dupes before using them.
Haven't had a problem in 8 years....
I do however use a GUID like number to identify a computer.
Rich...
Post by bigMike
I use an "access" number, which is really a customer number, for searches.
What else would you use the GUID for? I just add 1 to the last used number
when I get a new customer/student and it tells me how many students we have
had. No problems in the last 3 years the program has been running.
bigMike
Rich - AutoTraker Inc.
2008-09-28 17:17:05 UTC
Permalink
Hi Andrew,
Its very difficult to do. I've tried different schemes and all need to use a
number based on something that could change.
Even Microsoft's scheme changes if you change enough components.
The CPU serial number is out since some CPUs don't have one or it can be
suppressed.
Memory isn't a good indicator as that can be changed all to easy.
Hard drives can have the same volume serial number on cloned machines and
its far too easy to change.
The harddrive's hardware manufacture's serial number is unique but as you
pointed out, a harddrive can be changed.
Pen drive doesn't really matter unless you want to use it as a dongle where
you can grab the pen drive's hardware serial number and only allow your
software to run if it finds that particular drive.
A NIC has only the MAC address to make it unique but MACs can be cloned or
changed in some models.
And NetBIOS name can be changed way to easy enough.
Service pack doesn't really matter or upgrading a OS if you are using the
right security info (SID).
Probably the most reliable number is the machine portion of the SID to
represent the machine but cloned machines will have the same SID.
There just isn't anything that doesn't change or can't be cloned.
Calculating a serial number figerprint based on the most static information
from numerous sources seems the best way to go but its not an easy chore to
pick the right sources.
I toyed with a scheme to calculate a figerprint and store it in the registry
or hide it on the harddrive and then reuse it for identification but a
simple cloning of the drive negates that idea.
The more sources you use the greater that chance it will be unique but you
also increase the chance a hardware change will change the number.
Somewhere I posted a serialNumbers.cc (maybe binaries) which has all the
different serial number schemes rolled into one. It also has a fingerprint
I'm calculating using some of those numbers.

To really protect my software I've ended up with a dongle which also
contains an allowed user count.
For local network access I just use the IP address of the machines since
that can't be duplicated on a local network and software login/logout
routines. If the count of unique IPs logged into the software at any one
time exceeds the allowed user count, I don't allow them to login to the
software. By periodically getting all the IP addresses of machines on the
network and comparing them to my previous stored logins, I can automatically
logout any machines that have dropped off the network to help prevent failed
logout from crashes. The "control" machine is the one with the dongle.

Hope this helps,
Rich...
Post by Andrew Shimmin
Rich,
Post by Rich - AutoTraker Inc.
I do however use a GUID like number to identify a computer.
How do you deal with the configuration (system fingerprint) changing
A new CPU is added.
Memory is added/removed.
A new hard drive is added.
A pen drive is inserted.
A NIC is replaced or another NIC added.
A new OS service pack is installed.
The OS is upgraded say from W2K to WXP.
The Netbios name is changed.
How do you know it is the same system?
regards, andrew
Post by Rich - AutoTraker Inc.
I do the same for customer, invoice numbers etc.
I do use a randomly generated number for a license plate or VIN if they
don't know the actual numbers when the start an invoice.
Plates can be up to 10 characters and VINs are 17 character. I test for
dupes before using them.
Haven't had a problem in 8 years....
I do however use a GUID like number to identify a computer.
Rich...
Post by bigMike
I use an "access" number, which is really a customer number, for searches.
What else would you use the GUID for? I just add 1 to the last used number
when I get a new customer/student and it tells me how many students we have
had. No problems in the last 3 years the program has been running.
bigMike
Andrew Shimmin
2008-09-30 12:28:45 UTC
Permalink
Rich,

Thanks .. it helped.

I have been using SoftwareKey's Protection Plus and Instant solo products and they protect and manage licences for me very well. However I have hit a showstopper so I was curious about alternatives.

I an in Australia and the Instant Solo eCommerce server is in St.Louis, Mo. It only does USD and I will be hit with a 25% transaction fee by Australain banks to get it back to Australia.

I have US bank accounts but I am no longer interested in dual taxation regimes.

Getting to market is very painful.

regards, andrew
Post by Rich - AutoTraker Inc.
Hi Andrew,
Its very difficult to do. I've tried different schemes and all need to use a
number based on something that could change.
Even Microsoft's scheme changes if you change enough components.
The CPU serial number is out since some CPUs don't have one or it can be
suppressed.
Memory isn't a good indicator as that can be changed all to easy.
Hard drives can have the same volume serial number on cloned machines and
its far too easy to change.
The harddrive's hardware manufacture's serial number is unique but as you
pointed out, a harddrive can be changed.
Pen drive doesn't really matter unless you want to use it as a dongle where
you can grab the pen drive's hardware serial number and only allow your
software to run if it finds that particular drive.
A NIC has only the MAC address to make it unique but MACs can be cloned or
changed in some models.
And NetBIOS name can be changed way to easy enough.
Service pack doesn't really matter or upgrading a OS if you are using the
right security info (SID).
Probably the most reliable number is the machine portion of the SID to
represent the machine but cloned machines will have the same SID.
There just isn't anything that doesn't change or can't be cloned.
Calculating a serial number figerprint based on the most static information
from numerous sources seems the best way to go but its not an easy chore to
pick the right sources.
I toyed with a scheme to calculate a figerprint and store it in the registry
or hide it on the harddrive and then reuse it for identification but a
simple cloning of the drive negates that idea.
The more sources you use the greater that chance it will be unique but you
also increase the chance a hardware change will change the number.
Somewhere I posted a serialNumbers.cc (maybe binaries) which has all the
different serial number schemes rolled into one. It also has a fingerprint
I'm calculating using some of those numbers.
To really protect my software I've ended up with a dongle which also
contains an allowed user count.
For local network access I just use the IP address of the machines since
that can't be duplicated on a local network and software login/logout
routines. If the count of unique IPs logged into the software at any one
time exceeds the allowed user count, I don't allow them to login to the
software. By periodically getting all the IP addresses of machines on the
network and comparing them to my previous stored logins, I can automatically
logout any machines that have dropped off the network to help prevent failed
logout from crashes. The "control" machine is the one with the dongle.
Hope this helps,
Rich...
Post by Andrew Shimmin
Rich,
Post by Rich - AutoTraker Inc.
I do however use a GUID like number to identify a computer.
How do you deal with the configuration (system fingerprint) changing
A new CPU is added.
Memory is added/removed.
A new hard drive is added.
A pen drive is inserted.
A NIC is replaced or another NIC added.
A new OS service pack is installed.
The OS is upgraded say from W2K to WXP.
The Netbios name is changed.
How do you know it is the same system?
regards, andrew
Post by Rich - AutoTraker Inc.
I do the same for customer, invoice numbers etc.
I do use a randomly generated number for a license plate or VIN if they
don't know the actual numbers when the start an invoice.
Plates can be up to 10 characters and VINs are 17 character. I test for
dupes before using them.
Haven't had a problem in 8 years....
I do however use a GUID like number to identify a computer.
Rich...
Post by bigMike
I use an "access" number, which is really a customer number, for searches.
What else would you use the GUID for? I just add 1 to the last used number
when I get a new customer/student and it tells me how many students we have
had. No problems in the last 3 years the program has been running.
bigMike
Rich - AutoTraker Inc.
2008-09-30 14:48:04 UTC
Permalink
I went with a dongle and update it via the web on my own. That way I'm not
dependant on 3rd parties servers. My customers don't seem to mind waiting a
few days for the dongle to be delivered. Then again my software starts in
price at $1500 USD so its not a cheap product and I can afford the $40 for a
rainbow sentry dongle. You can also use a real cheap jump drive as a dongle
if it has a manufacturer's hardware serial number that's accessible. That
manufacturer's hardware serial number can't be hacked or emulated that I
know of.
All software only solutions are made to be hacked but I guess if your
software is inexpensive enough, no one wants to go though the trouble. You
just have to make it as complicated as you can and hope for the best.

You might check out PayPal since they now have a full ability to take credit
cards without your customers needing to me a member. The percentage they
take as the processor is a little high but it works real nice with all
country currencies. I just transfer from my PayPal account to my local bank.
Its like making a deposit to my local bank so I don't get hit with bank
fees. Your Australian banks may not look for a transaction fee either since
it isn't an intra-bank transfer.

Rich...
Post by Andrew Shimmin
Rich,
Thanks .. it helped.
I have been using SoftwareKey's Protection Plus and Instant solo products
and they protect and manage licences for me very well. However I have hit
a showstopper so I was curious about alternatives.
I an in Australia and the Instant Solo eCommerce server is in St.Louis,
Mo. It only does USD and I will be hit with a 25% transaction fee by
Australain banks to get it back to Australia.
I have US bank accounts but I am no longer interested in dual taxation regimes.
Getting to market is very painful.
regards, andrew
Post by Rich - AutoTraker Inc.
Hi Andrew,
Its very difficult to do. I've tried different schemes and all need to
use a number based on something that could change.
Even Microsoft's scheme changes if you change enough components.
The CPU serial number is out since some CPUs don't have one or it can be
suppressed.
Memory isn't a good indicator as that can be changed all to easy.
Hard drives can have the same volume serial number on cloned machines and
its far too easy to change.
The harddrive's hardware manufacture's serial number is unique but as you
pointed out, a harddrive can be changed.
Pen drive doesn't really matter unless you want to use it as a dongle
where you can grab the pen drive's hardware serial number and only allow
your software to run if it finds that particular drive.
A NIC has only the MAC address to make it unique but MACs can be cloned
or changed in some models.
And NetBIOS name can be changed way to easy enough.
Service pack doesn't really matter or upgrading a OS if you are using the
right security info (SID).
Probably the most reliable number is the machine portion of the SID to
represent the machine but cloned machines will have the same SID.
There just isn't anything that doesn't change or can't be cloned.
Calculating a serial number figerprint based on the most static
information from numerous sources seems the best way to go but its not an
easy chore to pick the right sources.
I toyed with a scheme to calculate a figerprint and store it in the
registry or hide it on the harddrive and then reuse it for identification
but a simple cloning of the drive negates that idea.
The more sources you use the greater that chance it will be unique but
you also increase the chance a hardware change will change the number.
Somewhere I posted a serialNumbers.cc (maybe binaries) which has all the
different serial number schemes rolled into one. It also has a
fingerprint I'm calculating using some of those numbers.
To really protect my software I've ended up with a dongle which also
contains an allowed user count.
For local network access I just use the IP address of the machines since
that can't be duplicated on a local network and software login/logout
routines. If the count of unique IPs logged into the software at any one
time exceeds the allowed user count, I don't allow them to login to the
software. By periodically getting all the IP addresses of machines on the
network and comparing them to my previous stored logins, I can
automatically logout any machines that have dropped off the network to
help prevent failed logout from crashes. The "control" machine is the one
with the dongle.
Hope this helps,
Rich...
Post by Andrew Shimmin
Rich,
Post by Rich - AutoTraker Inc.
I do however use a GUID like number to identify a computer.
How do you deal with the configuration (system fingerprint) changing
A new CPU is added.
Memory is added/removed.
A new hard drive is added.
A pen drive is inserted.
A NIC is replaced or another NIC added.
A new OS service pack is installed.
The OS is upgraded say from W2K to WXP.
The Netbios name is changed.
How do you know it is the same system?
regards, andrew
Post by Rich - AutoTraker Inc.
I do the same for customer, invoice numbers etc.
I do use a randomly generated number for a license plate or VIN if they
don't know the actual numbers when the start an invoice.
Plates can be up to 10 characters and VINs are 17 character. I test for
dupes before using them.
Haven't had a problem in 8 years....
I do however use a GUID like number to identify a computer.
Rich...
Post by bigMike
I use an "access" number, which is really a customer number, for searches.
What else would you use the GUID for? I just add 1 to the last used number
when I get a new customer/student and it tells me how many students we have
had. No problems in the last 3 years the program has been running.
bigMike
bigMike
2008-09-28 16:37:38 UTC
Permalink
Your last wasn't sent to me but I like to put my two cents in now and then
:-)

Those items are pretty good ways to track a computer being used but
personally I love to hide one or more files at various locations (registry
or other non-obvious locations) and check for their existence before
allowing a program to be run. Then your adding memory or making other
changes won't matter unless a hard drive is replaced. In that case a new
install could be mandated on the new hard drive and then allow a copying of
the files from the previous hard drive. The new install would place all the
hidden files where they belong and they would have all their data from their
previous install.

bigMike
Post by Andrew Shimmin
Rich,
Post by Rich - AutoTraker Inc.
I do however use a GUID like number to identify a computer.
How do you deal with the configuration (system fingerprint) changing
A new CPU is added.
Memory is added/removed.
A new hard drive is added.
A pen drive is inserted.
A NIC is replaced or another NIC added.
A new OS service pack is installed.
The OS is upgraded say from W2K to WXP.
The Netbios name is changed.
How do you know it is the same system?
regards, andrew
Post by Rich - AutoTraker Inc.
I do the same for customer, invoice numbers etc.
I do use a randomly generated number for a license plate or VIN if they
don't know the actual numbers when the start an invoice.
Plates can be up to 10 characters and VINs are 17 character. I test for
dupes before using them.
Haven't had a problem in 8 years....
I do however use a GUID like number to identify a computer.
Rich...
Post by bigMike
I use an "access" number, which is really a customer number, for searches.
What else would you use the GUID for? I just add 1 to the last used number
when I get a new customer/student and it tells me how many students we have
had. No problems in the last 3 years the program has been running.
bigMike
Rich - AutoTraker Inc.
2008-09-28 18:22:32 UTC
Permalink
Post by bigMike
Your last wasn't sent to me but I like to put my two cents in now and then
:-)
Those items are pretty good ways to track a computer being used but
personally I love to hide one or more files at various locations (registry
or other non-obvious locations) and check for their existence before
allowing a program to be run. Then your adding memory or making other
changes won't matter unless a hard drive is replaced. In that case a new
install could be mandated on the new hard drive and then allow a copying
of the files from the previous hard drive. The new install would place
all the hidden files where they belong and they would have all their data
from their previous install.
bigMike
Your 2 cents are always welcome especially in this economy. LOL
I just don't care for this method as just cloning a hard drive would allow
the program to be used on multiple machines. I've had this happen to me and
done it for other software.
But if you use the hard drive manufacturer's hardware serial number, you can
achieve this without depending on just hiding a file and it will only change
if the hard drive itself is changed since its unique to each hard drive.
Store the number in your hidden file or registry.
Try the below function instead (watch for word wrap).
if NOT getFirstPhysicalDriveSerial() == storedNumber // hard drive has
changed.
Rich...


************************************************************************
function getFirstPhysicalDriveSerial
************************************************************************
//local objLocator,objWMI,oItems,cNum
/* Rich - www.autotraker.com
returns the manufacturers serial number from the first physical disk (HD)
This should always be unique for every hard drive. We are only getting
the
serial number for the first physical disk so we can build our unique ID
with it.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/Win32_PhysicalMedia.asp
Example of output: WD-WMAHL1136753
*/
objLocator = new OleAutoClient("WbemScripting.SWbemLocator")
objWMI=objLocator.ConnectServer(".", "root\cimv2")
objWMI.Security_.ImpersonationLevel=3 // Impersonate
oItems = objWMI.ExecQuery( [select * from Win32_PhysicalMedia where
Tag="\\\\.\\PHYSICALDRIVE0"])
cNum = iif(type("oItems[0].SerialNumber")=="C" and oItems.count => 0,new
string(""+oItems[0].SerialNumber).leftTrim().rightTrim(),"0")

// on some machines (Win 2003?) we may not be returning a hardware serial
number so use the drives signature
if empty(cNum) or cNum = "0"
oItems = objWMI.ExecQuery( [select * from Win32_DiskDrive where
Name="\\\\.\\PHYSICALDRIVE0"])
nNum = iif(type("oItems[0].Signature")=="N" and oItems.count =>
0,oItems[0].Signature,0)
cNum = new string(""+ABS(nNum))
endif

release object objWMI
release object objLocator

// make sure we don't have a NULL serial number
return iif(isBlank(cNum),"0",cNum)
Ted
2008-09-25 20:50:21 UTC
Permalink
Rich,
I send my apologizes to everyone that has helped me with this and feel like
its been a waste of time.

A company wanting to use my app wanted me to use GUIDs to insure there would
never be duplicates but my app has been setup to use numbers.
I thought, if there was a way to use GUIDs to generate numbers limited to
the 20 digits allowed by numeric tables, I wouldn't have to change my whole
app over to a character IDs.

I started this app using AutoIncrement fields but that turned into a
nightmare so I changed to numeric fields. After considering everything, it
sounds like it may be worth while to go ahead and change to character IDs.

Thank you Marc and Rich for the code.

All your help is greatly appreciated.
All the information I've gotten on this issue is a big help and there are
some other areas where it will be needed.

Ted
Post by Rich - AutoTraker Inc.
Since you only need a 20 digits long, why even bother with a GUID
Just generate a number using the datetime with a random numeric at the end.
This should always give you 20 digit interger and it should never repeat
Rich...
random(-1)
? val(""+year(date()) +;
str(month(date()),2,0,"0") +;
str(day(date()),2,0,"0") +;
str(int((seconds() * 100)),7,0,"0") +;
str((random()*100000),5,0,"0"))
Post by Ted
Hi Marc, Rich
You guys are incredible.
331714552188822262129259267790039431444
This is probably a dumb question but...how do you use a number this large
as a numeric key?
dBase fields will only hold a number 20 digits long.
Can it be converted and entered as scientific notation or hexadecimal?
I couldn't get a numeric field to accept either one.
or
since the maximum number of IDs used by the program would be a few
million rather that trillions, could a subset of it be used with a fair
amount of confidence that it would be unique?
All the numbers used will be placed in a table with a distinct index
field so if a duplicate did present itself another number could be
generated.
Thank you very much for your help.
Ted
Post by Marc VdB
Yea, the transform function does have its limitations. Its all I could
think of in just a few minutes using dBASE built in functions.
I like your "complete" translation and I'm going to save the code for
future inclusion in another program I'm working on that needs to add a
couple of 128bit intergers.
Are those functions already bundled in a CC?
Yes, they are in the duflp as bigmath.cc
However the bightoi is not yet included there...
CU, Marc
Rich - AutoTraker Inc.
2008-09-26 13:37:19 UTC
Permalink
Ted,
You know you can take the GUID and Base64 encode it and you'll end up with
22 characters.
Also Microsoft's implementation of a GUID is an entirely random number based
on the date/time as a seed and with a "4" as the 13th character meaning that
its a version 4 GUID.
As in {XXXXXXXX-XXXX-4XXX-XXXX-XXXXXXXXXXXX}
Since its actually a random number, there is no reason you can't use just
part of it. All you'd do is reduce the chance of a duplicate. If you test
each number to make sure its not already used in your table which you should
be doing even if you use the entire GUID, I can't see any real problem. That
way you could say you are using a GUID to keep the customer happy.
No problem about wasting anyone's time. You didn't. Its all a learning
process for everyone and can be fun too.
Rich...
Post by Ted
Rich,
I send my apologizes to everyone that has helped me with this and feel
like its been a waste of time.
A company wanting to use my app wanted me to use GUIDs to insure there
would never be duplicates but my app has been setup to use numbers.
I thought, if there was a way to use GUIDs to generate numbers limited to
the 20 digits allowed by numeric tables, I wouldn't have to change my
whole app over to a character IDs.
I started this app using AutoIncrement fields but that turned into a
nightmare so I changed to numeric fields. After considering everything, it
sounds like it may be worth while to go ahead and change to character IDs.
Thank you Marc and Rich for the code.
All your help is greatly appreciated.
All the information I've gotten on this issue is a big help and there are
some other areas where it will be needed.
Ted
Post by Rich - AutoTraker Inc.
Since you only need a 20 digits long, why even bother with a GUID
Just generate a number using the datetime with a random numeric at the end.
This should always give you 20 digit interger and it should never repeat
Rich...
random(-1)
? val(""+year(date()) +;
str(month(date()),2,0,"0") +;
str(day(date()),2,0,"0") +;
str(int((seconds() * 100)),7,0,"0") +;
str((random()*100000),5,0,"0"))
Post by Ted
Hi Marc, Rich
You guys are incredible.
331714552188822262129259267790039431444
This is probably a dumb question but...how do you use a number this
large as a numeric key?
dBase fields will only hold a number 20 digits long.
Can it be converted and entered as scientific notation or hexadecimal?
I couldn't get a numeric field to accept either one.
or
since the maximum number of IDs used by the program would be a few
million rather that trillions, could a subset of it be used with a fair
amount of confidence that it would be unique?
All the numbers used will be placed in a table with a distinct index
field so if a duplicate did present itself another number could be
generated.
Thank you very much for your help.
Ted
Post by Marc VdB
Yea, the transform function does have its limitations. Its all I could
think of in just a few minutes using dBASE built in functions.
I like your "complete" translation and I'm going to save the code for
future inclusion in another program I'm working on that needs to add a
couple of 128bit intergers.
Are those functions already bundled in a CC?
Yes, they are in the duflp as bigmath.cc
However the bightoi is not yet included there...
CU, Marc
Marc VdB
2008-09-19 13:18:47 UTC
Permalink
Hey Ted,
Post by Ted
331714552188822262129259267790039431444
since the maximum number of IDs used by the program would be a few million
rather that trillions, could a subset of it be used with a fair amount of
confidence that it would be unique?
I can't say, i don't know how the GUID is calculated, o i can't say wether
it is safe to take some digits from the start or at the end...

However, André and Geoff have given you some good food for thought, if you
don't need to do calculations with the number and just use it as a key, the
easisest thing would be to store it as a string. (in this case, the
hex-representation would be best)

If you need the numbers to folloz each other, you can't use the approach
with the GUID.
Search the NG, there has been a thread lately, that handled the problem of
building a unique sequential number...

HTH,
Marc
Rich - AutoTraker Inc.
2008-09-18 13:23:10 UTC
Permalink
Nice Marc...
Yea, the transform function does have its limitations. Its all I could think
of in just a few minutes using dBASE built in functions.
I like your "complete" translation and I'm going to save the code for future
inclusion in another program I'm working on that needs to add a couple of
128bit intergers.
Are those functions already bundled in a CC?
Thanks,
Rich...
Hi Rich
Post by Rich - AutoTraker Inc.
Maybe something like this would help. If he strips out all the dashes then
converts it to an interger.
This little function will turn it into a string without the scientific
notation.
If he really needs a decimal integer, Ted could use your little function.
I wondered about the missing digits (which are replaced with "0" by the
transform function) and wrote a little function that makes the
"complete" translation from hex to decimal.
Thereby finding out, that imho, you can't trust the transform function
when it comes to that big numbers...
Although you construct the correct macro expression in your function,
the execution of themacro yields "wrong" results...
To see it in action, run the attached prg a few times...
CU, MArc
Rich - AutoTraker Inc.
2008-09-17 02:47:31 UTC
Permalink
Ted, I believe the oleautoclient version is just an activeX wrapper for the
DLL calls as Mark posted them.
If I'm not mistaken cocreateguid returns an 128 bit interger into the
buffer. Try looking at the value of the buffer. Maybe try removing the
itoh() and dashes from where Mark is creating the variable zw. One of these
may give you what you are looking for.
Rich...
Post by Ted
Hi Marc,
Thank You!
(new oleautoclient("Scriptlet.TypeLib").Guid.left(38))
Do you know which would be most likely to generate unique values over time?
I've got another app that uses numeric Job Numbers. Is there a way to edit
mv_guid.cc to return all numbers?
I played around with it a little by multiplying the ASC() values of each
character of the GUID. Would this return equally unique numbers?
Ted
Post by Marc VdB
Hi Ted,
i found the following in my archive..
HTH, Marc
Post by Ted
Has anyone created a GUID (Globally Unique Identifier) program that
would be willing to share the code for it?
/* mv_GUID.cc
Get GUID from system
Usage : g= new mv_guid()
g.get_guid()
if g.error = 0
? g.c_val
else
? "Error occured"
endif
g.release()
Programmer : Marc VdB
*/
Class mv_GUID of string
extern chandle CoCreateGuid(cptr) ole32
this.c_val = space(38) // holds the string representation
this.string = Replicate(Chr(0),8) // holds the 128-bit integer
this.error = 0 // S_OK = 0
function getLong(nIndex) // get the long(dword) value
local n
n = this.getByte(nIndex) + ;
bitlshift(this.getByte(nIndex + 1), 8) + ;
bitlshift(this.getByte(nIndex + 2), 16) + ;
bitlshift(this.getByte(nIndex + 3), 24)
return n
function release() // cleanup
this.string = ''
this.c_val = ''
release object this
return
function getWord(nIndex) // get the word value
local n
n = this.getByte(nIndex) + ;
bitlshift(this.getByte(nIndex + 1), 8)
return n
function get_guid() // this assumes that the guid starts at pos 0
local zw,buffer // which seems to be the case every time
buffer = this.string
this.error = cocreateguid(buffer)
if this.error # 0
return ''
endif
this.string = buffer
zw="{"+itoh(this.getlong(0),8)+"-"+itoh(this.getword(4),4)+"-"
zw+=itoh(this.getword(6),4)+"-"+itoh(this.getbyte(8),2)+itoh(this.getbyte(9),2)+"-"
for i=10 to 15
zw+=itoh(this.getbyte(i),2)
endfor
zw+="}"
this.c_val = zw
return zw
endclass
Rich - AutoTraker Inc.
2008-09-15 14:49:41 UTC
Permalink
? (new oleautoclient("Scriptlet.TypeLib").Guid.left(38))

The GUID is actually a unique *pseudo-random* 128-bit indentifier which
means it could theoretically be duplicated if you generate enough of them.
Rich...
Post by Ted
Has anyone created a GUID (Globally Unique Identifier) program that
would be willing to share the code for it?
Thanks,
Ted
Rich - AutoTraker Inc.
2008-09-15 21:04:37 UTC
Permalink
Ok, so there is a 1 in 3.4028236692093846346337460743177e+38 chance of
getting a duplicate if generated all on the same machine.
Post by Rich - AutoTraker Inc.
? (new oleautoclient("Scriptlet.TypeLib").Guid.left(38))
The GUID is actually a unique *pseudo-random* 128-bit indentifier which
means it could theoretically be duplicated if you generate enough of them.
Rich...
Only parts of it are random. It is also based on the MAC address and
the local system clock, so it's pretty hard to get duplicates.
Post by Rich - AutoTraker Inc.
Post by Ted
Has anyone created a GUID (Globally Unique Identifier) program that
would be willing to share the code for it?
Thanks,
Ted
--
/~\ The ASCII
\ / Ribbon Campaign
X Against HTML
/ \ Email!
Remove the ns_ from if replying by e-mail (but keep posts in the
newsgroups if possible).
n***@ns_warrenrogersassociates.com
2008-09-15 17:49:32 UTC
Permalink
Post by Rich - AutoTraker Inc.
? (new oleautoclient("Scriptlet.TypeLib").Guid.left(38))
The GUID is actually a unique *pseudo-random* 128-bit indentifier which
means it could theoretically be duplicated if you generate enough of them.
Rich...
Only parts of it are random. It is also based on the MAC address and
the local system clock, so it's pretty hard to get duplicates.
Post by Rich - AutoTraker Inc.
Post by Ted
Has anyone created a GUID (Globally Unique Identifier) program that
would be willing to share the code for it?
Thanks,
Ted
--
/~\ The ASCII
\ / Ribbon Campaign
X Against HTML
/ \ Email!

Remove the ns_ from if replying by e-mail (but keep posts in the
newsgroups if possible).
bigMike
2008-09-16 11:53:14 UTC
Permalink
This is probably not what you want but I don't know your situation.

When I was in the military (LONG time ago) all electronic messaging had to
be unique so what was used was called a date-time-group (DTG). They would
take the date, and time down to the 100th of a second (you could go farther)
to come up with a unique number.

For instance, a message sent at Sept. 16, 2008 at 07:23:87 would have a DTG
of 09162008072387. Only 14 numbers but they never had duplicates anywhere
worldwide.

I don't know if they still do this today, but this would be a simple form of
unique identifier.

bigMike
Post by Ted
Has anyone created a GUID (Globally Unique Identifier) program that
would be willing to share the code for it?
Thanks,
Ted
Loading...