Arend_
(MM club member)
2006-03-02 11:06 AM
ChangeVLKey() - Test Function

I've created a function that will change the Volume License Key on a local Computer. Any input on this function would be apreciated.

Code:

Function ChangeVLKey($VOL_PROD_KEY)
Dim $obj, $objects, $x
;Key is without hyphens (ABCDEFGHIJKLMNOPQRSTUVWXY)
$objects = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf("win32_WindowsProductActivation")
If @Error <> 0
Exit @Error
EndIf
For Each $obj in $objects
$x = $obj.SetProductKey($VOL_PROD_KEY)
$ChangeVLKey = @error
Next
Exit @error
EndFunction



[edit]
Edited per Shawn's & NTDOC's suggestions.
[/edit]


ShawnAdministrator
(KiX Supporter)
2006-03-02 02:50 PM
Re: ChangeVLKey() - Test Function

Looks really good to me - well written. Just one comment in regards to syntax though ... this last line:

Return $ChangeVLKey

You might was well just remove the $ChangeVLKey altogether - the Return statement doesn't take arguments. The only reason that $ChangeVLKey didn't dump its contents to the console is because the script returned before it had a chance to.


Arend_
(MM club member)
2006-03-02 03:00 PM
Re: ChangeVLKey() - Test Function

Ah ok, I thought you'd have to actually put "return" in there for it to return the value (Just mIRC scripting habit I guess ). Thanks

ShawnAdministrator
(KiX Supporter)
2006-03-02 03:04 PM
Re: ChangeVLKey() - Test Function

well hold the phone now - as it stands, your returning the error code here:

$ChangeVLKey = @error

What is it you figure you want to return ? If you want to return the error code, I would make a slight addition to what you have. As well, it is possible to return a string AND an error code (in @ERROR), all depends on what you want to do.


Les
(KiX Master)
2006-03-02 03:11 PM
Re: ChangeVLKey() - Test Function

Exit @Error to return it.

Arend_
(MM club member)
2006-03-02 03:13 PM
Re: ChangeVLKey() - Test Function

It works good, the way you said it should be. I wanted the function to return an error code when the function completes it's task, 0 for success should be handled ok now by "$changeVLKey = @error" as well as an error code when it fails it's task.

for instance:
Code:

$gimme_answer = ChangeVLKey("ABCDEFGHIJKLMNOPQRSTUVWX")
? $gimme_answer



ShawnAdministrator
(KiX Supporter)
2006-03-02 03:17 PM
Re: ChangeVLKey() - Test Function

Ok thats fair - then I would make the following changes ...

Code:

Function ChangeVLKey($VOL_PROD_KEY)
Dim $obj, $objects, $result
;Key is without hyphens (ABCDEFGHIJKLMNOPQRSTUVWXY)

$objects = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf("win32_WindowsProductActivation")
$ChangeVLKey = @error
For Each $obj in $objects
$result = $obj.SetProductKey($VOL_PROD_KEY)
$ChangeVLKey = @error
Next
EndFunction



Basically adding this line after the GetObject:

$ChangeVLKey = @error

This statement kills two birds with one stone

1) It initializes the return code to "something", which it wasn't doing before

2) It will catch a failure on the GetObject and return the code.


Arend_
(MM club member)
2006-03-02 03:17 PM
Re: ChangeVLKey() - Test Function

I could do:
Code:

If @error <> 0
exit @error
Else
$ChangeVLKey = $result
EndIf



Arend_
(MM club member)
2006-03-02 03:20 PM
Re: ChangeVLKey() - Test Function

Aha, yes I agree. That would be the best option.
Edited the first post to reflect your modification.


Benny69
(MM club member)
2006-03-02 03:34 PM
Re: ChangeVLKey() - Test Function

gave your script a test run and i got back a -2147352567
what does that mean?


ShawnAdministrator
(KiX Supporter)
2006-03-02 03:43 PM
Re: ChangeVLKey() - Test Function

Thats the ubiquitous COM message that means "an error has occurred".

Benny69
(MM club member)
2006-03-02 03:47 PM
Re: ChangeVLKey() - Test Function

if its ubiquitous what is the point of checking for an error?

Arend_
(MM club member)
2006-03-02 03:50 PM
Re: ChangeVLKey() - Test Function

Well either it didn't get the object or it couln't be set.
Please keep in mind that it changes Volume License Keys. Not Retail or OEM Keys.


