Tuesday, December 02, 2008

Test Automation Useful References

XUnit Test Patterns - Refactoring Test Code

Sunday, November 23, 2008

UEUO free webhosting have file length limit

I was playing around with www.ueuo.com 's free web hosting solution and it seems like they have file length limit? I tried uploading a file with 39 characters and I can't understand why it is not going through. I tried FTP and web interface with the same results. I then changed the length of file name to 35 and everything was fine. Go figure!

~ts.

COM hooking research

This post is gonna be a work in progress. What I am trying to embark on is the possibility of inserting hooks to a running COM server to perform automated testing. I have seen applications tried to do this, like TestPartner, but it is crashing my application under test. Summary of available tools that may have a working COM server hooks: TestPartner  - they have ComSpy but this is crashing my application under test. COMslicer - from the help file. COMslicer is a utility that displays information about COM/DCOM components’ activity. It reports all methods and properties called by a client of a COM component and shows values for input/output parameters. COMslicer also reports creation and destroying of COM objects as well as raising events by COM objects. It keeps track of reference counting and interfaces queried by a client. COMslicer works on Windows 98/Me/ NT4/2K. But it seems to me that the development of this tools has halted. A quick visit to their website does not event mention about COMslicer software, rather it shows topics about food stuff. I tried installing the software in Vista and it chokes up, so this one is no good for me as my target applications need to run in Vista and Windows Server 2008

Below are some of the information I have scoured over in the internet that may help in COM spying. DLL injection, Detours and Deviare looks interesting.
Component Object Model (link ) - This wikipedia article discussed the history of COM and some high level details.
GUI Hooking
What are test hooks? link
The use of P/Invoke in Automation (.net link )
How to set a Windows hook in Visual C# .NET (link ) Windows Automation API 3.0 Overview (link ) GUI Automation with pyAA (link )
Advanced
SpyStuio - http://www.nektra.com/products/spystudio
Automating Windows Applications - http://www.codeproject.com/KB/COM/automatingwindowsapps.aspx?fid=13658&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26
Discusses about advanced hooking/spying techniques

Sunday, November 16, 2008

Google maps on BlackBerry

Google have mobilized their Google Maps and should now be available in BlackBerry. Actually this has been available in BB eons ago (at least when talking about how fast things change in the Net).

Unfortunately, not all cities have as good coverage as in the US. But it is still a nice to have application in your BB device, anyway if you stay in non-English region and you happen to not understand the local language or in some cases Google shows language that is not really the local language (like maybe your internet gateway is located somewhere else) then you can still force to view the English language, thus say:

http://m.google.com/maps?hl=en


~ts

English Blogger draft on BlackBerry Asia Region

When you are in Asia,draft.blogger.com tries to automatically detect your location and sets the UI to the language that was detected by Google. Unfortunately, sometimes the gateway is provided outside of the country mostly from Hongkong. This leaves you with a Chinese interface which I can't really understand. This is even more challenging if you are trying to access sites using BlackBerry.

Anyway, to access Blogger Draft in English, use the following URL:
http://draft.blogger.com/mobile-start.g?hl=en

~ts

Monday, November 10, 2008

InstallShield crashing when run from a remote machine using STAF

I have been using STAF/STAX for a while now as a framework on top of software test automation. When we started moving some of our tests in Windows Vista noticed that there have been cases where uninstallation of the software under test is crashing. I thought it was some component not playing well with Windows Vista but I when I tried to perform the uninstallation sequence manually everything was fine and dandy. So I started digging around and I found out that in Windows Vista, the following command may fail.

C:\>staf remotemachine process start command "C:\PROGRA~1\COMMON~1\INSTAL~1\Driver\1150\INTEL3~1\IDriver.exe /M^{1CD6500F-DE1E-44AC-A279-4C85247A9A85^}"

Poking around even more and I finally found a workaround, to get the above command working in Vista, do:
C:\>staf remotemachine process start shell command "C:\PROGRA~1\COMMON~1\INSTAL~1\Driver\1150\INTEL3~1\IDriver.exe /M^{1CD6500F-DE1E-44AC-A279-4C85247A9A85^}"

Notice the use of shell to make this command to work. I would have loved to know why this is causing problem in Windows Vista and not in XP/W2k3.

~ts

Monday, November 03, 2008

wxPython nuggets

Sample code playing around canvas, cursors, images.
Another wxPython Tutorial
The wxPython Tutorial - The wxPython tutorial is the largest and most advanced wxPython tutorial available on the Internet. Suitable for beginners and intermediate programmers
Rubberbanding in wxPython

Add items to Vista Send To Menu

This is the Microsoft Windows Vista Send To:
Adding item to Sent To menu in Vista is easy, just create an item (the item can be a shortcut, a small application, a folder etc..). The location of this folder is in:

%APPDATA%\Microsoft\Windows\SendTo

You can type this in Run dialog (Window+R), in Start Search box, in Windows Explorer locator bar. Another shortcut to this is :
Shell:sendto

As before you can type this in Run Dialog(Window+R) or Windows Search bar

~ts

Sunday, November 02, 2008

Could not open requested SVN filesystem

If you are trying to access a project in SourceForge using an SVN client and you see something like "Could not open requested SVN filesystem" then it is possible that the project's SVN access is not enabled. See this link on how to enable SVN. Note that you need to have admin privileges to a particular project to enable SVN.

~TS

Enable SVN access to Sourceforge project

SVN repository is not enabled by default when creating a project in SourceForge. To enable SVN is easy. Go to the summary page, see below for sample screen shot, then hover to Admin tab.
You should see the screen below, then just enable "The following box should be checked to enable Subversion" and Update and off you go.

Enjoy!

TS

Sourceforge links of interest

Some useful links for SourceForge users.

Quickstart Guide to Subversion on SourceForge
Recommended Software Configuration - this includes how to configure SVN clients, cvs and many more.


~TS

Thursday, October 30, 2008

Changing Eclipse text editor font

Working long hours tinkering with code can greatly strain your eyes. I think this is the reason why most programmers are so picky with the font they are using. I spend quite a lot of time looking for the best font (my personal best). Proggy fonts are quite good, so is Envy Code R.

But for quite sometime, I believe more than a year, I developed love and hate relationship with Consolas. This font is optimized for Microsoft ClearType. The problem is not all of the machines I used are upgraded to RDP 6.x clients. Older remote desktop clients does not support ClearType, so I have to use non-cleartype friendly fonts. Courier New is good candidate but most of the time I settle with Proggy fonts.

Anyway, to use Consolas in Eclipse 3.4.1 (Ganymede) is easy and oh note that this font is designed for VS2005 and VS2008. Just hit on Windows | Prerences | General | Appearance | Colors and Fonts | Basic | Text Font. See below for screen shot where to access this option.

Step 1: Window | Preferences.

Step 2: Select Text Font under "Basic" root node.

Step 3: Select the desired font. In this case, I'm gonna use Consolas.

Enjoy!
TS

Monday, October 27, 2008

TestPartner .Net Fusion

Yesterday, I came across a Microsoft website discussing .Net and Visual Basic 6.0 integration, they dubbed this as VB Fusion. Skimming through the documentation, I came to realize that most of these stuff can be used in TestPartner.

That is where my journey into the world of .Net with TestPartner, which I dubbed as TestPartner .Net Fusion, comes alive. I am planning on making this as a series of blogs discussing the ins and outs of integrating .Net functionality into TestPartner 6.1.x.

For this blog post will try to get our hands wet into the world of .Net integration using System assembly. In fact, what we will do is re-implement what's being dicussed in this site into TestPartner. In a nutshell, we want to display an image downloaded automatically from Space Science and Engineering Center, University of Wisconsin-Madison. We'll grab the latest photo from the east coast of the United States using the System assembly.

So let us create a new form in Common project in TestPartner, call this frmTest. Default form properties should be fine. Drop couple of controls, let's put in command button and image control. Add a code behind form for the command button. It should look like this:
Private Sub CommandButton1_Click()
    Dim webDownload As System.WebClient
    Set webDownload = New System.WebClient
    webDownload.downloadFile _
        "http://www.ssec.wisc.edu/data/east/latest_eastir.gif", _
    "D:" & "\latest_westir.jpg"
    Set Image1.Picture = LoadPicture("D:\latest_westir.jpg")
    frmTest.ScrollHeight = Image1.Height + Image1.Top
    frmTest.ScrollWidth = Image1.Width + Image1.Left
End Sub
For this to work, we need to set a reference to System.tlb. See below:
It should point to C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\system.tlb. It is possible that System.dll is not registered as COM object. So to fix this run:
C:\>regasm "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\system.dll"

Now, we are getting real close. Before creating our test script, check that your form looks somewhat what is shown below:
Now, let us create a test script that will make use of the form, see below for a sample code:
Option Explicit
Sub Main()

    Include "Common.frmTest"
    frmTest.Show
End Sub
Hit on run and viola! You should have the latest weather update from the east coast of the United States. Here is how mine looks:
Enjoy!
TS

Sunday, October 26, 2008

Controlling Popup menu using Accessibility API

In my previous post I discussed about using Accessibility API to control Windows Start Menu. For this blogpost exercise we will control a popup menu using AA.

For those who are familiar with VBA, they would know outright that class modules cannot use AddressOf operator within the class definition. In the spirit of Object Oriented programming, it would have been better to use solely class module for this but due to AddressOf requirements that it should be in a module then we will try to mix and match using both Class module and a module. The code is not a elegant as I hope it would be but this is the way VBA was designed.

