Google
Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

2011-09-12

Writing Binary Data to Registry

Uh, oh! I found yet another post in drafts from 2007. I do not recall the events but posting it for common good :)

**************************************************************

Yesterday, a friend from work showed me an interesting script he was working on. His script was reading a reg_binary type registry key, modifying its value and was 'attempting' to write it back to registry.

There was an issue with 'writing back to registry'. He was using SetBinaryValue method to write an array, which had modified values, back to registry but vbscript kept on complaining there was a "type mismatch" for this line:

Return = oReg.SetBinaryValue(HKEY_LOCAL_MACHINE, strKeyPath & "\" & subKey, strValueName, arrValues

if he set the arrValues to a static array like this

arrValues=Array(1,2,3,4,5,6)

script worked without any issues.

I took the code and tried to figure out what was wrong with it. I would like to write down a couple of key points for those people who are trying to do something similar.

* When we are talking about Binary data in Registry, we are actually referring to Hexadecimal values, because that's the Registry-speak (1984 anyone?). We can use GetBinaryValue Method of WMI's StdRegProv class. Output is "an array of binary bytes"

* However, binary bytes (hex values) are not meaningful to us, so if we are reading it to, let's say, modify a value, we will probably want to convert it to string using CHR function, which returns a character associated with the specified ANSI character code. I.e. a decimal value between 0..127 (see ascii table).

Also, although registry speaks in hex as far as binary data is concerned, "SetBinaryValue" method does not understand Hex

Consider the following Reg Key/Value (pasting from exported .reg):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\Adobe Acrobat\7.0\FeatureLockDown\cDefaultLaunchURLPerms]"

sSchemePerms2"=hex:76,65,72,73,69,6f,6e,3a,31,7c,73,68,65,6c,6c,3a,33,7c,68,\ 63,70,3a,33,7c,6d,73,2d,68,65,6c,70,3a,33,7c,6d,73,2d,69,74,73,3a,33,7c,6d,\ 73,2d,69,74,73,73,3a,33,7c,69,74,73,3a,33,7c,6d,6b,3a,33,7c,6d,68,74,6d,6c,\ 3a,33,7c,68,65,6c,70,3a,33,7c,64,69,73,6b,3a,33,7c,61,66,70,3a,33,7c,64,69,\ 73,6b,73,3a,33,7c,74,65,6c,6e,65,74,3a,33,7c,73,73,68,3a,33,7c,6a,61,76,61,\ 73,63,72,69,70,74,3a,31,7c,76,62,73,63,72,69,70,74,3a,31,7c,61,63,72,6f,62,\ 61,74,3a,32,7c,6d,61,69,6c,74,6f,3a,32,7c,66,69,6c,65,3a,32,00

If we convert it to string, we get something like

version:1shell:3hcp:3ms-help:3ms-its:3
ms-itss:3its:3mk:3mhtml:3help:3disk:3
afp:3disks:3telnet:3ssh:3javascript:1
vbscript:1acrobat:2mailto:2 file:2

Then, you will need to change
mailto:2
 to
mailto:3
 with vbscript's REPLACE funtion

sNewValue = replace(sOldValue,"mailto:2","mailto:3", 1, -1 , 1)


* SetBinaryValue method is used to write "an array of binary data values" to registry. What is misleading here, and this was the key to solving our issue, is that method actually needs a variant or you will get type mismatch.

So this code works :

'Assumes objRegistry is a valid StdRegProv object.On Error Resume Next
Const HKEY_LOCAL_MACHINE As Long = &H80000002
Dim lRC As Long
Dim sPath As String
Dim uBinary() As Variant
sPath = "SOFTWARE\MyKey"
uBinary = Array(1,2,3,4,5,6,7,8)

lRC = objRegistry.SetBinaryValue(HKEY_LOCAL_MACHINE, sPath, "MyBinaryNamedValue", uBinaryData)

If (lRC = 0) And (Err.Number = 0)  Then   

  'Do something

Else    

  'An error occurred

End If 
* Pay attention to Array function, which returns a Variant containing an array as mentioned in MS documentation:

"A variable that is not declared as an array can still contain an array. Although a Variant variable containing an array is conceptually different from an array variable containing Variant elements, the array elements are accessed in the same way."

2011-09-02

Find your Video Driver version with PowerShell

Well, I wrote this quite sometime ago (Bonus for geeks! Can you tell from the driver version?) but apparently forgot to post it:

Here is one way you can use WMI and PowerShell to get the version of driver you have installed for your video card(s).

PS C:\> gwmi win32_VideoController |select DeviceID,Name,DriverVersion |ft -a

DeviceID         Name                      DriverVersion
--------         ----                      -------------
VideoController1 ATI Radeon HD 5700 Series 8.812.0.0
VideoController2 ATI Radeon HD 5700 Series 8.812.0.0

gwmi is shorthand for get-wmi.
I happen to have two ATI cards. It's not really necessary to select Device ID and name. You can simplify it as follows:

PS C:\> (gwmi win32_VideoController)[0].DriverVersion
8.812.0.0

Why parentheses? Because that way you can access the properties of an object.

Why [0]? Well, b/c it's an array and you know you have the same card. So, it's enough to get driver version of the first card.

How did I know that I have to use Win32_VideoController WMI class? Well, I did not but there is no black magic here, just a bit of guess work and good ol' trial & error:

PS C:\> gwmi -list |?{$_ -match "video"}


   NameSpace: ROOT\cimv2

