Tuesday, 17 March 2009

Modifying a user's Revit.ini file

Historically I've been a bit cautious about this, as it just feels wrong sneaking into another Program's installation directory and modifying any file, let alone one with a .ini extension. But leaving my users having to edit their ini manually ad infinitum wasn't an acceptable long-term solution.

It was to my pleasant surprise that the SDK contains a sample of C# code designed to modify the Revit.ini. And very simple it looks too. It makes use of the windows registry functions WritePrivateProfileString and GetPrivateProfileInt.

Here I've knocked up a VB.net version and added one feature I wouldn't feel safe without - a backup copy in case it all goes wrong! Make a console application that starts in Sub Main, with two vb modules called anything you like. Drop this code into one module:

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.IO

Module General

    Public Sub Main(ByVal args() As String)
        Try
            ' path to Revit.ini
            Dim iniFilename As String = "C:\Path to Revit installation\Revit.ini"

            ' check exists
            If File.Exists(iniFilename) Then
                'make backup in case anything goes wrong!
                FileCopy(iniFilename, iniFilename & ".BAK")
            Else

                Console.WriteLine("File ""{0}"" not found.", iniFilename)
                Throw New ApplicationException("Ini file not found")
            End If

            Dim externalCommands As String = "ExternalCommands"
            Dim commandName As String = "This is my command name"
            Dim className As String = "class.name"
            Dim commandDescription As String = "Whatever you like"

            Dim revitIni As New IniFile(iniFilename)

            ' get count if exists.  else 0
            Dim ecCount As Integer = revitIni.GetIniValue(externalCommands, "ECCount", 0)

            ' increment count
            ecCount += 1
            Try
                ' get writing
                revitIni.WriteIniString(externalCommands, "ECCount", ecCount.ToString())
                revitIni.WriteIniString(externalCommands, "ECName" & ecCount.ToString(), commandName)
                revitIni.WriteIniString(externalCommands, "ECClassName" & ecCount.ToString(), className)
                revitIni.WriteIniString(externalCommands, "ECDescription" & ecCount.ToString(), commandDescription)

            Catch ex As Exception
                Console.WriteLine("Write failed")
            End Try

        Catch ex As Exception
            Console.WriteLine("Add External Command failed.")
        End Try

    End Sub

End Module

and drop this into the other:
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Runtime.InteropServices


Public Class IniFile
    'path of ini file
    Private iniPath As String

    ''' 
    ''' Gets or sets the path of ini file
    ''' 
    Public Property Path() As String
        Get
            Return iniPath
        End Get
        Set(ByVal value As String)
            iniPath = value
        End Set
    End Property

    <DllImport("kernel32")> _
    Private Shared Function WritePrivateProfileString(ByVal section As String, ByVal key As String, ByVal val As String, ByVal filePath As String) As Integer
    End Function


    <DllImport("kernel32")> _
    Private Shared Function GetPrivateProfileInt(ByVal section As String, ByVal key As String, ByVal def As Integer, ByVal filePath As String) As Integer
    End Function


    Public Sub New(ByVal iniFilePath As String)
        iniPath = iniFilePath
    End Sub


    Public Function WriteIniString(ByVal region As String, ByVal key As String, ByVal value As String) As Boolean
        Return If(WritePrivateProfileString(region, key, value, Me.iniPath) = 0, False, True)
    End Function


    Public Function GetIniValue(ByVal region As String, ByVal key As String, ByVal def As Integer) As Integer
        Return GetPrivateProfileInt(region, key, def, Me.iniPath)
    End Function
End Class

Start her up, and assuming the path to your Revit.ini file is correct it should work. I'll be looking to run this .exe in our installation process so we can banish manual ini editing forever. Yay!

No comments:

Post a Comment

Comments are moderated, so you'll have to wait a little bit before they appear!