Now let us get our hands dirty, first we will create a class module named CPopupMenuController. This is a very simple class module, in the initialization section we set a hook to receive focus events coming from the system and remove the hook once the object is destroyed. See below for the code:

'------------------------------------------------------------------------------
' Developed by  : Techno.Scavenger
' Licensed to   : Mankind
' Date          : 26Oct2008 @ 3:06 PM + 8 GMT (Sunday @home)
' Warranty
' THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
' “Techno.Scavenger” OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY CLAIM,
' DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
' OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
' USE OR OTHER DEALINGS IN THE SOFTWARE.
' Note:
' You can do whatever with this code
'------------------------------------------------------------------------------

'References:
'http://msdn.microsoft.com/en-us/library/ms697639(VS.85).aspx
'http://www.microsoft.com/downloads/details.aspx?familyid=3755582A-A707-460A-BF21-1373316E13F0&displaylang=en
'http://support.microsoft.com/kb/315519
'http://blogs.msdn.com/oldnewthing/archive/2004/04/23/118893.aspx
'http://www.eggheadcafe.com/software/aspnet/32676356/toolbarwindow32-button-in.aspx
'http://msdn.microsoft.com/en-us/library/ms696152(VS.85).aspx
'http://msdn.microsoft.com/en-us/library/ms971323.aspx
'Caret Tracking
'http://www.geocities.com/krishnapg/EventTracking.html
'-------------------------------------------------------
'Visual Basic Related
'http://www.brainbell.com/tutors/Visual_Basic/Retrieving_Accessibility_Information.htm
'sample code with hooks to AA
'http://www.eggheadcafe.com/software/aspnet/31694003/please-help-ie-window-do.aspx
'http://www.jsware.net/jsware/vbcode.php5#acc
'Notes:
'Seems like in VB, there is no need to call VariantClear for variants defined as [out] in API.

Option Explicit

'references
'Accessibility  - oleacc.dll

Private Declare Function AccessibleObjectFromEvent Lib "oleacc" (ByVal hwnd As Long, ByVal dwId As Long, ByVal dwChildId As Long, ppacc As IAccessible, pvarChild As Variant) As Long
Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
Private Declare Function SetWinEventHook Lib "user32.dll" (ByVal eventMin As Long, ByVal eventMax As Long, ByVal hmodWinEventProc As Long, ByVal pfnWinEventProc As Long, ByVal idProcess As Long, ByVal idThread As Long, ByVal dwFlags As Long) As Long
Private Declare Function UnhookWinEvent Lib "user32.dll" (ByVal lHandle As Long) As Long

'event constants
Private Const EVENT_OBJECT_CREATE = &H8000&         ' // hwnd + ID + idChild is created item
Private Const EVENT_OBJECT_DESTROY = &H8001&        '// hwnd + ID + idChild is destroyed item
Private Const EVENT_OBJECT_SHOW = &H8002&           '// hwnd + ID + idChild is shown item
Private Const EVENT_OBJECT_HIDE = &H8003&           '// hwnd + ID + idChild is hidden item
Private Const EVENT_OBJECT_FOCUS = &H8005&          '// hwnd + ID + idChild is focused item
Private Const EVENT_OBJECT_LOCATIONCHANGE = &H800B& '// hwnd + ID + idChild is moved/sized item
Private Const WINEVENT_OUTOFCONTEXT = &H0&          '// Events are ASYNC
Private Const WINEVENT_SKIPOWNPROCESS = &H2&        '// Don't call back for events on installer's process

'class private stuff
Private m_hHook As Long
Private m_sMenuPath As String

Private Sub Class_Initialize()
Include "Common.MPopupMenuController"
m_hHook = SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, 0&, AddressOf MPopupMenuController.WinEventFunc, 0, 0, WINEVENT_SKIPOWNPROCESS)
End Sub

Private Sub Class_Terminate()
Dim lRet As Long

If m_hHook <> 0 Then
lRet = UnhookWinEvent(m_hHook)
End If
End Sub

Public Sub SelectMenu(sMenuPath As String)
MPopupMenuController.SelectMenu sMenuPath
End Sub


MPopupMenuController does the workhorse for this implementation, basically it houses the function when we set a hook to focus events. The module is also responsible for sending key sequences. See below for the code, save this as MPopupMenuController:

'------------------------------------------------------------------------------
' Developed by  : Techno.Scavenger
' Licensed to   : Mankind
' Date          : 26Oct2008 @ 3:06 PM + 8 GMT (Sunday @home)
' Warranty
' THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
' “Techno.Scavenger” OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY CLAIM,
' DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
' OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
' USE OR OTHER DEALINGS IN THE SOFTWARE.
' Note:
' You can do whatever with this code
'------------------------------------------------------------------------------

'references
'Accessibility  - oleacc.dll

Option Explicit

Private Declare Function AccessibleObjectFromEvent Lib "oleacc" (ByVal hwnd As Long, ByVal dwId As Long, ByVal dwChildId As Long, ppacc As IAccessible, pvarChild As Variant) As Long
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
Private Declare Sub SleepEx Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)

'key constants
Private Const KEYEVENTF_KEYUP = 2
Private Const vbKeyControl = 17
Private Const vbKeyEscape = 27
'event constants
Private Const EVENT_OBJECT_CREATE = &H8000&         '// hwnd + ID + idChild is created item
Private Const EVENT_OBJECT_DESTROY = &H8001&        '// hwnd + ID + idChild is destroyed item
Private Const EVENT_OBJECT_SHOW = &H8002&           '// hwnd + ID + idChild is shown item
Private Const EVENT_OBJECT_HIDE = &H8003&           '// hwnd + ID + idChild is hidden item
Private Const EVENT_OBJECT_FOCUS = &H8005&          '// hwnd + ID + idChild is focused item
Private Const EVENT_OBJECT_LOCATIONCHANGE = &H800B& '// hwnd + ID + idChild is moved/sized item

'private data
Private m_sMenuPath As String
Private m_sActiveItem As String

Public Function WinEventFunc(ByVal hHook As Long, ByVal lEvent As Long, ByVal hwnd As Long, ByVal idObject As Long, ByVal idChild As Long, ByVal idEventThread As Long, ByVal dwmsEventTime As Long) As Long
Dim ObA As IAccessible
Dim lRet As Long
Dim v As Variant
Dim s As String, s1 As String, sName As String
Dim sTmp As String

On Error Resume Next
sTmp = "TS"
Select Case lEvent
'Case EVENT_OBJECT_CREATE, EVENT_OBJECT_DESTROY, EVENT_OBJECT_SHOW, EVENT_OBJECT_HIDE, EVENT_OBJECT_FOCUS, EVENT_OBJECT_LOCATIONCHANGE
Case EVENT_OBJECT_FOCUS
lRet = AccessibleObjectFromEvent(hwnd, idObject, idChild, ObA, v)
If lRet = 0 Then
sTmp = sTmp & ":Name:<" & ObA.accName(v)
sTmp = sTmp & ">:Description:< " & ObA.accDescription(v)
sTmp = sTmp & ">:Role<: " & ObA.accRole(v)
sTmp = sTmp & ">:State<: " & ObA.accState(v)
sTmp = sTmp & ">:menu<: " & m_sMenuPath
m_sActiveItem = ObA.accName(v)
End If
OutputDebugString sTmp
End Select

WinEventFunc = 0

End Function
Public Sub SelectMenu(sMenuPath As String)
m_sMenuPath = sMenuPath
PopupMenuEx sMenuPath
End Sub
Private Sub PopupMenuEx(sMenuPath As String)
Const MAX_LOOPS = 50

Dim vMenu As Variant
Dim iDx As Integer
Dim sMenuBookMark As String
Dim iTerminateCounter


vMenu = Split(sMenuPath, "~")


Call keybd_event(vbKeyControl, 0, 0, 0)
Call keybd_event(vbKeyEscape, 0, 0, 0)

' Release the two keys
Call keybd_event(vbKeyControl, 0, KEYEVENTF_KEYUP, 0)
Call keybd_event(vbKeyEscape, 0, KEYEVENTF_KEYUP, 0)
SleepEx 1000

For iDx = 0 To UBound(vMenu)

Do While m_sActiveItem <> vMenu(iDx)
OutputDebugString "TS: Sending DOWN key"
SendKeys "{DOWN}", True
SleepEx 1000

'set book on first loop thru menu indexes
If sMenuBookMark = "" Then
sMenuBookMark = m_sActiveItem
Else
'if we are here, then this must have been after one round
'we have come full circle, need to raise an error
If m_sActiveItem = sMenuBookMark Then
OutputDebugString "TS: We have come full circle, raising an error"
Include "Common.CustomErrorConstants"
Err.Raise CustomErrorConstants.vbErrMenuNotFound, "MPopupMenuController", "Menu was not found"
End If
End If

'another check if we have gone wild
iTerminateCounter = iTerminateCounter + 1
If iTerminateCounter >= MAX_LOOPS Then
OutputDebugString "TS:Max loops detected, raising an error"
Err.Raise CustomErrorConstants.vbErrMenuNotFound, "MPopupMenuController", "Menu was not found"
End If
Loop

'clear bookmark
sMenuBookMark = ""
'reset terminate marker
iTerminateCounter = 0

'move to next menu
OutputDebugString "TS:Sending RIGHT key"
SendKeys "{RIGHT}", True
Next

'assume we found the item, then hit on enter key
If vMenu(UBound(vMenu)) = m_sActiveItem Then
OutputDebugString "TS: We are about to run " & m_sActiveItem
SendKeys "~", True
Else
MsgBox "nah, not found"
End If
End Sub


Notice that we use custom error constant to raise an error to the system. The constants are defined in a module named CustomErrorConstants, see below for the code.
'------------------------------------------------------------------------------
' Developed by  : Techno.Scavenger
' Licensed to   : Mankind
' Date          : 26Oct2008 @ 1:39 AM + 8 GMT (Sunday @home)
' Warranty
' THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
' “Techno.Scavenger” OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY CLAIM,
' DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
' OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
' USE OR OTHER DEALINGS IN THE SOFTWARE.
' Note:
' You can do whatever with this code
'------------------------------------------------------------------------------

Option Explicit

'Menu not found
Public Const vbErrMenuNotFound = vbObjectError + 4



Now the fun part, how to use? See below for a sample code.
'------------------------------------------------------------------------------
' Developed by  : Techno.Scavenger
' Licensed to   : Mankind
' Date          : 26Oct2008 @ 3:06 PM + 8 GMT (Sunday @home)
' Warranty
' THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
' “Techno.Scavenger” OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY CLAIM,
' DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
' OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
' USE OR OTHER DEALINGS IN THE SOFTWARE.
' Note:
' You can do whatever with this code
'------------------------------------------------------------------------------
Option Explicit

Sub Main()

Window("Application=EXPLORER.EXE Caption=NewFolder").Attach
ListView("Index=1").Click 16, 295, tpMouseRight



Include "Common.CPopupMenuController"

Dim sm As CPopupMenuController
Set sm = New CPopupMenuController
sm.SelectMenu "New~Folder"
Set sm = Nothing
End Sub


Note that the above code is geared towards TestPartner 6.1.x. It is a functional test automation and a VBA host. This should work with minor modification to any VBA hosts like Excel, MSAcess ..etc.

Enjoy!

TS

Saturday, October 25, 2008

Start Menu handler using Accessibility API

The code below demonstrates how to run an application from Start menu using accessibility API in TestPartner making use of VBA. For this exercise, we will use Test Script, Class Module and Module. The original intent was to have the functionality built into class module and instantiate it in Test Script. But AddressOf operator does not work inside a class module in VBA hence using Module. Anyway, first let us define the class module. For this exercise name it CStartMenuController. See below for the code (save this as CStartMenuController):
'------------------------------------------------------------------------------
' Develop by    : Techno.Scavenger
' Licensed to   : Mankind
' Date          : 26Oct2008 @ 1:39 AM + 8 GMT (Sunday @home)
' Warranty
' THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
' “Techno.Scavenger” OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY CLAIM,
' DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
' OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
' USE OR OTHER DEALINGS IN THE SOFTWARE.
' Note:
' You can do whatever with this code
'------------------------------------------------------------------------------

'References:
'http://msdn.microsoft.com/en-us/library/ms697639(VS.85).aspx
'http://www.microsoft.com/downloads/details.aspx?familyid=3755582A-A707-460A-BF21-1373316E13F0&displaylang=en
'http://support.microsoft.com/kb/315519
'http://blogs.msdn.com/oldnewthing/archive/2004/04/23/118893.aspx
'http://www.eggheadcafe.com/software/aspnet/32676356/toolbarwindow32-button-in.aspx
'http://msdn.microsoft.com/en-us/library/ms696152(VS.85).aspx
'http://msdn.microsoft.com/en-us/library/ms971323.aspx
'Caret Tracking
'http://www.geocities.com/krishnapg/EventTracking.html
'-------------------------------------------------------
'Visual Basic Related
'http://www.brainbell.com/tutors/Visual_Basic/Retrieving_Accessibility_Information.htm
'sample code with hooks to AA
'http://www.eggheadcafe.com/software/aspnet/31694003/please-help-ie-window-do.aspx
'http://www.jsware.net/jsware/vbcode.php5#acc
'Notes:
'Seems like in VB, there is no need to call VariantClear for variants defined as [out] in API.

Option Explicit

'references
'Accessibility  - oleacc.dll

Private Declare Function AccessibleObjectFromEvent Lib "oleacc" (ByVal hwnd As Long, ByVal dwId As Long, ByVal dwChildId As Long, ppacc As IAccessible, pvarChild As Variant) As Long
Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
Private Declare Function SetWinEventHook Lib "user32.dll" (ByVal eventMin As Long, ByVal eventMax As Long, ByVal hmodWinEventProc As Long, ByVal pfnWinEventProc As Long, ByVal idProcess As Long, ByVal idThread As Long, ByVal dwFlags As Long) As Long
Private Declare Function UnhookWinEvent Lib "user32.dll" (ByVal lHandle As Long) As Long

'event constants
Private Const EVENT_OBJECT_CREATE = &H8000&         ' // hwnd + ID + idChild is created item
Private Const EVENT_OBJECT_DESTROY = &H8001&        '// hwnd + ID + idChild is destroyed item
Private Const EVENT_OBJECT_SHOW = &H8002&           '// hwnd + ID + idChild is shown item
Private Const EVENT_OBJECT_HIDE = &H8003&           '// hwnd + ID + idChild is hidden item
Private Const EVENT_OBJECT_FOCUS = &H8005&          '// hwnd + ID + idChild is focused item
Private Const EVENT_OBJECT_LOCATIONCHANGE = &H800B& '// hwnd + ID + idChild is moved/sized item
Private Const WINEVENT_OUTOFCONTEXT = &H0&          '// Events are ASYNC
Private Const WINEVENT_SKIPOWNPROCESS = &H2&        '// Don't call back for events on installer's process

'class private stuff
Private m_hHook As Long
Private m_sMenuPath As String

Private Sub Class_Initialize()
   Include "Common.MStartMenuController"
   m_hHook = SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, 0&, AddressOf MStartMenuController.WinEventFunc, 0, 0, WINEVENT_SKIPOWNPROCESS)
End Sub

Private Sub Class_Terminate()
   Dim lRet As Long
  
   If m_hHook <> 0 Then
       lRet = UnhookWinEvent(m_hHook)
   End If
End Sub

Public Sub SelectMenu(sMenuPath As String)
   MStartMenuController.SelectMenu sMenuPath
End Sub
As mentioned above, we need a module to house the function we supply to SetWinEventHook. And this is also where most of the action happens. See below for the code, save this as MStartMenuController:
'------------------------------------------------------------------------------
' Develop by    : Techno.Scavenger
' Licensed to   : Mankind
' Date          : 26Oct2008 @ 1:39 AM + 8 GMT (Sunday @home)
' Warranty
' THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
' “Techno.Scavenger” OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY CLAIM,
' DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
' OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
' USE OR OTHER DEALINGS IN THE SOFTWARE.
' Note:
' You can do whatever with this code
'------------------------------------------------------------------------------

'references
'Accessibility  - oleacc.dll

Option Explicit

Private Declare Function AccessibleObjectFromEvent Lib "oleacc" (ByVal hwnd As Long, ByVal dwId As Long, ByVal dwChildId As Long, ppacc As IAccessible, pvarChild As Variant) As Long
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
Private Declare Sub SleepEx Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)

'key constants
Private Const KEYEVENTF_KEYUP = 2
Private Const vbKeyControl = 17
Private Const vbKeyEscape = 27
'event constants
Private Const EVENT_OBJECT_CREATE = &H8000&         '// hwnd + ID + idChild is created item
Private Const EVENT_OBJECT_DESTROY = &H8001&        '// hwnd + ID + idChild is destroyed item
Private Const EVENT_OBJECT_SHOW = &H8002&           '// hwnd + ID + idChild is shown item
Private Const EVENT_OBJECT_HIDE = &H8003&           '// hwnd + ID + idChild is hidden item
Private Const EVENT_OBJECT_FOCUS = &H8005&          '// hwnd + ID + idChild is focused item
Private Const EVENT_OBJECT_LOCATIONCHANGE = &H800B& '// hwnd + ID + idChild is moved/sized item

'private data
Private m_sMenuPath As String
Private m_sActiveItem As String

Public Function WinEventFunc(ByVal hHook As Long, ByVal lEvent As Long, ByVal hwnd As Long, ByVal idObject As Long, ByVal idChild As Long, ByVal idEventThread As Long, ByVal dwmsEventTime As Long) As Long
   Dim ObA As IAccessible
   Dim lRet As Long
   Dim v As Variant
   Dim s As String, s1 As String, sName As String
   Dim sTmp As String
  
   On Error Resume Next
   sTmp = "YH"
   Select Case lEvent
       'Case EVENT_OBJECT_CREATE, EVENT_OBJECT_DESTROY, EVENT_OBJECT_SHOW, EVENT_OBJECT_HIDE, EVENT_OBJECT_FOCUS, EVENT_OBJECT_LOCATIONCHANGE
       Case EVENT_OBJECT_FOCUS
           lRet = AccessibleObjectFromEvent(hwnd, idObject, idChild, ObA, v)
           If lRet = 0 Then
               sTmp = sTmp & ":Name:<" & ObA.accName(v)                 sTmp = sTmp & ">:Description:< " & ObA.accDescription(v)                 sTmp = sTmp & ">:Role<: " & ObA.accRole(v)                 sTmp = sTmp & ">:State<: " & ObA.accState(v)                 sTmp = sTmp & ">:menu<: " & m_sMenuPath                 m_sActiveItem = ObA.accName(v)             End If             OutputDebugString sTmp     End Select      WinEventFunc = 0        End Function  Public Function SetMenuPath(sMenuPath As String) As Boolean     m_sMenuPath = sMenuPath End Function Public Sub SelectMenu(sMenuPath As String)     m_sMenuPath = sMenuPath     StartMenuEx sMenuPath End Sub Private Sub StartMenuEx(sMenuPath As String)     Const MAX_LOOPS = 50          Dim vMenu As Variant     Dim iDx As Integer     Dim sMenuBookMark As String     Dim iTerminateCounter               vMenu = Split(sMenuPath, "~")       Call keybd_event(vbKeyControl, 0, 0, 0)     Call keybd_event(vbKeyEscape, 0, 0, 0)        ' Release the two keys     Call keybd_event(vbKeyControl, 0, KEYEVENTF_KEYUP, 0)     Call keybd_event(vbKeyEscape, 0, KEYEVENTF_KEYUP, 0)     SleepEx 1000          For iDx = 0 To UBound(vMenu)                  Do While m_sActiveItem <> vMenu(iDx)
           OutputDebugString "YH: Sending DOWN key"
           SendKeys "{DOWN}", True
           SleepEx 1000
          
           'set book on first loop thru menu indexes
           If sMenuBookMark = "" Then
               sMenuBookMark = m_sActiveItem
           Else
               'if we are here, then this must have been after one round
               'we have come full circle, need to raise an error
               If m_sActiveItem = sMenuBookMark Then
                   OutputDebugString "YH: We have come full circle, raising an error"
                   Include "Common.CustomErrorConstants"
                   Err.Raise CustomErrorConstants.vbErrMenuNotFound, "MStartMenuController", "Menu was not found"
               End If
           End If
                      
           'another check if we have gone wild
           iTerminateCounter = iTerminateCounter + 1
           If iTerminateCounter >= MAX_LOOPS Then
               OutputDebugString "YH:Max loops detected, raising an error"
               Err.Raise CustomErrorConstants.vbErrMenuNotFound, "MStartMenuController", "Menu was not found"
           End If
       Loop
      
       'clear bookmark
       sMenuBookMark = ""
       'reset terminate marker
       iTerminateCounter = 0
      
       'move to next menu
       OutputDebugString "YH:Sending RIGHT key"
       SendKeys "{RIGHT}", True
   Next
  
   'assume we found the item, then hit on enter key
   If vMenu(UBound(vMenu)) = m_sActiveItem Then
       OutputDebugString "YH: We are about to run " & m_sActiveItem
       SendKeys "~", True
   Else
       MsgBox "nah, not found"
   End If
End Sub

To make the code a little modular, we have separated custom error constants for use when raising our custom Error. See below for constant definitions and save this as CustomErrorConstants.
'------------------------------------------------------------------------------
' Developed by  : Techno.Scavenger
' Licensed to   : Mankind
' Date          : 26Oct2008 @ 1:39 AM + 8 GMT (Sunday @home)
' Warranty
' THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
' “Techno.Scavenger” OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY CLAIM,
' DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
' OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
' USE OR OTHER DEALINGS IN THE SOFTWARE.
' Note:
' You can do whatever with this code
'------------------------------------------------------------------------------

Option Explicit

'Menu not found
Public Const vbErrMenuNotFound = vbObjectError + 4
Now, how do we use it? We it is quite easy actually. See below for a sample code that runs HyperTerminal. Save it as scratch or whatever suites you best.
'------------------------------------------------------------------------------
' Develop by    : Techno.Scavenger
' Licensed to   : Mankind
' Date          : 26Oct2008 @ 1:39 AM + 8 GMT (Sunday @home)
' Warranty
' THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
' “Techno.Scavenger” OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY CLAIM,
' DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
' OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
' USE OR OTHER DEALINGS IN THE SOFTWARE.
' Note:
' You can do whatever with this code
'------------------------------------------------------------------------------

Option Explicit

Sub Main()

   Include "Common.CStartMenuController"
  
   Dim sm As CStartMenuController
   Set sm = New CStartMenuController
   sm.SelectMenu "All Programs~Accessories~Communications~HyperTerminal"
   Set sm = Nothing
End Sub
Notes: This code is targeted for TestPartner 6.1.x. This should work with any VBA host but you need to adjust a few things. This is also inteneded to work only with Start Menu set to Windows XP style. It should be easy to adapt this for both classic and XP start menu. Enjoy! TS

Saturday, October 11, 2008

Change TestPartner script automatically

This is an ugly hack. Please be careful with this code as it is using an undocumented feature. Code below will allow you to modify a test script using VBA. Test script is an asset within TestPartner application, so if you are not using TP this may not apply to you.

'------------------------------------------------------------------------------
' Develop by    : Techno.Scavenger
' Licensed to   : Mankind
' Date          : 11Oct2008 @ 6:55 PM + 8 GMT (Saturday @home)
' Warranty
' THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
' “Techno.Scavenger” OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY CLAIM,
' DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
' OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
' USE OR OTHER DEALINGS IN THE SOFTWARE.
' Note:
' You can do whatever with this code
'------------------------------------------------------------------------------
Option Explicit
Sub Main()
TestAdd
End Sub
Sub TestAdd()
Dim t As New TPApp
Dim pCount As Integer
Dim p As Integer
Dim sCount As Integer
Dim sName As String
Dim tp As TestPartner.TPProject
Dim ts As TestPartner.TPScript
Dim tsx As TestPartner.TPScriptEx

t.Login "admin", "admin", "TestPartner_SQL", 1
t.Show
pCount = t.Projects.Count
For p = 1 To pCount
If t.Projects.Item(p).Name = "Common" Then
Debug.Print t.Projects.Item(p).Name
Set tp = t.Projects.Item(p)
Dim iSCount As Integer
iSCount = tp.Scripts.Count
Dim iSIdx As Integer
For iSIdx = 1 To iSCount
Set tsx = tp.Scripts.Item(iSIdx)

Set ts = tp.Scripts.Item(iSIdx)
If ts.Name = "TestExecOther" Then

tsx.OpenToLine 2
Sleep 1, tpPauseSeconds
SendKeys "^a", True
Sleep 1, tpPauseSeconds
SendKeys "{BACKSPACE}", True
Sleep 1, tpPauseSeconds
SendKeys "~", True
SendKeys "Sub Main", True
SendKeys "~", True
SendKeys "Msgbox ""Hello 6""", True
SendKeys "~", True
SendKeys "^S", True
Set tsx = Nothing
SendKeys "%FC", True
SendKeys "~", True
End If
Next
End If
Next
t.Logout
Sleep 5, tpPauseSeconds
Set t = New TestPartner.TPApp
t.Login "admin", "admin", "TestPartner_SQL", 1
t.Show
pCount = t.Projects.Count
For p = 1 To pCount
If t.Projects.Item(p).Name = "Common" Then
Set tp = t.Projects.Item(p)
iSCount = tp.Scripts.Count

For iSIdx = 1 To iSCount
Set ts = tp.Scripts.Item(iSIdx)
Debug.Print ts.Name
If ts.Name = "TestExecOther" Then
ts.Execute -1, -1
Do While t.PlaybackInProgress
Sleep 1
Loop
t.Logout
End If
Next

End If
Next
End Sub


~ts

Wednesday, October 01, 2008

Minimal Debian Etch install with X on VirtualBox host

This to document minimal installation of Debian 4.0 (Etch) on VirtualBox host.

Download latest Debian Etch, I am using debian-40r3-i386-netinst.iso. During the package installation, deselect all. This should give you a minimal Debian installation. During installation, you say "No" during selecting the mirror. We will update /etc/app/sources.list after the installation anyway. Reboot virtual machine after installation.

Add the following lines to your /etc/apt/sources.list, I am using nano to edit sources.list file. Since I am near Hongkong, I selected the mirror sites as shown below, change this as you see fit:
hostname:/# nano -w /etc/apt/sources.list

Additional entries into /etc/apt/sources.list
#more entries from here of course from /etc/apt/sources.list
deb http://ftp.hk.debian.org/debian etch main contrib non-free
deb-src http://ftp.hk.debian.org/debian etch main contrib non-free

Then do:
hostname:/# aptitude update hostname:/# aptitude upgrade

The above command should bring your fresh installation of Debian up to date with security patches and upgrade whatever is currently installed in your system. More likely than not, it will install new linux image so you need to reboot after the upgrade.
Now let us install xorg, base gnome and gdm:
hostname:/# aptitude install xorg gnome-core gdm gdm-themes

Reboot machine after the above command, we should now have a graphical login using GDM.
Now let us install some utility commands, less:
hostname:/# aptitude install less

Now install guest additions, in VirtualBox host do Devices | Install Guest Additions..... Then in Debian, do
# mount cdrom # cd /cdrom # sh VBoxLinuxAdditions-x86.run
The guest machine should now feel much faster. One thing you will notice is that GNome is only using a portion of your total screen real state. A quick search in Google points to the fact that the X server used in Debian 4.0 is a bit dated and it does not work with auto-resize. So what we will do next is to adjust xorg.conf to force X to use a much larger workspace. Since X configuration is a book in itself I will just post my configuration here, see below:
# /etc/X11/xorg.conf (xorg X Window System server configuration file) # # This file was generated by dexconf, the Debian X Configuration tool, using # values from the debconf database. # # Edit this file with caution, and see the /etc/X11/xorg.conf manual page. # (Type "man /etc/X11/xorg.conf" at the shell prompt.) # # This file is automatically updated on xserver-xorg package upgrades *only* # if it has not been modified since the last upgrade of the xserver-xorg # package. # # If you have edited this file but would like it to be automatically updated # again, run the following command: # sudo dpkg-reconfigure -phigh xserver-xorg Section "Files" FontPath "/usr/share/fonts/X11/misc" FontPath "/usr/X11R6/lib/X11/fonts/misc" FontPath "/usr/share/fonts/X11/cyrillic" FontPath "/usr/X11R6/lib/X11/fonts/cyrillic" FontPath "/usr/share/fonts/X11/100dpi/:unscaled" FontPath "/usr/X11R6/lib/X11/fonts/100dpi/:unscaled" FontPath "/usr/share/fonts/X11/75dpi/:unscaled" FontPath "/usr/X11R6/lib/X11/fonts/75dpi/:unscaled" FontPath "/usr/share/fonts/X11/Type1" FontPath "/usr/X11R6/lib/X11/fonts/Type1" FontPath "/usr/share/fonts/X11/100dpi" FontPath "/usr/X11R6/lib/X11/fonts/100dpi" FontPath "/usr/share/fonts/X11/75dpi" FontPath "/usr/X11R6/lib/X11/fonts/75dpi" # path to defoma fonts FontPath "/var/lib/defoma/x-ttcidfont-conf.d/dirs/TrueType" EndSection Section "Module" Load "i2c" Load "bitmap" Load "ddc" Load "dri" Load "extmod" Load "freetype" Load "glx" Load "int10" Load "vbe" EndSection Section "InputDevice" Identifier "Generic Keyboard" Driver "kbd" Option "CoreKeyboard" Option "XkbRules" "xorg" Option "XkbModel" "pc104" Option "XkbLayout" "us" EndSection Section "InputDevice" Identifier "Configured Mouse" Driver "vboxmouse" Option "CorePointer" Option "Device" "/dev/input/mice" Option "Protocol" "ImPS/2" Option "Emulate3Buttons" "true" EndSection Section "InputDevice" Identifier "Synaptics Touchpad" Driver "synaptics" Option "Device" "/dev/psaux" Option "Protocol" "auto-dev" Option "HorizScrollDelta" "0" EndSection Section "Device" Identifier "Generic Video Card" Driver "vboxvideo" EndSection Section "Monitor" Identifier "Generic Monitor" Option "DPMS" EndSection Section "Screen" Identifier "Default Screen" Device "Generic Video Card" Monitor "Generic Monitor" SubSection "Display" Modes "1024x680" "800x600" EndSubSection EndSection Section "ServerLayout" Identifier "Default Layout" Screen "Default Screen" InputDevice "Generic Keyboard" InputDevice "Configured Mouse" InputDevice "Synaptics Touchpad" EndSection Section "DRI" Mode 0666 EndSection

Enjoy!

~ts

Install Virtualbox in EeePc 900

Draft - draft - draft - draft

/etc/app/sources.list
deb http://update.eeepc.asus.com/p900 p900 main
deb http://update.eeepc.asus.com/p900/en p900 main

deb http://xnv4.xandros.com/xs2.0/pkg/ xs2.0-xn main non-free
deb http://xnv4.xandros.com/xs2.0/upkg-srv2 etch main contrib non-free
deb http://download.virtualbox.org/virtualbox/debian etch non-free

add public keys
wget -q http://download.virtualbox.org/virtualbox/debian/sun_vbox.asc -O- | sudo apt-key add -
sudo apt-get install xandros-archive-keyring

sudo apt-get install build-essential

download sources
http://support.asus.com/download/download.aspx

unrar x Eee_PC_900_source_code_part1.rar

dpkg --install linux-source-2.6.21.4-eeepc_17_all.deb
cd /usr/src
tar xvjf linux-source-2.6.21.4-eeepc.tar.bz2
cd linux-source-2.6.21.4-eeepc
ln /usr/src/linux-2.6.21.4 /usr/src/linux -s
cd /usr/src/linux
make oldconfig
make prepare
make all
apt-get install virtualbox

create a file, /bin/vbox/run
sudo nano /bin/vboxrun

and paste:
------------------------------
sudo /etc/init.d/vboxdrv start
sudo /etc/init.d/vboxnet start

/usr/bin/VirtualBox

sudo /etc/init.d/vboxdrv stop
sudo /etc/init.d/vboxnet stop
-----------------------------

chage file mode:
sudo chmod +x /bin/vboxrun

Copy or create asusadd:
http://forum.eeeuser.com/viewtopic.php?id=6645

For some reason the above script fails, try this:
mkdir /home/user/.AsusLauncher
then run :
sudo /bin/asusadd Work VirtualBox /bin/asusadd

sudo usermod -a -G vboxusers user
Logout to take effect

Sunday, September 21, 2008

Piping pslist or tslist to findstr

If you are are a console junkie and you frequently play around or look around what is running in your system you may find that using TaskManager can be time consuming and limiting. So I looked around and found a way to use pslist (from Windows Sysinternals) or tslist ( a built in command line ).

The command below means to show information about a process running on "remote_machine" with process name of python.exe
D:\><path_to_pslist>pslist.exe \\remote_machine | findstr python.exe

This one is using the built in tslist command. Same as before, we want to query for a process named python.exe on "remote_machine."
D:\> tslist /S remote_machine | findstr python

~ts

Friday, September 19, 2008

SHDocVw.ShellWindows stopped working on Vista

I have the following code to enumerate running instance of IE 7(not sure if this works with IE6).

Sub TestGetRunningIE()
    Dim sws As SHDocVw.ShellWindows
    Dim ie As SHDocVw.InternetExplorer
    
    Set sws = New SHDocVw.ShellWindows
    For Each ie In sws
        Debug.Print ie.Name
    Next