ShawnAdministrator
(KiX Supporter)
2006-03-02 03:55 PM
Re: ChangeVLKey() - Test Function

Well, i would seem that checking for errors did indeed serve its purpose - you got an error (for some reason) and I assume apronk isn't getting one. Problem is - whats the cause of your error?

Benny69
(MM club member)
2006-03-02 03:58 PM
Re: ChangeVLKey() - Test Function

apronk got it right i think because i tried it with a retail lic. if that is the case then can the script be modified to work with retail?

Arend_
(MM club member)
2006-03-02 05:06 PM
Re: ChangeVLKey() - Test Function

That is a good question, but to rule out the first case could you place an "? $ChangeVLKey" after the first "$ChangeVLKey = @error" ?

If that one is 0 then we know for sure that it is because of the Retail version that this function isn't working.


Arend_
(MM club member)
2006-03-02 05:07 PM
Re: ChangeVLKey() - Test Function

I've edited the function in the first post to get better error msg's. Try using it as this:
Code:

$msg = ChangeVLKey("ABCDEFGHIJKLMNOPQRSTUVWXY")
? $msg



If the function exit's with an error it is because of the GetObject. If the function complete's you get the msg that staes wether it was placed or not.


Richard H.Administrator
(KiX Supporter)
2006-03-02 05:15 PM
Re: ChangeVLKey() - Test Function

As the final thing you should
Code:
Exit @ERROR


or
Code:
Exit $ChangeVLKey



So that any error is also preserved in @ERROR when the function returns.

Code:
Function ChangeVLKey($VOL_PROD_KEY)
Dim $obj, $objects, $result
;Key is without hyphens (ABCDEFGHIJKLMNOPQRSTUVWXY)

$objects = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf("win32_WindowsProductActivation")

If Not @ERROR
For Each $obj in $objects
$result = $obj.SetProductKey($VOL_PROD_KEY)
Next
EndIf
$ChangeVLKey = @error
Exit $ChangeVLKey
EndFunction



Benny69
(MM club member)
2006-03-02 05:15 PM
Re: ChangeVLKey() - Test Function

ok, the error is not because it can't get the object.

Benny69
(MM club member)
2006-03-02 05:20 PM
Re: ChangeVLKey() - Test Function

ok, this is what i am running:
Code:

$Return = ChangeVLKey("VP6K44HMRQ86W8YH78DXD2YBQ"); HP1
;$Return = ChangeVLKey("W789C42CGQGPXHRHV4DJCMG4Y"); HP2
;$Return = ChangeVLKey("HPMV67JGMXWMJXRHT3JYGYB4Q"); HP3

? $Return
Get $a

Function ChangeVLKey($VOL_PROD_KEY)
Dim $obj, $objects, $result
;Key is without hyphens (ABCDEFGHIJKLMNOPQRSTUVWXY)

$objects = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf("win32_WindowsProductActivation")
If Not @ERROR
For Each $obj in $objects
$result = $obj.SetProductKey($VOL_PROD_KEY)
$ChangeVLKey = @error
; ? "ActivationRequired: " + $obj.ActivationRequired
; ? "Caption: " + $obj.Caption
; ? "Description: " + $obj.Description
; ? "IsNotificationOn: " + $obj.IsNotificationOn
; ? "ProductID: " + $obj.ProductID
; ? "RemainingEvaluationPeriod: " + $obj.RemainingEvaluationPeriod
; ? "RemainingGracePeriod: " + $obj.RemainingGracePeriod
; ? "ServerName: " + $obj.ServerName
; ? "SettingID: " + $obj.SettingID
Next
EndIf
$ChangeVLKey = @error
Exit $ChangeVLKey
EndFunction



Arend_
(MM club member)
2006-03-02 05:20 PM
Re: ChangeVLKey() - Test Function

Richard: I think I've caught everything safely in my last modification in the first post.

Benny: Then it is because of the Retail version I'm afraid


NTDOCAdministrator
(KiX Master)
2006-03-02 09:19 PM
Re: ChangeVLKey() - Test Function

Well I think if it's going to be a UDF it should be modified a little bit.

As for free tools out there to do this, take a look at RockXP
http://www.rockxp.org/

Download here:
http://korben.othersystem.net/web/softs/RockXP3.exe

Recommended UDF changes

Function ChangeVLKey($VOL_PROD_KEY)
Dim $obj, $objects
;Key is without hyphens (ABCDEFGHIJKLMNOPQRSTUVWXY)
$objects = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf("win32_WindowsProductActivation")
If @ERROR
;ChangeVLKey should not have a value if we got an error
$ChangeVLKey = 0
;Convert the error to readable format
Exit Val('&' + Right(DecToHex(@ERROR), 4))
EndIf
For Each $obj in $objects
$ChangeVLKey = $obj.SetProductKey($VOL_PROD_KEY)
Next
;Assumes we got here okay so exit with no error
Exit 0
EndFunction

 


Arend_
(MM club member)
2006-03-03 08:44 AM
Re: ChangeVLKey() - Test Function

I'll have a look trough this, the use of DecToHex might prove usefull.

Also if you want a good tool that changes any xp license key use this: KeyFinder 1.5b3
Or goto the site for more info: http://www.magicaljellybean.com


NTDOCAdministrator
(KiX Master)
2006-03-03 06:57 PM
Re: ChangeVLKey() - Test Function

Yep, I've tried both those before. Just like the RockXP a bit better myself. Thanks for the links though.

Sealeopard
(KiX Master)
2006-03-05 02:05 PM
Re: ChangeVLKey() - Test Function

