VB Project Setup - Add custom code to an installation

Using the default "Project Setup" template in Visual Studio 2010 I have created a installation program. I've done some research and discovered that I need to use a Custom Action in order to add additional code to the installation. My Goal: Is to parse a TXT file and dump to the registry during the installation.

I created a seperate VB project that does the parsing and importing and it works fine. When I add to the Custom Actions as Primary Output it doesn't execute during the installation. In one of my tests it did create an EXE in the root of install directory and if I double click on the EXE after the fact it works too.

I also don't want the EXE in the program file folder, so I would assume that I would need to delete those files after the fact too.

LVL 1
gregbrainerdAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Meir RivkinFull stack Software EngineerCommented:
did u make sure to add RunInstaller atribute on the custom action class?
something like :

 <RunInstaller(True)> _
    Public Class MyCustomInstaller
0
Meir RivkinFull stack Software EngineerCommented:
did u debug the custom action code? did u try using logging to determine if maybe exception is thrown?
0
meraydin2Commented:
Add an "Installer" class to the project. After the installer class has been added, override Install or handle AfterInstall event.

Let me know if you need an example solution.
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

meraydin2Commented:
Your installer class should look like this:

Imports System.ComponentModel
Imports System.Configuration.Install

Public Class Installer1

    Public Sub New()
        MyBase.New()

        'This call is required by the Component Designer.
        InitializeComponent()

        'Add initialization code after the call to InitializeComponent

    End Sub

    Private Sub Installer1_AfterInstall(ByVal sender As Object, _
                                        ByVal e As System.Configuration.Install.InstallEventArgs) Handles Me.AfterInstall
        'Dim mca As New MyCustomAction
        'mca.Foo()
    End Sub
End Class

Open in new window

0
Meir RivkinFull stack Software EngineerCommented:
@meraydin2

your code snippet is incomplete.
you missing the RunInstaller attribute and the custom class should implement Installer base class.
0
meraydin2Commented:
RunInstaller attribute is in Designer code. This is the normal code file.
0
meraydin2Commented:
like this:
<System.ComponentModel.RunInstaller(True)> Partial Class Installer1
    Inherits System.Configuration.Install.Installer

    'Installer overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Component Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Component Designer
    'It can be modified using the Component Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        components = New System.ComponentModel.Container()
    End Sub

End Class

Open in new window

0
gregbrainerdAuthor Commented:
I get nothing... here is the code. I've tried this as several different things. I've tried modules, class, and straight vb.

Here is the code. I've put it under the Install section of the Custom Actions. I added a logfile to let me know if anything actually happens and if there is any errors in the code but I get nothing.

I tried the debug but it gives the following error: "A project with an Output type of Class Library cannot be started directly."

Maybe I am testing it wrong? In the Solution Explorer it has the "Solution 'Setup 1' (2 projects)
Then it lists my Installer-Class-ImportINI2REG and second the SETUP program. I build at the Solution setup1 step but run the install test from the SETUP program, maybe it's not executing the installer?

I have had some success using the InstallShield.. so far that appears a bit easier than this.
Imports System
Imports System.Collections
Imports System.ComponentModel

<RunInstaller(True)>
Public Class ImportINI2REG
    Dim COMPANYNAME, ADDRESS, CITY, STATE, ZIP, PRIMARYCONTACT, EMAIL, PHONE
    Dim Shell = CreateObject("WScript.Shell")
    Dim FSO = CreateObject("scripting.filesystemobject")
    Dim ProgFiles = Shell.ExpandEnvironmentStrings("%PROGRAMFILES%")

    Public Sub Main()
        'Dim COMPANYNAME, ADDRESS, CITY, STATE, ZIP, PRIMARYCONTACT, EMAIL, PHONE
        Dim logfile = FSO.createtextfile("c:\logfile.txt", True)
        logfile.writeline("ImportINI2REG" & vbCrLf & "---------------------------------------")
        logfile.writeline("Script Started " & TimeOfDay)

        Call ImportINI(logfile)

        logfile.writeline("Script Completed " & TimeOfDay)
        logfile.close()

    End Sub
    Public Sub ImportINI(ByVal logfile)
        ' Import INI file into Registry

        Dim TXTFileName, Key, textfile, line
        Dim iRegPath = "HKLM\Software\Company\Program\v7\"
        'dim targetpath = Shell.regread(iRegPath & "ProgramPath")

        TXTFileName = ProgFiles & "\Company\Program\setup.ini"
        'TXTFileName = "setup.ini"

        If (FSO.FileExists(TXTFileName)) Then
            textfile = FSO.opentextfile(TXTFileName)
            logfile.writeline("Setup.ini found, continuing install" & vbCrLf & TXTFileName)
        Else
            logfile.writeline("Setup.ini not found, please reinstall application" & vbCrLf & TXTFileName)
            Exit Sub

        End If

        logfile.writeline("Parsing TXTFile")
        Do While Not textfile.AtEndOfStream
            line = textfile.ReadLine
            Key = Left(line, InStr(line, "="))
            Select Case Key
                Case "COMPANY="
                    COMPANYNAME = Mid(line, InStr(line, "=") + 1)
                Case "ADDRESS="
                    ADDRESS = Mid(line, InStr(line, "=") + 1)
                Case "CITY="
                    CITY = Mid(line, InStr(line, "=") + 1)
                Case "STATE="
                    STATE = Mid(line, InStr(line, "=") + 1)
                Case "ZIP="
                    ZIP = Mid(line, InStr(line, "=") + 1)
                Case "PHONE="
                    PHONE = Mid(line, InStr(line, "=") + 1)
                Case "CONTACT="
                    PRIMARYCONTACT = Mid(line, InStr(line, "=") + 1)
                Case "EMAIL="
                    EMAIL = Mid(line, InStr(line, "=") + 1)
            End Select

        Loop
        textfile.close()

        logfile.writeline("Adding to Registry")
        'Insert values into the Registry
        Shell.regwrite(iRegPath & "Company", COMPANYNAME, "REG_SZ")
        Shell.regwrite(iRegPath & "Address", ADDRESS, "REG_SZ")
        Shell.regwrite(iRegPath & "City", CITY, "REG_SZ")
        Shell.regwrite(iRegPath & "State", STATE, "REG_SZ")
        Shell.regwrite(iRegPath & "Zip", ZIP, "REG_SZ")
        Shell.regwrite(iRegPath & "Phone", PHONE, "REG_SZ")
        Shell.regwrite(iRegPath & "Contact", PRIMARYCONTACT, "REG_SZ")
        Shell.regwrite(iRegPath & "Email", EMAIL, "REG_SZ")

        'Delete INI file
        'FSO.deletefile(TXTFileName)

    End Sub
End Class

Open in new window

0
Meir RivkinFull stack Software EngineerCommented:
to debug the custom action class add the following line:
Debugger.Break();

when the code reach this line, u may start debugging line by line.
0
Meir RivkinFull stack Software EngineerCommented:
as meraydin2 posted u may drop RunInstaller attribute in your custom action class.
check meraydin2 post and compare with your custom action class in Designer view.
also your code is missing the event handlers or overriding Installer base class like AfterInstall/BeforeInstall etc.
0
Meir RivkinFull stack Software EngineerCommented:
here's your code snippet with an additional code, compile it and run the installer.
your code should break in BeforeInstall event handler.
Imports System
Imports System.Collections
Imports System.ComponentModel

Public Class ImportINI2REG
    Dim COMPANYNAME, ADDRESS, CITY, STATE, ZIP, PRIMARYCONTACT, EMAIL, PHONE
    Dim Shell = CreateObject("WScript.Shell")
    Dim FSO = CreateObject("scripting.filesystemobject")
    Dim ProgFiles = Shell.ExpandEnvironmentStrings("%PROGRAMFILES%")

 Private Sub Installer1_BeforeInstall(ByVal sender As Object, _
                                        ByVal e As System.Configuration.Install.InstallEventArgs) Handles Me.BeforeInstall

System.Diagnostics.Debugger.Break() 

'Dim COMPANYNAME, ADDRESS, CITY, STATE, ZIP, PRIMARYCONTACT, EMAIL, PHONE
        Dim logfile = FSO.createtextfile("c:\logfile.txt", True)
        logfile.writeline("ImportINI2REG" & vbCrLf & "---------------------------------------")
        logfile.writeline("Script Started " & TimeOfDay)

        Call ImportINI(logfile)

        logfile.writeline("Script Completed " & TimeOfDay)
        logfile.close()

    End Sub

    Public Sub Main()

    End Sub

    Public Sub ImportINI(ByVal logfile)
        ' Import INI file into Registry

        Dim TXTFileName, Key, textfile, line
        Dim iRegPath = "HKLM\Software\Company\Program\v7\"
        'dim targetpath = Shell.regread(iRegPath & "ProgramPath")

        TXTFileName = ProgFiles & "\Company\Program\setup.ini"
        'TXTFileName = "setup.ini"

        If (FSO.FileExists(TXTFileName)) Then
            textfile = FSO.opentextfile(TXTFileName)
            logfile.writeline("Setup.ini found, continuing install" & vbCrLf & TXTFileName)
        Else
            logfile.writeline("Setup.ini not found, please reinstall application" & vbCrLf & TXTFileName)
            Exit Sub

        End If

        logfile.writeline("Parsing TXTFile")
        Do While Not textfile.AtEndOfStream
            line = textfile.ReadLine
            Key = Left(line, InStr(line, "="))
            Select Case Key
                Case "COMPANY="
                    COMPANYNAME = Mid(line, InStr(line, "=") + 1)
                Case "ADDRESS="
                    ADDRESS = Mid(line, InStr(line, "=") + 1)
                Case "CITY="
                    CITY = Mid(line, InStr(line, "=") + 1)
                Case "STATE="
                    STATE = Mid(line, InStr(line, "=") + 1)
                Case "ZIP="
                    ZIP = Mid(line, InStr(line, "=") + 1)
                Case "PHONE="
                    PHONE = Mid(line, InStr(line, "=") + 1)
                Case "CONTACT="
                    PRIMARYCONTACT = Mid(line, InStr(line, "=") + 1)
                Case "EMAIL="
                    EMAIL = Mid(line, InStr(line, "=") + 1)
            End Select

        Loop
        textfile.close()

        logfile.writeline("Adding to Registry")
        'Insert values into the Registry
        Shell.regwrite(iRegPath & "Company", COMPANYNAME, "REG_SZ")
        Shell.regwrite(iRegPath & "Address", ADDRESS, "REG_SZ")
        Shell.regwrite(iRegPath & "City", CITY, "REG_SZ")
        Shell.regwrite(iRegPath & "State", STATE, "REG_SZ")
        Shell.regwrite(iRegPath & "Zip", ZIP, "REG_SZ")
        Shell.regwrite(iRegPath & "Phone", PHONE, "REG_SZ")
        Shell.regwrite(iRegPath & "Contact", PRIMARYCONTACT, "REG_SZ")
        Shell.regwrite(iRegPath & "Email", EMAIL, "REG_SZ")

        'Delete INI file
        'FSO.deletefile(TXTFileName)

    End Sub
End Class

Open in new window

0
meraydin2Commented:
You can download the sample solution from the address below. EE did not like the .settings file so I cannot post it here. Just modify the AfterInstall handler in the example code.

http://dev.karmasis.com/customactiontest.zip

sedgwick - thanks for clarifications.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
gregbrainerdAuthor Commented:
No shock I am sure, but yours works. ;-)

Okay, I am going to try and replace your msgbox with the code that I want to use and get back to you in a few.
0
gregbrainerdAuthor Commented:
Your the man!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.