DCSIMG
May 2010 - Posts - Amit Peer - Blog

MS Israel Community

Building a community
Welcome to MS Israel Community Sign in | Join | Help
in Search

Amit Peer - Blog

The day to day life of a small company CTO using Microsoft's technology

May 2010 - Posts

  • Create/Update/Delete ODBC connection using the registry

    We have just recently asked by a customer to come up with a simple method of quickly update more than 500 machines with multiple ODBC connections. That might be a hell-of-a headache for the IT guys…

    The way we have decided to achieve that, was by running a vbscript (I admit that I forgot it even still exists). So I have found the basic idea in the Hey, Scripting Guy! Blog (thank you!) and have made some changes and additions.

    So here it is – in full (can be downloaded from here):

    sub UpdateOdbc(Name, Server, Database, User, Password, Trusted)

    'Updates an existing System ODBC SQL connection.
    'Please note that this script must run with administrative privileges.
    'Parameters:
    'Name (string) - The ODBC DSN Name
    'Server (string) - The full database server name. Might be in Server\Instance format
    'Database (string) - The database name
    'User (string) - the user name used to login
    'Password (string) - the password used to login
    'Trusted (boolean) - states that the connection is to be trusted connection. When set to True, both username and password are disregarded.
    '
    'Usage:
    'UpdateOdbc "Because Connection", "Because\sql2008", "BecauseDB", "sa", "jku!oi", False
    'or - trusted:
    'UpdateOdbc "Because Connection", "Because\sql2008", "BecauseDB ", "", "", True
        if OdbcNameExists(Name) = true then 
            DeleteOdbc Name 
            CreateOdbc Name, Server, Database, User, Password, Trusted 
        end if
    end sub
     

    sub CreateOdbc(Name, Server, Database, User, Password, Trusted)
    'Creates a System ODBC SQL connection.
    'Please note that this script must run with administrative privileges.
    'Parameters:
    'Name (string) - The ODBC DSN Name
    'Server (string) - The full database server name. Might be in Server\Instance format
    'Database (string) - The database name
    'User (string) - the user name used to login
    'Password (string) - the password used to login
    'Trusted (boolean) - states that the connection is to be trusted connection. When set to True, both username and password are disregarded.
    '

    'Usage:
    'CreateOdbc "Because Connection", "Because\sql2008", "BecauseDB", "sa", "jku!oi", False
    'or - trusted:
    'CreateOdbc "Because Connection", "Because\sql2008", "BecauseDB", "", "", True 
        Const HKEY_LOCAL_MACHINE = &H80000002 

        computer = "." 
        Set registryObject=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _ 
        computer & "\root\default:StdRegProv"

        keyPath = "SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources" 
        valueName = Name

        'You may want to replace "SQL Server" with
        '"SQL Server Native Client 10.0" for SQL native client 10
        '"SQL Native Client" for SQL Native client
        value = "SQL Server" 
        registryObject.SetStringValue HKEY_LOCAL_MACHINE,keyPath,valueName,value 

        keyPath = "SOFTWARE\ODBC\ODBC.INI\" & Name 
        registryObject.CreateKey HKEY_LOCAL_MACHINE,keyPath 
        keyPath = "SOFTWARE\ODBC\ODBC.INI\" & Name 
        valueName = "Database" 
        value = Database 
        registryObject.SetStringValue HKEY_LOCAL_MACHINE,keyPath,valueName,value 

        'Driver - Defaults to SQL Driver (SQLSRV32.dll) 
        'Instead of SQLSRV32.dll you may use: 
        'SQL Native Client - SQLNCLI.dll 
        'SQL Server Native Client 10 - SQLNCLI10.dll 
        valueName = "Driver" 
        value = "C:\WINDOWS\System32\SQLSRV32.dll" 
        registryObject.SetStringValue HKEY_LOCAL_MACHINE,keyPath,valueName,value 
        valueName = "Server" 
        value = Server 
        registryObject.SetStringValue HKEY_LOCAL_MACHINE,keyPath,valueName,value
     
        if Trusted = True then 
            valueName = "Trusted_Connection" 
            value = "Yes" 
            registryObject.SetStringValue HKEY_LOCAL_MACHINE,keyPath,valueName,value 
        else 
            valueName = "Password" 
            value = Password 
            registryObject.SetStringValue HKEY_LOCAL_MACHINE,keyPath,valueName,value 

           
    valueName = "PWD" 
            value = Password 
            registryObject.SetStringValue HKEY_LOCAL_MACHINE,keyPath,valueName,value 

           
    valueName = "username" 
            value = User 
            registryObject.SetStringValue HKEY_LOCAL_MACHINE,keyPath,valueName,value 

           
    valueName = "LastUser" 
            value = User 
            registryObject.SetStringValue HKEY_LOCAL_MACHINE,keyPath,valueName,value 
        end if
    end sub
     

    sub DeleteOdbc(Name)
    'Use to delete an ODBC Connection
    'Please note that this script must run with administrative privileges.
    '
    'Parameters:
    'Name (string) - The ODBC DSN Name
    '
    'Usage:
    'DeleteOdbc "Because Connection" 
        Const HKEY_LOCAL_MACHINE = &H80000002 
        computer = "." 
        Set registryObject=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _ 
        computer & "\root\default:StdRegProv"
        keyPath = "SOFTWARE\ODBC\ODBC.INI\" & Name 
        registryObject.DeleteKey HKEY_LOCAL_MACHINE, keyPath 

       
    keyPath = "SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources" 
        valueName = Name 
        registryObject.DeleteValue HKEY_LOCAL_MACHINE,keyPath,valueName
    end sub


    function OdbcNameExists(Name) 
        Const HKEY_LOCAL_MACHINE = &H80000002 
        computer = "." 
        Set registryObject=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _ 
        computer & "\root\default:StdRegProv"
        keyPath = "SOFTWARE\ODBC\ODBC.INI\" & Name 
        registryObject.GetStringValue HKEY_LOCAL_MACHINE, keyPath, "Server", key 

       
    if
    IsNull(key) then 
            OdbcNameExists = false 
        else 
            OdbcNameExists = true 
        end if
    end function

  • System Restore Issue (0x8007007b) – Off topic

    This is really off topic.

    I'm having an issue opening XAML files in Visual Studio 2010. The IDE simply crashes. I have opened a bug with Microsoft regarding that matter and will update once I have some sort of a result.

    Anyway, I thought it might be something I've installed in the past few days, so I went to System Restore – which of course, happened to be disabled… So, I thought to myself, I'll simply enable it, so that it won't happen again. That wasn't simple as I thought though. When trying to enable system restore on drive C it gave me an error "There was an unexpected error: The filename, directory name or volume label syntax is incorrect. (0x8007007B). System Restore will now close."
    After some investigations, I have discovered that I happen to have two instances of C drive on the System Restore Properties form. One appeared in the beginning and the other at the end and was called "C (missing)" – which, by the way, is not a good sign.
    All I had to do is to turn off system restore for that "missing" hard drive – which made it disappear, and enable system restore on the correct C drive.

  • Delayed Transactions

    (I'm writing this post in English, as I assume it would be easier for me to express my thoughts regarding this subject in a more technical manner. Please try to excuse me for abusing the language…)

    When dealing with cross domain transactions, with processes that may take more than split seconds, we may have a "too long transaction" that will hang one or more tables in the database. Let me start with an example. Assume you have an n-tier application with a business tier. Each domain has its own business process, and the tiers, by any mean, interact one with the other.

    Figure 1 - Add Customer - Simple

    In Figure 1, a system dealing with customers, companies, etc. (possibly some kind of a CRM solution), when adding a customer will also add a company, and to that company – a default warehouse. While relatively a simple process, considering the amount of necessary validation etc. that might be a lengthy operation. Of course, it should be an atomic operation, wrapped in a transaction (see Figure 2).

    Figure 2 - Add Customer - Elaborative

    A way to solve the lengthy transactions problem is to accumulate the proposed database interactions within a separate component, and when the time to "commit" arrives, and only then, to actually begin the transaction, execute the SQL statements and commit the transaction. In order to achieve that goal, we have changed the way our data access layer interacts with our Transaction Manager. The transaction manager is no longer just handling transaction, but has become an actual statements aggregator. It has two modes of operations: the common way – which is still needed in some cases, and the aggregator way – which solves the above problem.

    The Transaction Manager

    Generally, as mentioned there should be two methods – the "regular" one (use TransactionScope against the connection) and the "aggregator" one – which should solve the discussed problem. The way to solve that, is instead of opening a transaction against a database connection and directly call the execute methods on that connection, is to collect the statements and upon commit, and only then, begin the actual database connection and execute the collected statements. So the time the actual transaction locks the relevant table shrinks to the amount of time it takes to actual run the statements rather than the time it takes to run the whole business process.

    Another benefit from this solution is that in some cases one can delay the whole process to a later time, and even stop it in the middle – pretty easily and without a compensation mechanism.

    If you have any questions, drawbacks and/or comments – please write them down here or send me an email to amit@because.co.il

Powered by Community Server (Commercial Edition), by Telligent Systems