简体   繁体   中英

Read INI in Visual Basic vb.NET

I'm trying to read a INI file then dump the values into the registry for a setup application to function.

The INI file looks like this

[Setup Components]

Sybase Adaptive Server Anywhere Client=Yes

Borland Database Engine=Yes

BDERoot=c:\Program Files\Borland\BDE 

Program Shortcuts=Yes

ODBC Data Service Name=Yes

Local Client = Yes

Sybase Admin = Yes

Sybase Directory= C:\Program Files\SQL Anywhere 16

DBRoot=c:\Database

Word Link=Yes

Installation Root Folder=c:\program

FireDAC=DB=asa16;eng=ENGINE;dbn=DBNAME;links=TCPIP{Host=127.0.0.1;Port=2638}

[Program Shortcuts]

Desktop=Yes
Start Menu=Yes

Program Title=PROGRAM

EXE Pathname=c:\program.exe

Parameters=DBNAME

Starting Directory=c:\

Icon=icon.ICO


[ODBC Data Service Name]

Data Service Name=DBNAME

Database File Name=c:\database\database.db

Database Name=DBNAME

Server Name=ENGINE

Comm Links=TCPIP{}

PrefetchBuffer=6000

PrefetchRows=50

CommBufferSize=1460

Compress=no


[Service]

Service Name=SQLANYs_DBNAME
Display Name=SQL Anywhere - DBNAME
Service Group=SQLANYServer
Params=-n DBNAME -x TCPIP{} "C:\database\database.db" -n DBNAME

So I need all those items to be dumped into the registry easily.

I'm using Visual Studio 2015, I did attempt to use Ludvik Jerabek's INI reader ( http://www.codeproject.com/Articles/21896/INI-Reader-Writer-Class-for-C-VB-NET-and-VBScript ) but had no luck getting that to function!

The code i did use for the above was the following:

Dim ini = New IniFile()
ini.Load("setup.ini")
Dim readValue = ini.Sections("Service").Keys("Service Name")
MessageBox.Show(readValue.ToString)

When running this code i got the following error : "Conversion from string "Service" to type "Integer" is not valid. -Also this method means naming each and every key in the INI file which would be quite some task!

I then went down another method after reading some help questions on here and i used the following:

Private Declare Auto Function GetPrivateProfileString Lib "kernel32" (ByVal lpAppName As String,
    ByVal lpKeyName As String,
    ByVal lpDefault As String,
    ByVal lpReturnedString As StringBuilder,
    ByVal nSize As Integer,
    ByVal lpFileName As String) As Integer


Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim sb As StringBuilder
    sb = New StringBuilder(500)
    Dim readVal = GetPrivateProfileString("Service", "Service Name", "", sb, sb.Capacity, "setup.ini")
    MessageBox.Show(readVal.ToString)
End Sub

However this just returns "0"

Any help would be grateful to find a way to get this reading from the INI and dumping to the registry

Using the given IniFile class, this will get you to the config setting values:

Private Sub INIButtonTest_Click(sender As Object, e As EventArgs) Handles INIButtonTest.Click
    Try

        Dim iniFilePath As String = "H:\Dev\StackOverflow\StackOverflowTest\StackOverflowApp\bin\Debug\test.ini"

        Dim myIniFile As New IniFile
        myIniFile.Load(iniFilePath)

        Dim myValue As String = getIniValue(myIniFile, "Service", "Service Name")

        If Not String.IsNullOrEmpty(myValue) Then
            MessageBox.Show(String.Format("Found value: [{0}]", myValue))
        End If

    Catch ex As Exception
        MessageBox.Show(String.Concat("Something went wrong:", ex.Message))
    End Try
End Sub

Private Function getIniValue(iniFileInstance As IniFile, sectionName As String, sectionKey As String) As String

    Dim myValue As String = String.Empty

    For Each sect As IniFile.IniSection In iniFileInstance.Sections
        If sect.Name = sectionName Then
            For Each key As IniFile.IniSection.IniKey In sect.Keys
                If key.Name = sectionKey Then
                    myValue = key.GetValue
                    Exit For
                End If
            Next
            Exit For
        End If
    Next

    Return myValue

End Function

As an alternate, the code for the original approach is very close to correct, but GetPrivateProfileString doesn't actually exist in Kernel32.dll. You need to add a W to the name, which makes the corrected code:

' With these imports
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.Text

' Note the W on the function name
Private Declare Auto Function GetPrivateProfileStringW Lib "kernel32" (ByVal lpAppName As String,
    ByVal lpKeyName As String,
    ByVal lpDefault As String,
    ByVal lpReturnedString As StringBuilder,
    ByVal nSize As Integer,
    ByVal lpFileName As String) As Integer


Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim sb As New StringBuilder(500)
    Dim result As Integer = GetPrivateProfileStringW("Service", "Service Name", "", sb, sb.Capacity, "setup.ini")
    If result > 0 Then
        MessageBox.Show(sb.ToString())
    Else
        Dim ex As New Win32Exception(Marshal.GetLastWin32Error())
        MessageBox.Show(ex.Message)
    End If
End Sub

If you prefer not to use the W, or you want to call your function something different, you can also use the DllImportAttribute and change the function declaration to:

<DllImport("Kernel32.dll", CharSet:=CharSet.Auto, 
           SetLastError:=True, EntryPoint:="GetPrivateProfileStringW")>
Private Shared Function GetPrivateProfileString(ByVal lpAppName As String,
                                                ByVal lpKeyName As String,
                                                ByVal lpDefault As String,
                                                ByVal lpReturnedString As StringBuilder,
                                                ByVal nSize As Integer,
                                                ByVal lpFileName As String) As Integer
End Function

This is what I have used since VB 3.0 and it has worked with all versions of windows since 3.1. There have been a few modifications to make it fit into the conventions of the newer dev tools but essentially they are the same routines.

These must be in a public class or in the public area of a form:

Public Declare Function OSGetPrivateProfileString% Lib "kernel32" Alias "GetPrivateProfileStringA"(ByVal AppName As String, ByVal KeyName As String, ByVal keydefault As String, ByVal ReturnString As String, ByVal NumBytes As Integer, ByVal FileName As String)

Public Declare Function OSWritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA"(ByVal AppName As String, ByVal KeyName As String, ByVal keydefault As String, ByVal FileName As String) As Integer

Then, somewhere in your form's code area or if you have a "functions.vb" class (where the above would be declared) place these two:

Public Shared Function GetINIString(ByVal strItem As String, ByVal strDefault As String, ByVal strSection As String, ByVal filename As String) As String

    Const BUFFERSIZE As Integer = 16768

    Dim strTemp As New String(Chr(0), BUFFERSIZE)
    Dim stringSize As Long = 0

    stringSize = OSGetPrivateProfileString%(strSection, strItem, strDefault, strTemp, BUFFERSIZE, filename)

    Return Strings.Left(strTemp, stringSize)

End Function

AND

Public Shared Sub PutINIString(strItem As String, strValue As String, strSection As String, iniFilename As String)

Dim i As Integer = 0

i = OSWritePrivateProfileString(strSection, strItem, strValue, iniFilename)

End Sub


This continues to work in VB 2010

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM