Forum Discussion

AlexKaras's avatar
AlexKaras
Community Hero
15 years ago

How to determine process 'bitness' from code?

Hi,



I'm wondering if anyone succeeded in figuring out via script code whether some given process is 32-bit or 64-bit one?



The are a lot of code samples about how to determine OS or CPU 'bitness', but the problem is that 32-bit process can be executed on 64-bit platform. And the software can be installed into the folder other than ProgramFiles or ProgramFiles(x86), so this also cannot be used as the criterion.

Any piece of advice is appreciated.

6 Replies

  • Hi Alex,



    The Process object has the ProcessType property which returns the bitness of this process as a string ('x86' or 'x64'). See the "ProcessType Property (Process Objects)" help topic.
  • AlexKaras's avatar
    AlexKaras
    Community Hero
    Hi Jared,



    Thank you for prompt reply, but unfortunately, I need to do this from ABS macro, thus I cannot use properties provided by TC engine. (I posted question here in hope of wider audience.) That is why I asked for the script-based option.

    Did I overlooked the similair property in ABS Process Iterator operation?
  • Hi Alex,



    There's no such property, however, you actually wrote a script which checks whether a module is x86 or x64. You posted it here.



    You can use your script with the Process Enumerator (WMI) operation - just pass the ExecutablePath parameter value to the GetExecutableBitness function. Note that you need to replace the aqFile object with Scripting.FileSystemObject to make this function work in ABS.
  • AlexKaras's avatar
    AlexKaras
    Community Hero
    Hi Jared,



    Thank you for reminding me about the GetExecutableBitness function. I also thought for the solution you suggested and tried to implement it in ABS. The problem appeared to be in the replacement of aqFile methods with something available in plain scripting (preferably, with VBScript).

    FSO seems to be not oriented to work with binary files (like it is mentioned, for example at http://blogs.msdn.com/b/ericlippert/archive/2005/04/20/binary-files-and-the-file-system-object-do-not-mix.aspx). And I don't like the idea to read the whole analyzed executable file into memory, because the executable may be quite big.



    Most other approaches from the internet recommend using ADO Stream (e.g. http://www.tek-tips.com/viewthread.cfm?qid=202173&page=534 and your sample with downloading the file: http://www.automatedqa.com/support/viewarticle/8999/?st=0), but all of them are dealing with text files and are using the 'Stream.Read' call which also reads the whole file into the stream (I believe, OS handles streams more efficiently than plain reading of the file into memory, but don't have proof for that). I tried to replace the Stream.Read call with Stream.Read(iNumBytes) one like in this code snippet:

    '--------------------------------------------

      ...

      Stream.Type = 1 ' Binary (adTypeBinary)

    '  Stream.Mode = 1 ' adModeRead

      Stream.Open

      Stream.LoadFromFile strFullFileName

    '  Stream.Open strFullFileName, 1 ' adModeRead



      Stream.Position = &H3C ' contains offset to segmented .EXE header

      iOffset = Stream.Read(4) ' ReadInt

      ...

    '--------------------------------------------

    but this code resulted in two problems.



    The first problem was that the 'Stream.LoadFromFile strFullFileName' line failed when the strFullFileName contained the UNC path to the executable that was opened (running) on the remote machine. I don't know as we speak whether this was because of remote location of the file (though this seems to be OK according to the ADO documentation) or because the file was locked by remote OS (as the running process).

    For the debug purposes, I tried with the strFullFileName pointing to the local file and got the second problem.



    The second problem is that the Stream.Read(iNumBytes) call returns the bytes array (e.g. iOffset from the code snippet from above). In TestComplete's Watch window I was able to see the contents of the array, but failed with both: to convert the returned iOffset bytes array to integer and access its elements via iOffset[0] and iOffset(0) notation.



    Summing-up: strategically, I feel that the suggested approach is correct one. Tactically, I am still looking for the code to read the binary files. I think that my next step will be to consider reading binary files with DelphiScript.
  • AlexKaras's avatar
    AlexKaras
    Community Hero
    Just an update:

    > [...] I think that my next step will be to consider reading binary files with DelphiScript.

    Unfortunately, as per ABS documentation, DelphiScript does not support reading from binary files.



    Will keep considering possible options.
  • AlexKaras's avatar
    AlexKaras
    Community Hero
    In case somebody is interested, I ended with the code like this:

    '-------------------------------------------------------------------------------


    Option Explicit

    '-----------------------------------------------------------------------------


    'From: http://smartbear.com/forums/forum/post/?mode=singleThread&thread=21d89356-06a5-42b0-aff9-0d4c6d58332e

    'also: http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx (http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx)

    'also: http://blogs.msdn.com/b/ericlippert/archive/2005/04/20/binary-files-and-the-file-system-object-do-not-mix.aspx

    'also: http://www.tek-tips.com/viewthread.cfm?qid=202173&page=534

    Function GetExecutableBitness(ByVal strFullFileName)

      Dim iOffset

      Dim oValue

      Dim Stream: Set Stream = CreateObject("ADODB.Stream")

      Dim strHex


      GetExecutableBitness = -1


      Stream.Type = 1 ' Binary (adTypeBinary)

    '  Stream.Mode = 1 ' adModeRead

      Stream.Open

      Stream.LoadFromFile strFullFileName



      Stream.Position = &H3C ' offset to segmented .EXE header start

      iOffset = Stream.Read(4) ' ReadInt


      strHex = AscB(MidB(iOffset, 2, 1)) & AscB(MidB(iOffset, 1, 1))

      strHex = AscB(MidB(iOffset, 4, 1)) & AscB(MidB(iOffset, 3, 1)) & strHex

    Log.Message "Segmented .EXE header starts at " & strHex & " (0x" & Hex(strHex) & "h)"


      Stream.Position = strHex ' move to segmented .EXE header start

      iOffset = Stream.Read(6)


      strHex = Chr(AscB(MidB(iOffset, 1, 1))) & Chr(AscB(MidB(iOffset, 2, 1)))

    'Log.Message "strHex = " & strHex

      If ("PE" <> strHex) Then _

        Log.Error(strFullFileName & " file does not contain the required 'PE' signature")


      strHex = Hex(AscB(MidB(iOffset, 6, 1))) & Hex(AscB(MidB(iOffset, 5, 1)))

    Log.Message "File image is of 0x" & strHex & "h type"


      Stream.Close

      Set Stream = Nothing


      GetExecutableBitness = "0x" & strHex

    End Function

    '-----------------------------------------------------------------------------