Soory to jump in so late. IMHO, the function should return the error code only in EXIT @ERROR and the $ChangeVLKey whatever the SET/GETOBJCT generates (0 in case of success otherwise WMI error code, thus
Code:

Function ChangeVLKey($VOL_PROD_KEY)
Dim $obj, $objects
;Key is without hyphens (ABCDEFGHIJKLMNOPQRSTUVWXY)
$objects = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf("win32_WindowsProductActivation")
If @ERROR
;ChangeVLKey should not have a value if we got an error
$ChangeVLKey = Val('&' + Right(DecToHex(@ERROR), 4))
;Convert the error to readable format
Exit Val('&' + Right(DecToHex(@ERROR), 4))
EndIf
For Each $obj in $objects
$ChangeVLKey = $obj.SetProductKey($VOL_PROD_KEY)
Next
;Assumes we got here okay so exit with no error
Exit @ERROR
EndFunction



NTDOCAdministrator
(KiX Master)
2006-03-06 05:40 AM
Re: ChangeVLKey() - Test Function

I don't agree. If there is ANY error your code will be have invalid / unpredictable results and should quit the UDF then and there not set the UDF value to it.

NTDOCAdministrator
(KiX Master)
2006-03-06 06:28 AM
Re: ChangeVLKey() - Test Function

I can agree that the last Exit @ERROR is probably better

However I don't think setting the Function to the Error is good.

As an example let's suppose that you had a function that read a remote value
from the registry and you expected it to be between 1 and 5
Well as you would rewrite it unless one specifically tested for the Error condition first
(I agree that is probably best coding but we all know that we don't all always do that first)

Example:

Dim $T
$T = ReadRegValue('some computer')
'The value was: ' + $T ?



In this example if say 5 came back the admin would think, cool that's the right value and
proceed from there, but in reality it could easily have been 5 - Access Denied

Setting the Function to 0 after ANY error prohibits any misunderstanding like that.
With the way it is now it would come back blank

If one did better coding one would know, but I still don't see the value in setting it to the error.

Dim $T
$T = ReadRegValue('some computer')
If @ERROR
  'ERROR: There was an error accessing the information: ' + @ERROR + ' - ' + @SERROR ?
Else
  'The value was: ' + $T ?
EndIf


NTDOCAdministrator
(KiX Master)
2006-03-06 07:28 AM
Re: ChangeVLKey() - Test Function

After thinking about it some more, I think setting the value to blank if an error was detected is better than setting it to 0

$ChangeVLKey = 0
Would be better set to
$ChangeVLKey = ""

I'm open to further discussion on this subject as well as WHY you think it should be one way or another.


Richard H.Administrator
(KiX Supporter)
2006-03-06 10:37 AM
Re: ChangeVLKey() - Test Function

A function should always explicitly return a value, even if it is a null value.

When the purpose of a function is to return data then it is reasonable to return either the data on success or a null value on an error - I agree that in this case that returning an error value is unwise.

However, when the function is not expected to return data then it makes sense use the error status as the return value.

Apart from anything else this makes it consistent with the KiXtart built-in functions (e.g. Open() EnumValue()) which use the error state as their exit value.

The code that I posted earlier (repeated here for clarity) does just that:
Code:
Function ChangeVLKey($VOL_PROD_KEY)
Dim $obj, $objects, $result
;Key is without hyphens (ABCDEFGHIJKLMNOPQRSTUVWXY)

$objects = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf("win32_WindowsProductActivation")

If Not @ERROR
For Each $obj in $objects
$result = $obj.SetProductKey($VOL_PROD_KEY)
Next
EndIf
$ChangeVLKey = @error
Exit $ChangeVLKey
EndFunction



Sealeopard
(KiX Master)
2006-03-06 01:50 PM
Re: ChangeVLKey() - Test Function

The problem is that the WMI action will return '0' to indicate success, thus if someone checks for the UDF return but not the @ERROR, it'll evaluate to 'success' even though the action failed.

Richard H.Administrator
(KiX Supporter)
2006-03-06 02:08 PM
Re: ChangeVLKey() - Test Function

Quote:

The problem is that the WMI action will return '0' to indicate success, thus if someone checks for the UDF return but not the @ERROR, it'll evaluate to 'success' even though the action failed




Eh? What do you mean?

Both the exit value and the function value are set to @ERROR wether the error is set by the initial creation of the object or the enumeration.


Glenn BarnasAdministrator
(KiX Supporter)
2006-03-06 02:15 PM
Re: ChangeVLKey() - Test Function

Richard,

I think that those examples are special cases that return EXTENDED information, and return 0 on success, the opposite of what this and many other functions do.

As for the rest of the comments...

If you expect a function to return non-zero data, it should return zero or null in the case of an error, and exit with the error value. This allows
Code:

If Func()
; got a reply - don't care, just do!
Else
; No reply - there's a problem, check @ERROR
EndIf


- or -
Code:

$X = Func()
If $X
; got a reply - OK to process the data
Else
; No reply - there's a problem, check @ERROR
EndIf



Conversely, if a function normally does not return specific data, it is helpful to return status info (which may or may not be the ERROR code). Look at the ExistKey/KeyExist functions. These return Status, one inverted, the other "fixed" to return true. The original one returned "success", which wasn't too helpful when doing simple "If ExistKey()" tests. The newer function returns status, not error info.

Think about your Open example.. the sample in the book looks something like
Code:

If Open(1, 'Filename', 2) = 0


Which is generally what I see in UDFs that use it. However, consider
Code:

$RC = -3
$Ct = 0
While $RC = -3 And $Ct < 10
$RC = Open(1, 'Filename', 2) = 0
$Ct = $Ct + 1
If $RC = -3 Sleep .5 EndIf
Loop


This allows code to be more robust in an environment where many copies of a script may need to access a file. This is a simplified example, but should illustrate the point of checking the status returned.

In this UDF example, and the one Doc is referring to, the UDF returns a specific value - valid data. Even worse, the UDFs return strings of numbers (Strings, because they may have dashes). Returning a pure number as an error is counter-intuitive. It should return a null (empty string) if it usully returns strings, and a zero if it usually returns numbers. If returning zero as a numeric value is valid, then the calling code should ALWAYS check the ERROR macro.

Mode A - Either I get data (non-zero, non-null) or I don't, and if I don't, I check the ERROR macro for more info.

Mode B - I don't expect data, so if I get some, it's a problem and should check the value further, and possibly the @ERROR macro.

One last example.. Consider a UDF that updates some data repository (file, database, registry). It normally returns nothing, indicating success. It performs a "complex" validation process before writing the data, and if it fails validation, it exits with error 87.

Hmm, bad data. What kind of bad data?
The value returned might have the following meanings:
0 = Success
-1 = Out of Bounds - Low
1 = Out of Bounds - High
2 = Incorrect data type (not number)
3 = Null value supplied
4 = System Error

Of course, a return of 4 would indicate that some other error occurred, and would be identified by the exit value in the ERROR macro.

Bottom line, I'm definitly against arbitrarily returning ERROR values as data unless the conditions warrant as outlined above.

Glenn


ShawnAdministrator
(KiX Supporter)
2006-03-06 02:22 PM
Re: ChangeVLKey() - Test Function

Since this UDF can theoretically change multiple instances of a class (its looping through a collection) - if I was coding this UDF - I would probably create it so that it returned the number of instances changed (which may be usefull information) and if an error occurred it would return 0 (zero nothing changed) and then @ERROR would indicate the error.

ShawnAdministrator
(KiX Supporter)
2006-03-06 02:39 PM
Re: ChangeVLKey() - Test Function

eh, strike that idea - this is one of those "WMI returns a collection but it will always be only one item" thingies.

Richard H.Administrator
(KiX Supporter)
2006-03-06 03:12 PM
Re: ChangeVLKey() - Test Function

Quote:

I think that those examples are special cases that return EXTENDED information, and return 0 on success, the opposite of what this and many other functions do.




The example script I gave above returns 0 on success or the error which caused the failure. This is consistent with...

AddKey(), AddPrinterConnection(), AddProgramGroup(), AddProgramItem(), BackupEventLog(), DelKey(), LoadHive(), LogEvent(), SendKeys(), SendMessage(), SetConsole(), ShutDown(), WriteProfileString()

... and others.

Maybe I misunderstand. Wouldn't be the first time


Richard H.Administrator
(KiX Supporter)
2006-03-06 03:20 PM
Re: ChangeVLKey() - Test Function

Ahh I think I see where the confusion lies:
Quote:

In this UDF example, and the one Doc is referring to, the UDF returns a specific value - valid data.




This is not correct. Well, not what you mean anyway

The value of SetProductKey is not a datum as such - it is the same error code that @ERROR is set to:
Quote:

SetProductKey Method of the Win32_WindowsProductActivation Class
The SetProductKey WMI class method updates the system product key for a computer.

This topic uses Managed Object Format (MOF) syntax. For information on using this method see Calling a Method.

uint32 SetProductKey(
string ProductKey
);

Parameters
ProductKey
[in] Unique product key that is licensed for use on the computer. Product keys are alphanumeric strings of 25 characters formatted as follows: xxxxx-xxxxx-xxxxx-xxxxx-xxxxx. The product key must be valid for the media type. Media types include retail, volume-licensing, and OEM.
Return Values
If the method succeeds and the product key is valid, the method returns 0 (zero) and the corresponding product key is updated. Otherwise, the method returns one of the WMI error constants.





Glenn BarnasAdministrator
(KiX Supporter)
2006-03-06 03:25 PM
Re: ChangeVLKey() - Test Function

The issue is not whether the UDF or Function returns error info as much as being consistent. Those functions you reference do not return Data OR the result (status) codes, they ONLY return the result codes. It makes sense for them to return 0 for success and some status on failure.

Imagine the difficulty if ReadProfileString() returned an error code instead of the data it read! How could you tell, unless you ALWAYS checked the ERROR macro.

I was trying to point out that if a function is expected to return data.. maybe "Variable Data" describes it better, that No Data is a better indication of an error (and a reason to check the ERROR macro) than Error Data, which makes you figure out if what you got was Valid Data or Error Data.

Glenn


Richard H.Administrator
(KiX Supporter)
2006-03-06 03:43 PM
Re: ChangeVLKey() - Test Function

Quote:

I was trying to point out that if a function is expected to return data.. maybe "Variable Data" describes it better, that No Data is a better indication of an error (and a reason to check the ERROR macro) than Error Data, which makes you figure out if what you got was Valid Data or Error Data.




Yes, that is exactly what I said in my earlier post. I know it's bad form to quote yourself but:
Quote:

Richy says...
When the purpose of a function is to return data then it is reasonable to return either the data on success or a null value on an error - I agree that in this case that returning an error value is unwise.




However, this function never returns any data. It only ever returns an error state.


ShawnAdministrator
(KiX Supporter)
2006-03-06 03:51 PM
Re: ChangeVLKey() - Test Function

I agree with Richard. So what were agreeing to is that the UDF should remain as is (returning the errorlevel).

Glenn BarnasAdministrator
(KiX Supporter)
2006-03-06 04:08 PM
Re: ChangeVLKey() - Test Function

Quote:

However, this function never returns any data. It only ever returns an error state.




OK - this situation it makes sense.. I guess I didn't understand the function itself, but had recently had issues with other UDFs that returned data when it worked and returned errors when it didn't, and it made it more complex to code around that.

Glenn


Arend_
(MM club member)
2006-03-06 05:07 PM
Re: ChangeVLKey() - Test Function

My whole idea is that it returns 0 when succesfull and an @error code when it isn'succesfull and exits with an @error is it fails somewhere before the function finishes.

NTDOCAdministrator
(KiX Master)
2006-03-06 10:09 PM
Re: ChangeVLKey() - Test Function

Quote:

However, when the function is not expected to return data then it makes sense use the error status as the return value.




Well then I would assume in most cases that it would be 0

If that's the case then why do we really need to set it to anything? If it's not expected to return data then as long as one checks for @ERROR and does not find an error then it should have worked, otherwise regardless of what caused the error it would be captured in the EXIT @ERROR code.

Also in your example by using the NOT operator forces one to use KiXtart 4.50 or newer (which is okay )

But as I view it if no data is expected why would you check for data? That's like expecting to really see the Tooth Fairy when you know it's not there.

Code:
Function ChangeVLKey($VOL_PROD_KEY)
Dim $obj, $objects, $result
;Key is without hyphens (ABCDEFGHIJKLMNOPQRSTUVWXY)
$objects = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf("win32_WindowsProductActivation")
If Not @ERROR
For Each $obj in $objects
$result = $obj.SetProductKey($VOL_PROD_KEY)
Next
EndIf
Exit Val('&' + Right(DecToHex(@ERROR), 4))
EndFunction



Here we simply exit with the ERROR if anything caused one during that processing which we didn't expect data.

I assume from your point of view that well we would see the error and know that something went wrong, but I'm thinking the opposite in that for a function that does not return data, I won't go looking, I'll only look for an ERROR

Regardless of outcome here I think it has been a good discussion on the subject.


ShawnAdministrator
(KiX Supporter)
2006-03-06 10:29 PM
Re: ChangeVLKey() - Test Function

I think the point is that returning the errorlevel is most "kix-like". For example - WriteValue from the manual is:

Code:

$RC=WriteValue("EZReg\Test", "A MultiString variable", "Line 1|Line 2|Line 3 with a || in it|" "REG_MULTI_SZ")
If @ERROR = 0
? "Value written to the registry"
Endif



WriteValue returns the errorlevel and sets the errorlevel. This keeps two types of coders happy - those that like to check @ERROR (you i think) and those that like to check the return value (me for example).

The only pain-in-the-ass thing is when you forget to capture the return value - but we all deal with that day-in day-out. In fact, when I get rc's dumped to the console its a good reminder (to me anyways) about something that should be checked and handled if issues.


NTDOCAdministrator
(KiX Master)
2006-03-06 11:05 PM
Re: ChangeVLKey() - Test Function

Well after a bit more discussion with Glenn on this subject via MSN (Shawn is never on anymore to group chat on this)

I think it boils down a bit more to what is easier to support / use / test and not so much as always mimicking the KiXtart functions which are not 100% consistent either.

As an example in the manual by Ruud

If Exist()

That just doesn't work with 0 for success so he used positive logic for testing.

Returns:
0 File not found
1 File found



So basically in a nutshell (regardless of how KiX internally handles it)

If you can with reasonable certainty know what error you want returned when the function did not do as you wanted then one would force set the value and not use @ERROR
This is on a case by case basis
When the error is fully unexpected then using the @ERROR makes sense.
Setting a positive logic to a RETURN (when data is not excpected) makes more sense than 0 or @ERROR (imho)
ie.. I would set it to 1 to mean it was successful
and set the exit to 0

If I felt the @ERROR might give better feedback than I would use that. Sometimes though setting a specific error gives a better indication of what the problem is.

I apologize for not seemingly being able to clearly define this subject, but I think I have better grasp of how I want to mabye write future UDFs.


Arend_
(MM club member)
2006-03-07 09:06 AM
Re: ChangeVLKey() - Test Function

I think this should cover it all
I removed the Error parsing NTDOC suggested earlier because I want to keep the function as simple as can be. It returns an error code, ppl who use this function should be able to recover the error themselves.

Code:

Function ChangeVLKey($VOL_PROD_KEY)
Dim $obj, $objects, $x
;Key is without hyphens (ABCDEFGHIJKLMNOPQRSTUVWXY)
$objects = GetObject("winmgmts:{impersonationLevel=impersonate}").InstancesOf("win32_WindowsProductActivation")
If @Error <> 0
Exit @Error
EndIf
For Each $obj in $objects
$x = $obj.SetProductKey($VOL_PROD_KEY)
$ChangeVLKey = @error
Next
EndFunction



NTDOCAdministrator
(KiX Master)
2006-03-07 09:10 AM
Re: ChangeVLKey() - Test Function

That's okay, but you're missing an EXIT code when it's finished. All UDF code should have an Exit code and not just Exit either. This has been discussed in the past and shown that on some occassions it can lead to other problems if an Exit with value is not supplied.

Richard H.Administrator
(KiX Supporter)
2006-03-07 09:57 AM
Re: ChangeVLKey() - Test Function

Quote:

If Exist()

That just doesn't work with 0 for success so he used positive logic for testing.

Returns:
0 File not found
1 File found





That is a very bad example to choose

You've assumed that because the function is returning a 1 or a 0 that this is the same as returning an error state.

But is not is it? The 1 or 0 returned by Exist() is data and has nothing to do with the error condition.

This still fits into the simple rule set:
  1. If a function is designed to return data it should return FALSE, 0 or null on an error where that will not prejudice the purpose of the function.
  2. If a function has no explicit return value then it should return an error status where "0" is success.

Now the example you have chosen (Exist) is designed to explicitly return a value, so it matches rule 1. If an error occurs then 0 will be returned, which fits it's purpose and the way it is used in scripts.

AScan is a good example of a function which fits rule 1 but cannot return 0 on an error which is a bit of a design error IMO.


NTDOCAdministrator
(KiX Master)
2006-03-07 10:04 AM
Re: ChangeVLKey() - Test Function

No I did not assume or think it was ERROR it is data and I chose it on purpose to illustrate my point that I think you're still missing the overall larger picture here.

Coding, using a UDF with a positive logic regardless of how KiXtart internals may handle them.

A return and an Error are different and I don't believe I showed otherwise, but then again I seem to have trouble presenting my point here.

I suppose what I'm trying to say is that a UDF does not and can not have a SOLID one rule fits all, but rather can and will change depending on what the UDF code consists of.

I think I agree with your RULE 1 but I don't fully agree with your RULE 2


Richard H.Administrator
(KiX Supporter)
2006-03-07 10:35 AM
Re: ChangeVLKey() - Test Function

I think I understand what you are saying. If I have it right then:
  1. If a function is designed to return data it should return FALSE, 0 or null on an error where that will not prejudice the purpose of the function.
  2. If a function has no explicit return value then it should also return 0 on error and non-zero on success so that it is consistent with rule 1.


I see the argument but it would be pretty counter-intuitive as it is the reverse of every other scripting or programming language I've ever used. I guess that's why it took me a while to see what you were getting at.


Arend_
(MM club member)
2006-03-07 12:16 PM
Re: ChangeVLKey() - Test Function

Quote:

That's okay, but you're missing an EXIT code when it's finished. All UDF code should have an Exit code and not just Exit either. This has been discussed in the past and shown that on some occassions it can lead to other problems if an Exit with value is not supplied.




I don't think that is the case in this scenario, it returns an error code at the end of the function. Thus the function is ended. I do not believe the function can "hang" in any case scenario however I'd like to hear it if you believe otherwise.


NTDOCAdministrator
(KiX Master)
2006-03-07 06:49 PM
Re: ChangeVLKey() - Test Function

Well I'm not saying it would/could/or might hang or error out, just saying that setting the Function to the error is not the same as exiting the function.

A bit of this is theoritical and personal preference. You may run this function a thousand times and have no issues, but you might and having a set exit code (imho) would be a bit better.


Arend_
(MM club member)
2006-03-08 10:55 AM
Re: ChangeVLKey() - Test Function

Ok sounds fair enough, could you give you last suggestion as to how the function should look like in your opinion then ? without converting error codes.

NTDOCAdministrator
(KiX Master)
2006-03-08 08:06 PM
Re: ChangeVLKey() - Test Function

Code:
  For Each $obj in $objects
$x = $obj.SetProductKey($VOL_PROD_KEY)
$ChangeVLKey = @error
Next
Exit 0



As I said though I'm sure the script as you have would probably run good on 99.9% of every run.

Personal opinion is that having the Exit 0 or @ERROR is just a bit better is all.


Arend_
(MM club member)
2006-03-09 08:44 AM
Re: ChangeVLKey() - Test Function

I agree with that, I've changed the first post and the UDF post to reflect your suggestion. Thanks