NTK and The NTK Project
are properties of Jn Dechereux
Home | Documentation | FAQ.

Vanilla 1.1.8 is a product of Lussumo. More Information: Documentation, Community Support.

Welcome Guest!
Want to take part in these discussions? If you have an account, sign in now.
If you don't have an account, apply for one now.
    •  
      CommentAuthorAbbougaga
    • CommentTimeMar 20th 2017 edited
     
    Just wanted to share this small contribution with NTK community members.
    hope it will be useful and inspire some of you to enhance it with extra features.

    Introduction & problematic
    The aim of this contribution is to show how to 1.detect if Skype is installed on a PC.
    If so, 2.try to retrieve the Skype's default account name (if any) and when possible 3.get the list of registered accounts.

    Solutions
    1 Detecting Skype's presence
    The Skype default account's name is stored in a file named "shared.xml".
    This file is located in C:\users\username\AppData\Roaming\Skype\. So, as the exact path we need to access depends on username, we call the NTK_SHGetSpecialFolderPath() win32 API with CSIDL_APPDATA as second argument.
    FUNCTION GetSkypeDefaultAccount( void )
    . . .
    cFileName := NTK_SHGetSpecialFolderPath(NULL, CSIDL_APPDATA, .F.)
    cFileName := cFileName + "\\Skype\\shared.xml" // This file holdes among other data, the default user ID
    
    IF !FILE(cFileName)
       cMsgResult := "Skype is not installed on this machine."
       RETURN(cMsgResult)
    ENDIF
    . . .
    

    2 Finding Skype's default account name
    "shared.xml" is obviously an XML file. So this second step consists in opening shared.xml and extracting
    the desired information. To do so, we use MEMOREAD() to load the whole xml file content into a string var, remove eventual invalid chars, ...
    . . .
    // Load the content of shared.xml into a memory var string
    cString := MEMOREAD( cFileName )
    IF !( LEN(cString) > 0 )
       cMsgResult := "XML content unavailable - File: "+CRLF+cFileName+CRLF+;
                     "Skype is probably not installed on this machine."
       RETURN(cMsgResult)
    ENDIF
    
    // Remove invalid chars in tag names, if any
    cString := STRTRAN( cString, "<_", "[_" )   // avoid error #4: 'Invalid character as tag name'
    cString := STRTRAN( cString, "</_", "[/_" ) // avoid error #4: 'Invalid character as tag name'
    . . .
    

    ...........then we are able to create an xml object from this string.
    Thus, we can proceed to shared.xml parsing and extract the relevant information.
    . . .
    // Create an XML memory object
    oXmlDoc := TXmlDocument():New( cString )
    IF !( oXmlDoc:nError==HBXML_ERROR_NONE )
       cMsgResult :=  "XML file parsing error #"+AllTrim(str(oXmlDoc:nError))+": "+HB_XmlErrorDesc(oXmlDoc:nError)
       RETURN(cMsgResult)
    ENDIF
    
    // Parse the XML document till the <Account> node is found
    oXmlNode := oXmlDoc:findFirst( "Account" )
    IF oXmlNode <> NIL
       // If found, we look for the existence if a nested node called: <Default>.
       oXmlSubNode := oXmlNode:nextInTree()   // Go to Next node
       If oXmlSubNode:cName=="Default"
          cMsgResult := "DEFAULT ACCOUNT NAME FOUND!"+CRLF+;
                        "The Skype's Default Account Name is:"+CRLF+"["+oXmlSubNode:cData+"]"
       EndIf
    ENDIF
    . . .
    

    In order to find the default account's name, we first call oXmlDoc:findFirst( "Account" ) to locate the <Account> node, then we invoke oXmlNode:nextInTree() to find inside of it, the immediate <Default> subnode, where the account name is stored as a string value.
    <?xml version="1.0"?>
    <config version="1.0" serial="42" timestamp="1489748553.11">
      <Lib>
        <Access>
          <Cookies>4100</Cookies>
          <Enabled>1</Enabled>
        </Access>
        <Account>
          <Default>myaccountname</Default>
          <UpgradeHints>0/6.18.*.*,4</UpgradeHints>
        </Account>
        <BCM>
          <_2>000010008844E7...... ect.
        </BCM>
    . . .
    

    3 Retrieving the Skype's list of account names.
    The list of Skype's registered accounts is quite easy to retrieve. We just have to browse files of the C:\users\username\AppData\Roaming\Skype\ folder, then only keep trace of subdirectories that have a file named config.xml. Our GetSkypeAccountList() is in charge of that basic task.
    FUNCTION GetSkypeAccountList( void )
       Local nI
       Local aSkypeAccList
       Local cMsgResult := ""
    
       // Get Skype's list of registered accounts, if any
       aSkypeAccList := __GetSkypeAccountList()
       IF !EMPTY(aSkypeAccList)
          cMsgResult += "Skype's list of registered accounts:"+CRLF
          cMsgResult += "------------------------------------"+CRLF
          FOR nI := 1 TO LEN(aSkypeAccList)
              cMsgResult += "["+ aSkypeAccList[nI] +"]"+CRLF
          NEXT
          cMsgResult += CRLF+CRLF  // Skip two lines
       ENDIF
    
    RETURN(cMsgResult)
    

    Find out more into the attached zip file.

    Sources and Acknowlegments
    A domain public contribution by Abbougaga Jr.
    This source code for NTK-Framework has been freely inspired from an original MFC-application written by Michael Haephrati:
    https://www.codeproject.com/Tips/826814/Finding-Skypes-Default-Account-Name
    •  
      CommentAuthorxbasefan
    • CommentTimeMar 21st 2017
     
    great demo, seems interesting. will give it a try.
    thanks for sharing.
    wilson
    •  
      CommentAuthorccarrignon
    • CommentTimeMar 25th 2017 edited
     

    +1 Ab.
    Thanks for the work done and for the time devoted to these step-by-step explanations.
    - Chris
    I just have a question:
    Where could I find documention on xml objects used in your code?


    •  
      CommentAuthorAbbougaga
    • CommentTimeMar 30th 2017
     
    Hello guys, thanks for the words.
    Documentation can be found here:
    C:\xharbour\doc\hbxml.txt

    Cheers,
    Ab