Name                                Methods              Properties
----                                -------              ----------
CIM_VideoBIOSElement                {}                   {BuildNumber, Caption, CodeSet, Description...}
CIM_VideoController                 {SetPowerState, R... {AcceleratorCapabilities, Availability, CapabilityDescripti...
CIM_PCVideoController               {SetPowerState, R... {AcceleratorCapabilities, Availability, CapabilityDescripti...
Win32_VideoController               {SetPowerState, R... {AcceleratorCapabilities, AdapterCompatibility, AdapterDACT...
CIM_VideoBIOSFeature                {}                   {Caption, CharacteristicDescriptions, Characteristics, Desc...
CIM_VideoBIOSFeatureVideoBIOSEle... {}                   {GroupComponent, PartComponent}
CIM_VideoSetting                    {}                   {Element, Setting}
Win32_VideoSettings                 {}                   {Element, Setting}
CIM_VideoControllerResolution       {}                   {Caption, Description, HorizontalResolution, MaxRefreshRate...
Win32_VideoConfiguration            {}                   {ActualColorResolution, AdapterChipType, AdapterCompatibili...

Guess which Python string find method is faster?

I came across a question on finding which of the two simple string find methods was faster. So, let's play a game. All we are trying to determine is whether a single character ('ch') passed to our function is lowercase or not. Can you guess which method will be fastest out of these four?


# check result of string find function

def is_lower1(ch):

    return (string.find(string.lowercase, ch) !=-1)

## compare the string char to lower case version of it

def is_lower2(ch):   

    return (ch.lower() == ch)

# check string char against all lowercase chars

def is_lower3(ch):

    return (ch in string.lowercase)

# check the char against the lowercase boundries

def is_lower4(ch):

    return 'a' <= ch <= 'z'

Clearly, you can guess the first one will be the sore loser. It is using a string function (string.find) on all the possible lowercase characters (string.lowercase) to check if the passed character matches one. 'Find' Function will return -1, if it cannot find the passed character, that's why result is compared against '-1'. OK, but how about the rest?

is_lower2 function is also using a string function (lower) to lower only the passed character and is then comparing it against its original value. So, basically there are two operations here, but no iteration as in find.

is_lower3 is using 'in' operator against all possible lower case values. So, our string operation here is to list all possible values with (string.lowercase). Is this faster than is_lower2?

is_lower4 is comparing the passed character against the boundaries of lower case letters. There are no iterations or string operations as before but two comparison operations. That should be fast, right? Note that we are using Ascii characters here for comparison. If you print string.lowercase, 'z' is not the last character, it's '\xff' which looks like 'y' with two dots over it on my PC, but be assured that results are not affected any noticeable way.

So, let's timeit :

if __name__ == '__main__':

    import string

    from timeit import Timer

    t = Timer("is_lower1('A')", "from __main__ import is_lower1")

    print "is_lower1 result: %f" % t.timeit()

    t = Timer("is_lower2('A')", "from __main__ import is_lower2")

    print "is_lower2 result: %f" % t.timeit()

    t = Timer("is_lower3('A')", "from __main__ import is_lower3")

    print "is_lower3 result: %f" % t.timeit()

    t = Timer("is_lower4('A')", "from __main__ import is_lower4")

    print "is_lower4 result: %f" % t.timeit()


You probably guessed it but here are results to prove our hunch on which string search method is faster:

is_lower1 result: 0.957694

is_lower2 result: 0.322355

is_lower3 result: 0.256491

is_lower4 result: 0.201267

Did you guess it right?

2008-04-04

Best Programming Language To Learn

I think it was 1988 when I learned my first programming language: Basic. I will never forget the first day when teacher wrote I = I +1 on the screen, and for a second it made no 'matheatical' sense at all :) I liked Basic!

Anyway, most Engineering applications were written in some variation of Fortran then, so that's what I learned in college. I never really liked Fortran. At the time, Computer Science students were learning Pascal, Turbo Pascal was very popular. One of the students who was very good at it gave a couple of us free lessons and that's how I learned it...

Then, when I started to work at 1993, I realized that 'Excel' (version 4, then) was 'the' application that was used for everything around me. Accounting was using it as well as Engineering teams. So, I learned about Macros and later VBA, which made life so much easier! At some point, I jumped from VBA to VisualBasic.

When 'Web Master' became a cool term, I learned about html and ASP. That was a nice combo and helped me do a lot of cool stuff around year 2000.

Later on, when I started to dig into Unix/Linux world, it became clear that Perl would help and together with shell scripting; it did in a big way when automatic tasks in Unix! Although I became proficient with VBScript/WMI scripting, ActivePerl is still my preferred choice in Windows b/c of it's spectacular power with regular expressions (Well VBScript became better with regular expressions and introduced "Dictionaries" (Hashes) yet I don't think it matches Perl).

So, I was thinking what to do next? Java has been out there for quite a while. I was interested in PowerShell but became disillusioned with version 1. AutoIt3 seems interesting but not super easy or intuitive. I keep on hearing about Python (check out this link for some resources) but I am not sure if it adds much on top of Perl...

That's why, I was quite interested when I saw the subject on LifeHacker. There is a lengthy discussion about it. Take a look if you are interested...

2006-11-25

Lisp, Perl, Python

I learned programming in Perl 2 yrs ago when I started supporting an in-house-developed Java/Unix based application. I have seen Python gaining ground since then and got interested in it.

Today, I came across a bunch of very interesting and absorbing articles about several programming languages but mostly focused on lisp, perl and python.

It all started with Paul Graham's "Revenge of the Nerds" article. He is a Lisp expert and to be honest I did not know much about lisp until I read his article. It was a provocative one and he got a lot of responses which he responded with "Re: Revenge of the Nerds".

After you read these two, you would probably want to keep on reading how Python Lovers responded:
Paul Prescod has written a rebuttal to Revenge of the Nerds, On the Relationship between Python and Lisp. Peter Norvig (Google's Director of Research) has also written about this topic in Python for Lisp Programmers.