End Sub
For the above code to work, need to make a reference to shdocvw.dll, see below for the location:
image
When I moved this code in Vista SP1 Business it stopped working. Who would think that this is related to UAC :)... anyway just disable UAC and this code should work again. Note that on one of my machines it is working with UAC on :(....

See this post to disable UAC. This is only one of the methods to disable User Account Control.
~ts

Disable Windows Vista UAC using MSCONFIG

Run msconfig.exe from command line.

image

Then select "Disable UAC", see above for the location. Then hit on "Launch" button. Reboot computer.

~ts

Thursday, September 18, 2008

Remote Registry missing in Vista

 

After installing/uninstalling software in Windows Vista Business machine "Remote Registry" got missing in the services list. Poking around the registry, noticed that under "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RemoteRegistry", Start key was gone.

See picture below for the location:

image

Creating the "Start" key of type REG_DWORD and value 3 (Manual) or 2 (Automatic), then a rebooted fixed the problem.

~ts

Tuesday, September 09, 2008

eeepc important information

Additional repository for Eee PC 900, see link.

Seems like location of simpleui.rc was changed in Eee900 PC. In my machine it is now located in:

/var/lib/AsusLauncher/



~ts

Sunday, September 07, 2008

Powertools free software

Vitrite is a tiny utility written by me, Ryan VanMiddlesworth, that allows you to manually adjust the level of transparency for almost any visible window. It works by utilizing a feature present in Windows 2000/XP (and all later incarnations) for variable window transparency.



WinSpy++ is a handy programmer's utility which can be used to select and view the properties of any window in the system. WinSpy is based around the Spy++ utility that ships with Microsoft Visual Studio.


~ts

Saturday, September 06, 2008

Windows Server 2008 64bit crashing randomly after memory upgrade

I have VMWare Server 2.0 Beta x running on Windows Server 2008 Std 64bit. At only 2GB I can only run one virtual machine. So the machine was upgraded to 8GB! I didn't notice much performance improvement in the host machine but I can start kicking in four virtual machines. But.........

The big but.. was that Windows Server 2008 just crashes randomly. Sometimes just a few minutes.. booom it crashes. Digging a little further I was able to simulate the crash pretty easily. Remote the machine's console session (/admin switch in mstsc.exe) then login back to the host machine.

So I was thinking/asking myself, was it because of the new 8GB memory upgrade? It must be, but is it the hardware or software that does not like the upgrade.

Trying to eliminate variables, I booted the machine into System Rescue CD then run memtest for two hours. No dice here. So it must not be the new memory being faulty.

Digging more, I found out that there was a video error logged in Control Panel>"Problem Reports and Solutions".

So I was thinking then that this must have been a video controller problem or video driver issue. Back in XP days, as far as I know, the high memory area of RAM is being used to access to PC peripherals like PCI cards, shadow of video memory etc. So maybe, just maybe, the drivers where not designed for this large memory configuration. The drivers might have used 32bit addressing assuming that it will be only upto 4GB in memory but I got 8GB in the system. So all of the sudden the memory being allocated (assuming the drivers are using malloc) now returns incorrect values explaining the random crash.

Since the machine is going to be a virtual machine host, I don't need fancy graphics effects, in fact the machine can be headless. So I downgraded the video driver to MS Windows SVGA default driver. Low and behold it is now at last working without issues.

Monday, August 25, 2008

Export TestPartner run into xml with xsl

TestPartner run results can be exported using command line, tpexport, or via File|Export from with TestPartner itself.

Another way of exporting run results is via TestPartner.TLB automation. The beauty with TestPartner.TLB is that you can export with it the xsl.

See below for the code.
Option Explicit
Sub TestTPResultDump()
    Dim t As New TPApp
    Dim pCount As Integer
    Dim p As Integer
    Dim sCount As Integer
    Dim sName As String
    Dim tp2 As TestPartner.TPProject2


    t.Login "admin", "admin", "TestPartner_SQL", 1

    pCount = t.Projects.Count

    For p = 1 To pCount
        If t.Projects.Item(p).Name = "ScratchProject" Then
            Debug.Print t.Projects.Item(p).Name
            Set tp2 = t.Projects.Item(p)
            Dim rc As Integer
            For rc = 1 To tp2.Results.Count
                If tp2.Results.Item(rc).Name = "scratch2" Then
                    Debug.Print tp2.Results.Item(rc).Description
                    Debug.Print tp2.Results.Item(rc).Name
                    Debug.Print tp2.Results.Item(rc).LastModifiedBy
                    Dim v As Long
                    v = tp2.Results.Item(rc).CurrentVersion
                    Dim rr As TestPartner.TPResult
                    Set rr = tp2.Results.Item(rc)
                    rr.Open (v)
                    Debug.Print rr.GetXML(v, v, "d:\test.xml")
                    Call rr.GetXML(v, 1, "D:\test.xml", "D:\test.xsl")
    
                    Dim sXLST As String
                    Dim fXLST As Scripting.File
                    
                    Debug.Print rr.GetXSLT(1, sXLST)
                    'Debug.Print sXLST
                    Dim fso As Scripting.FileSystemObject
                    Dim ts As Scripting.TextStream
                    Set fso = New Scripting.FileSystemObject
                    Set ts = fso.OpenTextFile("D:\test.xsl", ForWriting, True, TristateTrue)
                    ts.Write sXLST
                    ts.Close
                    Set ts = Nothing
                    Set fso = Nothing
                End If
            Next rc
            'tp2.Results.Count
        End If

    Next p
End Sub

Note that you need reference to TestPartner(TestPartner.TLB) and Microsoft Scripting Runtime for the above code snippets to work.

See below for the location of the type library:

















~ts

Saturday, August 23, 2008

Handle popup menus manually in TestPartner

One of the areas where TestPartner 6.1.x is challenged in controlling application under test (AUT) is Popup Menus. It handles it one time but sometimes it complains that the menu is not detected but it is clearly infront of the screen. Though it is working ~80% of the time but Murphy's law has it that if anything can go wrong, it will. What I have come up so far is to handle popup menus manually. See below for the code, so far it seems to meet my needs.

Option Explicit
Private Declare Function SetCursorPos Lib "user32" _
    (ByVal x As Long, ByVal y As Long) As Long
Sub Main()
    'open Windows Explorer in "My Computer"
    Window("Desktop Window").Attach
        ListView("Index=1").Select "CD Drive (E:)", tpMouseRight
    
    PopupMenuEx2 "Properties"

    Window("Application=Explorer.exe Classname='#32770'").Attach
        Button("Caption=OK").Click



End Sub
Private Function PopupMenuEx2(sMenuPath As String) As Boolean
    Dim iMenuCount As Integer
    Dim sMenuSplit As Variant
    Dim iMenuPos As Integer
    
    SetCursorPos 1, 1
    Window.MouseMove 1, 1
    
    'Note that this is important. This is to minimize code in SelectMenuItem
    SendKeys "{DOWN}", True
    sMenuSplit = Split(sMenuPath, "~")
    For iMenuCount = 0 To UBound(sMenuSplit)
        SelectMenuItem sMenuSplit(iMenuCount), iMenuCount > 0
        
        If iMenuCount = UBound(sMenuSplit) Then
            SendKeys "{ENTER}", True
            Exit For
        Else
            SendKeys "{RIGHT}", True
        End If
    Next
End Function

Private Function SelectMenuItem(ByVal sMenuStr As String, isSubMenu As Boolean) As Integer
    Dim mnu As TMenu
    Dim ti As TMenuItem
    Dim i As Integer
    Dim sAttachName As String
    Const DELAY = 100
    
    sAttachName = Window.Application
    sAttachName = "Application=" & sAttachName & " ClassName='#32768'"
    If isSubMenu = False Then
        Set mnu = Window(sAttachName).GetMenu(tpPopupMenu)
    Else
        Set mnu = Window(sAttachName).GetMenu(tpMenu)
    End If
    For i = 1 To mnu.Count
        Set ti = mnu.GetItem(i)
        If ti.Text = sMenuStr Then
            Sleep DELAY, tpPauseMilliSeconds
            Exit Function
        End If
        If Not (ti.IsSeparator) Then
            Sleep DELAY, tpPauseMilliSeconds
            SendKeys "{DOWN}", True
        End If
    Next
End Function
~ts

Saturday, August 16, 2008

Print active application and title using pywinauto

Code snippet below shows how to get the window title and application name of the active application. That is the application on top of the z-order. Need to install pywinauto to get this to work.

import pywinauto.application
import pywinauto.handleprops as _handleprops
import pywinauto.win32functions as _win32functions
import time

while 1:
    hwnd = _win32functions.GetForegroundWindow()
    print "Active Window title is %s"%(_handleprops.text(hwnd))
    print "Application name is %s"%(pywinauto.application.process_module(_handleprops.processid(hwnd)))
    time.sleep(2)    

~ts

Tuesday, August 05, 2008

USB Mouse not detected properly in Vista

After using Windows Vista for over a month my USB mice stopped working :(.... Fortunately this is easy to fix via trial and error on what driver best works for Vista. To fix this do the ff:

Step 1. Go to Device Manager (devmgmt.msc).

Step 2. Do Update Driver Software.

Step 3. Browse my computer for driver software.

Step 4. Select "Let me pick from from a list of device drivers on my computer."

Step 5. If it was shown as unknown device, select "Mice and other pointing device" else select "HID-compliant device."

Step 6. Click on "Have Disk..."

Step 7. Drill to C:\Windows\System32\DriverStore\FileRepository. Select a folder with a name that start with msmouse*. Start with the folder that has the latest time stamp. If this driver does not work select the next newer folder until your mouse driver is installed properly.

See below for related figures.

Figures:

capture

Figure 1.

capture2

Figure 2.

~ts

Thursday, July 31, 2008

KDE4.1 shortcuts

Alt-F2 : Open Run Command (KRunner)

Wednesday, July 30, 2008

Windbg stack tracing

This is a very crude documentation only.

If you got "Module load completed but symbols could not be loaded for....." do the following to investigate:
kd> !sym noisy
kd> .reload

This should pin point why debug symbols are not being loaded.

To use the Microsoft Symbol Server
1. Make sure you have installed the latest version of Debugging Tools for Windows.
2. Start a debugging session.
3. Decide where to store the downloaded symbols (the "downstream store"). This can be a local drive or a UNC path.
4. Set the debugger symbol path as follows, substituting your downstream store path for DownstreamStore.
SRV*d:\msdndebug*http://msdl.microsoft.com/download/symbols
This will download debug symbols to d:\msdndebug automatically.

If you got "Couldn't load mismatched pdb for appname.exe", you can force Windbg to load the pdb file via:
kd> .symopt 0x40
kd> .reload

To check if the symbols match:
#>!itoldyouso bff c:\path\bin\bff.pdb
~ts

Kubutu frequently used commands

Run Kate as root:
:# kdesu kate
~ts

Monday, July 28, 2008

Enable Remote Desktop via Registry key

To enable Remote Desktop of a remote computer change the following key in the registry:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\fDenyTSConnections
Set the value of this key to 0.

Note that you have to connect to remote computer using Registry Editor, thus say, File | Connect Network Registry.

~technos

Friday, July 25, 2008

Get treeview item information using VBA

Test Partner is quite flexible in handling treeview control. But there are times when you need to have a finer control of the object. The purpose of this blogpost is to document how to get treeview item information using Win32 api.

The code below is a class module that now supports getting the text of root and currently selected item. It also allows the user to check whether the item is expanded or not. See below for the code. For demonstration purposes, save this as TWin32TreeView class module under common project (I am referring to Test Partner here).

Option Explicit

'References:
'http://msdn.microsoft.com/en-us/library/bb759988(VS.85).aspx
'http://www.xtremevbtalk.com/showthread.php?t=45515
'http://www.tek-tips.com/viewthread.cfm?qid=344761&page=8
'Get items across process boundaries
'http://www.codeproject.com/KB/threads/int64_memsteal.aspx?fid=29535&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2558283&fr=26
'http://www.autoitscript.com/forum/lofiversion/index.php?t9988.html
'Getting text from GetLastError
'http://support.microsoft.com/kb/186063
'How To List Running Processes
'http://support.microsoft.com/kb/187913
'problem using LVM_SETTEXTBKCOLOR to change color listview text
'http://www.programmersheaven.com/mb/VBasic/340733/340733/ReadMessage.aspx
'GetCommandLine win32 function for VB/VBA
'http://www.motobit.com/tips/detpg_vba-getcommandline/


Private Const TVGN_ROOT As Long = &H0
Private Const TVGN_CARET As Long = &H9

'// TreeView messages
Private Const TV_FIRST As Long = &H1100
Private Const TVM_GETCOUNT As Long = (TV_FIRST + 5)
Private Const TVM_GETNEXTITEM As Long = (TV_FIRST + 10)
Private Const TVM_SELECTITEM As Long = (TV_FIRST + 11)
Private Const TVM_GETITEM As Long = (TV_FIRST + 12) 'this is assuming non-UNICODE
Private Const TVM_ENSUREVISIBLE As Long = (TV_FIRST + 20)
Private Const TVM_GETITEMSTATE As Long = (TV_FIRST + 39)
'TreeView item mask
Private Const TVIF_TEXT = &H1
Private Const TVIF_STATE = &H8
Private Const TVIF_HANDLE = &H10
Private Const TVIF_CHILDREN = &H40

'Treeview statemask
Private Const TVIS_EXPANDED = &H20


Private Const MAXTEXTLEN = 50 'max length per item in tree view

Private m_hwnd As Long

'//process related
Private Const PROCESS_VM_OPERATION As Integer = &H8
Private Const PROCESS_VM_READ As Integer = &H10
Private Const PROCESS_VM_WRITE As Integer = &H20
Private Const PROCESS_QUERY_INFORMATION As Integer = &H400

Private Const MEM_COMMIT = &H1000&
Private Const MEM_RESERVE = &H2000&
Private Const MEM_RELEASE = &H8000&

Private Const PAGE_READWRITE = &H4&

Private Type TVITEM 'was TV_ITEM
    mask As Long
    hItem As Long
    state As Long
    stateMask As Long
    pszText As Long 'pointer to string
    cchTextMax As Long
    iImage As Long
    iSelectedImage As Long
    cChildren As Long
    lParam As Long
End Type

Private Type TVITEMEX
    mask As Long
    hItem As Long
    state As Long
    stateMask As Long
    pszText As Long 'pointer to string
    cchTextMax As Long
    iImage As Long
    iSelectedImage As Long
    cChildren As Long
    lParam As Long
    iIntegral As Long
    #If (WIN32_IE >= &H600) Then
    uStateEx As Long
    hwnd As Long
    iExpandedImage As Long
    #End If
End Type

Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000

Private Declare Function FormatMessage Lib "kernel32" Alias _
    "FormatMessageA" (ByVal dwFlags As Long, lpSource As Long, _
    ByVal dwMessageId As Long, ByVal dwLanguageId As Long, _
    ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Any) _
    As Long
Private Declare Function SendMessageAny Lib "user32" _
    Alias "SendMessageA" _
    (ByVal hwnd As Long, _
    ByVal wMsg As Long, _
    ByVal wParam As Any, _
    lParam As Any) As Long

Private Declare Function GetWindowThreadProcessId Lib "user32" _
    (ByVal hwnd As Long, lpdwprocessid As Long) As Long
Private Declare Function OpenProcess Lib "kernel32.dll" _
    (ByVal dwAccess As Long, _
    ByVal fInherit As Integer, _
    ByVal hObject As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" _
    (ByVal hProcess As Long, lpAddress As Any, _
    ByVal dwSize As Long, _
    ByVal flAllocationType As Long, _
    ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32" _
    (ByVal hProcess As Long, _
    lpAddress As Any, _
    ByVal dwSize As Long, _
    ByVal dwFreeType As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" _
    (ByVal hProcess As Long, _
    lpBaseAddress As Any, _
    lpBuffer As Any, _
    ByVal nSize As Long, _
    lpNumberOfBytesWritten As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" _
    (ByVal hProcess As Long, _
    lpBaseAddress As Any, _
    lpBuffer As Any, _
    ByVal nSize As Long, _
    lpNumberOfBytesWritten As Long) As Long
Private Declare Function lstrcpyn_long_string Lib "kernel32" _
    Alias "lstrcpynA" (ByVal DestString As String, _
    ByVal SourcePointer As Long, _
    ByVal MaxLen As Long) As Long
Private Declare Function lstrlen_long Lib "kernel32" _
    Alias "lstrlenA" (ByVal SourcePointer As Long) As Long

'this black magic functions are not yet being used
Private Declare Function GetProcessHeap Lib "kernel32" () As Long
Private Declare Function HeapAlloc Lib "kernel32" _
    (ByVal hHeap As Long, ByVal dwFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function HeapFree Lib "kernel32" _
    (ByVal hHeap As Long, _
    ByVal dwFlags As Long, _
    lpMem As Any) As Long
Private Declare Sub CopyMemoryWrite Lib "kernel32" _
    Alias "RtlMoveMemory" _
    (ByVal Destination As Long, _
    Source As Any, ByVal Length As Long)

Private Function MessageText(lCode As Long) As String
    Dim sRtrnCode As String
    Dim lret As Long
    
    sRtrnCode = Space$(256)
    lret = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0&, lCode, 0&, _
    sRtrnCode, 256&, 0&)
    If lret > 0 Then
        MessageText = Left(sRtrnCode, lret)
    Else
        MessageText = "Error not found."
    End If
End Function

Public Property Let Handle(l_hwnd As Long)
    m_hwnd = l_hwnd
    OutputDebugString "YH:- Handle: " & CStr(m_hwnd)
End Property


Public Property Get Count() As Long
    Dim lResult As Long
    lResult = SendMessage(m_hwnd, TVM_GETCOUNT, 0, 0)
    Count = lResult
End Property

Public Function MoveToRoot()
    Dim lResult As Long
    lResult = SendMessageAny(m_hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0&)
    'Note: Very important
    'Since lResult is already a pointer to a memory
    'we need to pass the value into the stack as is, not the address hence using ByVal instead of ByRef
    Call SendMessageAny(m_hwnd, TVM_SELECTITEM, TVGN_CARET, ByVal lResult)
End Function

Public Function GetRootItemText() As String 'TVITEM
    Dim pid As Long
    Dim process As Long
    Dim tv_item As TVITEM
    Dim ptv_item As Long 'pointer to tv_item
    Dim pitemsz As Long 'Pointer to pz
    Dim pitem_root As Long 'pointer to tv_item for the root node
    Dim sRet As String

    Call GetWindowThreadProcessId(m_hwnd, pid)
    process = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE Or PROCESS_QUERY_INFORMATION, 0, pid)
    
    If process > 0 Then
        ptv_item = VirtualAllocEx(process, 0, LenB(tv_item), MEM_COMMIT, PAGE_READWRITE)
        pitemsz = VirtualAllocEx(process, 0, MAXTEXTLEN, MEM_COMMIT, PAGE_READWRITE)
        pitem_root = SendMessageAny(m_hwnd, TVM_GETNEXTITEM, TVGN_ROOT, 0&)
        
        If pitem_root <> 0 Then
            tv_item.cchTextMax = MAXTEXTLEN
            tv_item.hItem = pitem_root
            'tv_item.mask = TVIF_TEXT Or TVIF_CHILDREN
            tv_item.mask = TVIF_TEXT Or TVIF_HANDLE
            tv_item.pszText = pitemsz
            
            Dim lpWritten As Long
            Dim lret As Long
            
            lret = WriteProcessMemory(process, ByVal ptv_item, tv_item, LenB(tv_item), lpWritten)
            If lret = 0 Then
                OutputDebugString "YH: -o- WriteProcessMemory returned 0 "
            End If
    
            Call SendMessageAny(m_hwnd, TVM_GETITEM, 0&, ByVal ptv_item)
            
            Dim buf() As Byte
            ReDim buf(MAXTEXTLEN)
            lret = ReadProcessMemory(process, ByVal pitemsz, buf(0), MAXTEXTLEN, lpWritten)
            OutputDebugString "YH: -o- lpwritten > " & CStr(lpWritten)
            
            Dim index As Long
            Dim tmpstring As String
            For index = LBound(buf) To UBound(buf)
            If Chr(buf(index)) = vbNullChar Then Exit For
            tmpstring = tmpstring & Chr(buf(index))
            Next index
            sRet = tmpstring
            
            OutputDebugString "YH: -o- " & tmpstring
        End If
    End If
    
    VirtualFreeEx process, ByVal pitemsz, MAXTEXTLEN, MEM_RELEASE
    VirtualFreeEx process, ByVal tv_item, LenB(tv_item), MEM_RELEASE
    CloseHandle process
    GetRootItemText = sRet
End Function
'Note: Use TVGN_CARET flag of TVM_GETNEXTITEM to get the currently selected item
Public Function GetSelectedItemText() As String
    Dim pid As Long
    Dim process As Long
    Dim tv_item As TVITEM
    Dim ptv_item As Long 'pointer to tv_item
    Dim pitemsz As Long 'Pointer to pz
    Dim pitem_selected As Long 'pointer to tv_item for the selected item
    Dim sRet As String 'return string
    
    Call GetWindowThreadProcessId(m_hwnd, pid)
    process = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE Or PROCESS_QUERY_INFORMATION, 0, pid)
    
    If process > 0 Then
        ptv_item = VirtualAllocEx(process, 0, LenB(tv_item), MEM_COMMIT, PAGE_READWRITE)
        pitemsz = VirtualAllocEx(process, 0, MAXTEXTLEN, MEM_COMMIT, PAGE_READWRITE)
        'get pointer to item object
        pitem_selected = SendMessageAny(m_hwnd, TVM_GETNEXTITEM, TVGN_CARET, 0&)
        If pitem_selected <> 0 Then
            tv_item.cchTextMax = MAXTEXTLEN
            tv_item.hItem = pitem_selected
            tv_item.mask = TVIF_TEXT Or TVIF_HANDLE
            tv_item.pszText = pitemsz

            Dim lpWritten As Long
            Dim lret As Long

            lret = WriteProcessMemory(process, ByVal ptv_item, tv_item, LenB(tv_item), lpWritten)
            If lret = 0 Then
                OutputDebugString "YH: -o- WriteProcessMemory returned 0 "
            End If
            'Now get ptv_item populated with data
            Call SendMessageAny(m_hwnd, TVM_GETITEM, 0&, ByVal ptv_item)

            Dim buf() As Byte
            ReDim buf(MAXTEXTLEN)
            lret = ReadProcessMemory(process, ByVal pitemsz, buf(0), MAXTEXTLEN, lpWritten)
            OutputDebugString "YH: -o- lpwritten > " & CStr(lpWritten)

            Dim index As Long
            Dim tmpstring As String
            For index = LBound(buf) To UBound(buf)
                If Chr(buf(index)) = vbNullChar Then Exit For
                tmpstring = tmpstring & Chr(buf(index))
            Next index
            sRet = tmpstring

            OutputDebugString "YH: -o- " & tmpstring
        End If
    End If

    VirtualFreeEx process, ByVal pitemsz, MAXTEXTLEN, MEM_RELEASE
    VirtualFreeEx process, ByVal tv_item, LenB(tv_item), MEM_RELEASE
    CloseHandle process
    GetSelectedItemText = sRet
End Function
'Note: Use TVM_GETITEMSTATE message with stateMask set to TVIS_EXPANDED
Public Function IsSelectedItemExpanded() As Boolean
    Dim pitem_selected As Long 'pointer to tv_item for the selected item
    Dim bRet As Boolean
    
    pitem_selected = SendMessageAny(m_hwnd, TVM_GETNEXTITEM, TVGN_CARET, 0&)
    'Now get ptv_item populated with data, get the state of the item
    Dim lItemState As Long
    'lItemState = SendMessageAny(m_hwnd, TVM_GETITEMSTATE, ByVal ptv_item, TVIS_EXPANDED)
    lItemState = SendMessageAny(m_hwnd, TVM_GETITEMSTATE, ByVal pitem_selected, TVIS_EXPANDED)
    If (lItemState And TVIS_EXPANDED) = TVIS_EXPANDED Then
        bRet = True
    Else
        bRet = False
    End If
    IsSelectedItemExpanded = bRet
End Function

Below is a sample test script to use the class module. You can save this as "scratch" under common project.

Option Explicit

Sub Main()
    Include "Common.TWin32TreeView"
    Dim wtv As TWin32TreeView
    
    'Window("Desktop Window").Attach
    Window("Application=Explorer.exe ClassName=CabinetWClass TypeName=Window").Attach
    
    Set wtv = New TWin32TreeView
    wtv.Handle = TreeView("Index=1").hwnd
    Dim sMsg As String
    sMsg = "Root item is " & wtv.GetRootItemText
    sMsg = sMsg & vbCrLf & "Selected item is : " & wtv.GetSelectedItemText
    MsgBox sMsg
    
    If wtv.IsSelectedItemExpanded Then
        MsgBox "selected node is expanded"
    Else
        MsgBox "it is not yet expanded"
    End If

End Sub
Enjoy!

Note: For better result, use Notepad++ when copying source code from clipboard. The builtin Notepad.exe is not up to the job.

You may check latest copy from http://tscodesnippets.googlecode.com/svn/tpcodesnippets/trunk/ or browse source from svn repository here.

TechnoS

Test code

This is only a test of formatting source code in Blogger. See http://code.google.com/p/syntaxhighlighter/ for details. Use Notepad++ when copying source over from clipboard.

Option Explicit

Sub Main()

    
    
    Include "Common.TWin32TreeView"
    Dim wtv As TWin32TreeView
    
    'Window("Desktop Window").Attach
    Window("Application=Explorer.exe ClassName=CabinetWClass TypeName=Window").Attach
    
    Set wtv = New TWin32TreeView
    wtv.Handle = TreeView("Index=1").hwnd
    Dim sMsg As String
    sMsg = "Root item is " & wtv.GetRootItemText
    sMsg = sMsg & vbCrLf & "Selected item is : " & wtv.GetSelectedItemText
    'MsgBox sMsg
    
    If wtv.IsSelectedItemExpanded Then
        MsgBox "selected node is expanded"
    Else
        MsgBox "it is not yet expanded"
    End If

End Sub

Wednesday, July 16, 2008

Using System Rescue CD for Windows machines

Backup MBR (master boot record)
:#/ dd if=/dev/sda of=/mnt/tmp/mbr-sda.bak bs=512 count=1


~ts~

Saturday, July 05, 2008

Common Debian administration commands

:#/ apt-cache search [package name] -> searches for a package
:#/ apt-get clean -> cleans the cached installed packages
:#/ apt-get insall [package name] -> install a package
:#/ apt-get update -> synchronize the package index files from their sources
:#/ apt-show-versions -> shows the version of the installed package

Friday, July 04, 2008

Minimal Debian Etch install with X and open-vm-tools


World wide mirror sites (link)
After installing the base system, do the following.

For main Debian repository
hostname:/# nano -w /etc/apt/sources.list

#more entries from here of course from /etc/apt/sources.list
deb http://ftp.debian.org/debian etch main contrib non-free
deb-src http://ftp.debian.org/debian etch main contrib non-free
deb http://www.backports.org/debian etch-backports main contrib non-free
Hongkong is best for my case too:
#more entries from here of course from /etc/apt/sources.list
deb http://ftp.hk.debian.org/debian etch main contrib non-free
deb-src http://ftp.hk.debian.org/debian etch main contrib non-free
deb http://www.backports.org/debian etch-backports main contrib non-free
Notice that we added backports URL in sources.list. That's where open-vm-tools are currently hosted.

Continue with installing the rest of the software:
:/# wget -O - http://backports.org/debian/archive.key | apt-key add -
:/# apt-get update
:/# apt-get install less
 Depending on your Debian version, do install xorg related packages.
Debian Sarge 3.1Debian Etch
apt-get install x-window-system-core apt-get install xorg
Note: Based from this url , the above package is for compatibility only from Debian 3.x. Etch should instead use xorg package.
hostname:/# apt-get install gnome-core
hostname:/# apt-get install gdm msttcorefonts gdm-themes
hostname:/# reboot
After reboot, you should now be in graphical mode. Next step is to open-vm-tools.
:#/ apt-get install open-vm-source
:#/ module-assistant prepare open-vm
:#/ module-assistant auto-install open-vm
:#/ apt-get install open-vm-tools
:#/ reboot
 Install additional applications, like:
:/# apt-get install synaptic
:/# apt-get install firefox
:/# apt-get install gnome-themes
:/# apt-get install gnome-art

~ts~

Monday, June 30, 2008

Screen garbled in VMware Server 2.0 beta 2

 This can be fixed by adding the following line in .vmx of the guest virtual machine.
svga.enableOverlay = "FALSE"

References:
http://communities.vmware.com/message/978732?tstart=15
http://communities.vmware.com/message/905156#905156

~ts~

The file is not a valid compound file opening data link file

If you get this message when opening an ADO connection using Data Link File (.udl)  then this may mean that your .udl file was saved as ANSI. To fix this save .udl file as Unicode  BOM.

~ts~

Friday, June 27, 2008

Fixing VBox guest lossing networking connection

When playing around with Virtual Box guests running Linux, the network connection my get lost on Debian Etch when the virtual interface's MAC changes. This is due to the fact that this version of linux is using udev and fortunately udev detects changes to MAC address. So basically, each new network interface with new MAC address gets its new ethx network interface device name. In my case, I got 3 ethx's already so I need to get rid of the unnecessary interfaces. As a root do this:
$: su
#: cd /etc/udev/rules.d
#: mkdir ~/bak
#: cp zxx_persistent-net-generator.rules ~/bak
#: rm zxx_persistent-net-generator.rules
#: /etc/init.d/udev stop
#: /etc/init.d/udev start
Note that we make a backup of the file just in case we need to go back. Also, for zxx_persistent-net-generator.rules, xx is any two digit number. So just go check the directory for a file that resembels *_persistent-net-generator.rules. Now to prevent udev to generate new interface for every new MAC address for Virtual Box virtual interface, do make the following changes:
#: nano -w /etc/udev/persistent-net-generator.rules
Then ensure that you have the line to ingore MAC address from Virtual Box virtual network interface:
# These rules generate rules to keep network interface names unchanged
# across reboots write them to /etc/udev/rules.d/z25_persistent-net.rules.
#
# The default name for this file is z45_persistent-net-generator.rules.

ACTION!="add",    GOTO="persistent_net_generator_end"
SUBSYSTEM!="net",   GOTO="persistent_net_generator_end"

# ignore the interface if a name has already been set
NAME=="?*",    GOTO="persistent_net_generator_end"

# ignore "secondary" raw interfaces of the madwifi driver
KERNEL=="ath*", ATTRS{type}=="802", GOTO="persistent_net_generator_end"

# provide nice comments for the generated rules
SUBSYSTEMS=="pci", \
ENV{COMMENT}="PCI device $attr{vendor}:$attr{device}"
SUBSYSTEMS=="usb", \
ENV{COMMENT}="USB device $attr{idVendor}:$attr{idProduct}"
SUBSYSTEMS=="ieee1394", \
ENV{COMMENT}="Firewire device $attr{host_id}"
SUBSYSTEMS=="xen", \
ENV{COMMENT}="Xen virtual device"
ENV{COMMENT}=="", \
ENV{COMMENT}="Unknown $env{SUBSYSTEM} device ($env{DEVPATH})"
ATTRS{driver}=="?*", \
ENV{COMMENT}="$env{COMMENT} ($attr{driver})"
#Ignore Virtual Box virtual network interface
ATTR{address}=="08:00:27:*", GOTO="persistent_net_generator_end"

# ignore interfaces without a driver link like bridges and VLANs
KERNEL=="eth*|ath*|wlan*|ra*|sta*", DRIVERS=="?*",\
IMPORT{program}="write_net_rules $attr{address}"

ENV{INTERFACE_NEW}=="?*", NAME="$env{INTERFACE_NEW}"

LABEL="persistent_net_generator_end"
Then delete /etc/udev/rules.d/zxx_persistent-net-generator.rules. In Debian Etch, default xx value is 25 but once you re-generate new rule it defaults xx to 45. Now once you restart udev or reboot the machine you should have a persistent interface name for Virtual Box virtual interface. A word of caution though. If you add another interface this may cause problem as udev might not assign new network interface for the additional NIC card since we have created an exception. So you might opt to use the first method of just regenerating the rules by deleting /etc/udev/rules.d/zxx_persistent-net-generator.rules and restarting udev or rebooting the machine.

References: http://forums.virtualbox.org/viewtopic.php?t=1616

Enjoy!

~TechnoS