Click here to Skip to main content
15,041,767 members
Articles / Desktop Programming / MFC
Article
Posted 3 Feb 2017

Stats

6.3K views
243 downloads
8 bookmarked

Ved Startup Manager

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
3 Feb 2017CPOL4 min read
This article is written in VC++ as utility to manage startup applications of Windows.

Introduction

Startup programs are entries which are launched or start by windows automatically. For some programs it is necessary to start automatically with windows but majority of applications residing in startup list are eating your system's memory and CPU. It also increases your system's startup time. Some of them keep running in background which degrades your system performance. So it is necessary to manage startup applications according to your need.

Background

Startup entries are essential part of Windows Operating System. Through windows we can view startup programs using, "Windows Management Instrumentation". To view startup programs through this process we need to follow following steps:
    1) Open command prompt and type command, "WMIC" and hit the "Enter" key.
    2) After that type, "STARTUP" and hit the "Enter" key.
We can also able to see startup programs through "MSCONFIG" or through "TASKMANAGER".

About Startup Entries

On Windows OS we can make any application to run as startup using two methods. Either we put execution command (executable path with its commandline arguments if any) in system’s registry or we put link for an application in special folders of windows OS.

Registry

Locations for startup applications in registry are as follows:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServices
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunServicesOnce

RUN

Commands found in subkey "RUN" starts every time when user log on to computer. Interesting points about commands found under "RUN" subkey key are:

  • Command found under this subkey to be run each time after window log on and not at boot time.
  • There is not any specific order to execute these commands.
  • This key is present under, "HKEY_LOCAL_MACHINE" and "HKEY_CURRENT_USER" hives.
  • If present under, "HKEY_LOCAL_MACHINE" then command affects to all users.

RUNONCE

Commands under this category runs only once. Windows deletes these commands from "RunOnce" subkey path after execution. For other cases "RUNONCE" subkey is similar to "RUN".

To know more about these entries and other startup entries please go through following links:

http://www.tenouk.com/ModuleP1.html

https://msdn.microsoft.com/en-us/library/windows/desktop/aa376977(v=vs.85).aspx

https://msdn.microsoft.com/en-us/windows/hardware/drivers/install/runonce-registry-key

https://support.microsoft.com/en-us/help/310593/description-of-the-runonceex-registry-key

https://msdn.microsoft.com/en-us/library/windows/desktop/ms724072(v=vs.85).aspx

NOTE:

  • If your operating system is 64 bit then, 32 bit application's startup entries get stored on:
    HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run
    HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce
    HKEY_CURRENT_USER\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run
    HKEY_CURRENT_USER\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce
  • Wow6432Node:
    To manage 32 bit application on 64 bit machine "Wow6432Node" key is used.

Startup Folders

Startup directories or folders contains a list of shortcuts or executables which start with window just after windows logon. We can find them on Windows 8/10 on the following path:

ALL USERS

%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\StartUp
Shortcut way to access this path, open "RUN", type "shell:common startup" and hit Enter.

USER PROFILE/CURRENT USER

%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup
Shortcut way to access this path, open "RUN", type "shell:startup" and hit Enter.

Classes Used

Before elaborating this section of article, I wants to thank "Sven Wiegand" for his article for retrieving file version information. I have used, "CFileVersionInfo" class here in this application to retrieve file information. You will find it here:

https://www.codeproject.com/Articles/1502/CFileVersionInfo-Retrieving-a-File-s-full-Version

Source code of this utility contains following classes:

  1. CStartupDlg: This is applications main class dealing with user interface.

Image 1

  1. CCommonUtilities: This class contains common utility functions used throughout the project.

Image 2

  1. CRegistryUtility: This class contains registry manipulating functions needed in this project.

Image 3

  1. CAddNewStartupEntry: This is dialog class used to add new startup entries in the registry through user interface.

Image 4

 

Using the code

Registry utility function

Following two functions used to access startup entries from registry.

32BIT

C++
void CRegistryUtility::Query32BitAppValues(const HKEY hRoot, const CString strSubKey, vector<pair<CString, CString>> &vecValueData)
    /* ===================================================================================
    NAME OF FUNCTION:   Query32BitAppValues
    CREDIT:             Satish Jagtap
    PURPOSE:            Retrieve data from registry.
    PARAMETERS:         1) [IN] const HKEY hRoot: Root key or hive
                        2) [IN] const CString strSubKey: Key path to retrieve data from
                        3) [OUT] vector<pair<CString, CString>> &vecValueData: List of
                                    retrieved data entries
    RETURN VALUE:       None
    CALLS TO: -         QueryRegistryKeyForValAndData
    CALLED FROM: -      None
    Added date: -       1 Jan, 2016
   ===================================================================================*/
{
    HKEY hKey = NULL;

    if(RegOpenKeyEx(hRoot, strSubKey, 0, KEY_ALL_ACCESS|KEY_WOW64_32KEY, &hKey) != ERROR_SUCCESS) return;

    QueryRegistryKeyForValAndData(hKey, vecValueData); 
    RegCloseKey(hKey);
}

64BIT

C++
void CRegistryUtility::Query64BitAppValues(const HKEY hRoot, const CString strSubKey, vector<pair<CString, CString>> &vecValueData)
    /* ===================================================================================
    NAME OF FUNCTION:   Query64BitAppValues
    CREDIT:             Satish Jagtap
    PURPOSE:            Retrieve data from registry.
    PARAMETERS:         1) [IN] const HKEY hRoot: Root key or hive
                        2) [IN] const CString strSubKey: Key path to retrieve data from
                        3) [OUT] vector<pair<CString, CString>> &vecValueData: List of
                                    retrieved data entries
    RETURN VALUE:       None
    CALLS TO: -         QueryRegistryKeyForValAndData
    CALLED FROM: -      None
    Added date: -       1 Jan, 2016
   ===================================================================================*/
{
    HKEY hKey = NULL;

    if(RegOpenKeyEx(hRoot, strSubKey, 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY, &hKey) != ERROR_SUCCESS) return;

    QueryRegistryKeyForValAndData(hKey, vecValueData); 
    RegCloseKey(hKey);
}

Main functionality

  1. Retrieve all startup entries from registry under, "RUN" and "RUNONCE" subkey
C++
void CStartupDlg::RefreshStartupList_Enable()
    /* ===================================================================================
    NAME OF FUNCTION:   RefreshStartupList_Enable
    CREDIT:             Satish Jagtap
    PURPOSE:            Refresh list control with enabled startup list.
    PARAMETERS:         None
    RETURN VALUE:       None
    CALLS TO: -         1) CCommonUtilities::GetFullPathOfSelectedItem
                        2) CRegistryUtility::Query32BitAppValues
                        3) CRegistryUtility::Query64BitAppValues
                        4) FillStartUpList_Registry
                        5) ListStartupProgramsForSpecificUser
                        6) FillStartUpList_Folder
    CALLED FROM: -      1) OnTvnSelchangedTreeStartupEntries
                        2) OnBnClickedButtonAddnew
                        3) OnFileAddNewStartupEntry
                        4) OnBnClickedButtonRemove
                        5) OnEditRemoveEntry
                        6) OnEditEditEntry
                        7) DisableSelectedEntries
    Added date: -       1 Jan, 2016
   ===================================================================================*/
{
    HTREEITEM hitemSelected        = m_treectlStartupEntries.GetSelectedItem();
    CString strSelectedItemText = m_treectlStartupEntries.GetItemText(hitemSelected);
    CString strSelectedItemPath = m_objCommonUtilities.GetFullPathOfSelectedItem(m_treectlStartupEntries, hitemSelected);

    if(strSelectedItemPath.Find(_T("Enabled Entries")) != -1)
    {
        /***************************************************/
        //Enable/disable menu items
        bool bEnable = false;

        GetMenu()->EnableMenuItem(ID_EDIT_DISABLEENTRY, bEnable ? 0 : MF_ENABLED);  //Enable "Disable Entry" menu item
        GetMenu()->EnableMenuItem(ID_EDIT_ENABLEENTRY, bEnable ? 0 : MF_DISABLED | MF_GRAYED);  //Disable "Enable Entry" menu item
        GetMenu()->EnableMenuItem(ID_EDIT_REMOVEENTRY, bEnable ? 0 : MF_ENABLED);  //Enable "Remove Entry" menu item
        GetMenu()->EnableMenuItem(ID_EDIT_EDITENTRY, bEnable ? 0 : MF_ENABLED); //Enable "Edit Entry" menu item
        m_ctlRemoveButton.EnableWindow(true);  //Enable "Remove" button
        m_ctlAddNewButton.EnableWindow(true); //Enable "Add New" button
        /***************************************************/

        if(strSelectedItemPath.Find(_T("Registry")) != -1)
        {
            m_lstctrlStartupDetailsFolder.ShowWindow(SW_HIDE);
            m_lstctrlStartupDetailsRegistry.ShowWindow(SW_SHOW);

            if(strSelectedItemPath.Find(_T("CurrentUser")) != -1) //Retrieve Current User entries
            {
                if(strSelectedItemPath.Find(_T("Run\\")) != -1)
                {
                    if(strSelectedItemText == _T("32Bit"))
                    {
                        vector<pair<CString, CString>> vec32BitAppValueData;

                        m_objRegistryUtility.Query32BitAppValues(HKEY_CURRENT_USER, _T("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run"), vec32BitAppValueData);
                        //Fill list control with start up entries details
                        FillStartUpList_Registry(vec32BitAppValueData, 
                                                    _T("HKEY_CURRENT_USER"),
                                                    _T("Run"),
                                                    _T("Enabled"),
                                                    _T("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run"));
                    }
                    else if(strSelectedItemText == _T("64Bit"))
                    {
                        vector<pair<CString, CString>> vec64BitAppValueData;

                        m_objRegistryUtility.Query64BitAppValues(HKEY_CURRENT_USER, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"), vec64BitAppValueData);
                        //Fill list control with start up entries details
                        FillStartUpList_Registry(vec64BitAppValueData, 
                                                    _T("HKEY_CURRENT_USER"),
                                                    _T("Run"),
                                                    _T("Enabled"),
                                                    _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"));
                    }
                }
                if(strSelectedItemPath.Find(_T("RunOnce\\")) != -1)
                {
                    if(strSelectedItemText == _T("32Bit"))
                    {
                        vector<pair<CString, CString>> vec32BitAppValueData;

                        m_objRegistryUtility.Query32BitAppValues(HKEY_CURRENT_USER, _T("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce"), vec32BitAppValueData);
                        //Fill list control with start up entries details
                        FillStartUpList_Registry(vec32BitAppValueData, 
                                                    _T("HKEY_CURRENT_USER"),
                                                    _T("Run"),
                                                    _T("Enabled"),
                                                    _T("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce"));
                    }
                    else if(strSelectedItemText == _T("64Bit"))
                    {
                        vector<pair<CString, CString>> vec64BitAppValueData;

                        m_objRegistryUtility.Query64BitAppValues(HKEY_CURRENT_USER, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"), vec64BitAppValueData);
                        //Fill list control with start up entries details
                        FillStartUpList_Registry(vec64BitAppValueData, 
                                                    _T("HKEY_CURRENT_USER"),
                                                    _T("Run"),
                                                    _T("Enabled"),
                                                    _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"));
                    }
                }
            }
            else if(strSelectedItemPath.Find(_T("LocalUser")) != -1)  //Retrieve Local User entries
            {
                if(strSelectedItemPath.Find(_T("Run\\")) != -1)
                {
                    if(strSelectedItemText == _T("32Bit"))
                    {
                        vector<pair<CString, CString>> vec32BitAppValueData;

                        m_objRegistryUtility.Query32BitAppValues(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run"), vec32BitAppValueData);
                        //Fill list control with start up entries details
                        FillStartUpList_Registry(vec32BitAppValueData, 
                                                    _T("HKEY_LOCAL_MACHINE"),
                                                    _T("Run"),
                                                    _T("Enabled"),
                                                    _T("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run"));
                    }
                    else if(strSelectedItemText == _T("64Bit"))
                    {
                        vector<pair<CString, CString>> vec64BitAppValueData;

                        m_objRegistryUtility.Query64BitAppValues(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"), vec64BitAppValueData);
                        //Fill list control with start up entries details
                        FillStartUpList_Registry(vec64BitAppValueData, 
                                                    _T("HKEY_LOCAL_MACHINE"),
                                                    _T("Run"),
                                                    _T("Enabled"),
                                                    _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"));
                    }
                }
                if(strSelectedItemPath.Find(_T("RunOnce\\")) != -1)
                {
                    if(strSelectedItemText == _T("32Bit"))
                    {
                        vector<pair<CString, CString>> vec32BitAppValueData;

                        m_objRegistryUtility.Query32BitAppValues(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce"), vec32BitAppValueData);
                        //Fill list control with start up entries details
                        FillStartUpList_Registry(vec32BitAppValueData, 
                            _T("HKEY_LOCAL_MACHINE"),
                            _T("Run"),
                            _T("Enabled"),
                            _T("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce"));
                    }
                    else if(strSelectedItemText == _T("64Bit"))
                    {
                        vector<pair<CString, CString>> vec64BitAppValueData;

                        m_objRegistryUtility.Query64BitAppValues(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"), vec64BitAppValueData);
                        //Fill list control with start up entries details
                        FillStartUpList_Registry(vec64BitAppValueData, 
                                                    _T("HKEY_LOCAL_MACHINE"),
                                                    _T("Run"),
                                                    _T("Enabled"),
                                                    _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"));
                    }
                }
            }
        }
        else if(strSelectedItemPath.Find(_T("Startup Folders")) != -1)
        {
            m_lstctrlStartupDetailsFolder.ShowWindow(SW_SHOW);
            m_lstctrlStartupDetailsRegistry.ShowWindow(SW_HIDE);

            if(strSelectedItemText == _T("All Users"))
            {
                vector<CString> vecListOfStartupPrograms;

                ListStartupProgramsForSpecificUser(CSIDL_COMMON_APPDATA, vecListOfStartupPrograms); //Retrieve startup programs from all user's app data
                FillStartUpList_Folder(vecListOfStartupPrograms); //populate list control
            }
            else if(strSelectedItemText == _T("Current User"))
            {
                vector<CString> vecListOfStartupPrograms;

                ListStartupProgramsForSpecificUser(CSIDL_APPDATA, vecListOfStartupPrograms); //Retrieve startup programs from current user's app data
                FillStartUpList_Folder(vecListOfStartupPrograms); //populate list control
            }
        }
    }
}
  1. Disable selected startup entries from registry
C++
void CStartupDlg::DisableSelectedEntries()
    /* ===================================================================================
    NAME OF FUNCTION:   DisableSelectedEntries
    CREDIT:             Satish Jagtap
    PURPOSE:            Disable selected registry entries.
    PARAMETERS:         None
    RETURN VALUE:       None
    CALLS TO: -         1) CCommonUtilities::GetSelectedItemsFromList
                        2) CCommonUtilities::SplitString
                        3) CINIUtility::WriteToINIFile
                        4) RemoveSelectedItemsFromList_Registry
                        5) RefreshStartupList_Enable
    CALLED FROM: -      1) OnEditDisableEntry
    Added date: -       1 Jan, 2016
   ===================================================================================*/
{
    vector<CString> vecListSelectedItems;
    TCHAR szPath[MAX_PATH]        = {0};
    CString strDirectory        = _T("");
    CString strDisabledEntries    = _T("");

    if(SUCCEEDED(SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, FALSE)))
    {
        strDirectory = szPath;

        strDirectory.Replace(_T("\\"), _T("/"));
        strDirectory += _T("/VedStartupManager/");

        if(!PathIsDirectory(strDirectory)) CreateDirectory(strDirectory, NULL);
    }

    if(m_lstctrlStartupDetailsRegistry.IsWindowVisible())
    {
        m_objCommonUtilities.GetSelectedItemsFromList(m_lstctrlStartupDetailsRegistry, vecListSelectedItems);

        if(vecListSelectedItems.size() > 0)
        {
            int nSelectedItems    = vecListSelectedItems.size();
            CString strFilePath = _T("");
            
            for(int nIndex = 0; nIndex < nSelectedItems; nIndex++)
            {
                CStringArray saTokens;
                CString strValueName = _T("");
                CString strData = _T("");
                CString strRoot = _T("");
                CString strSubKey = _T("");

                m_objCommonUtilities.SplitString(vecListSelectedItems[nIndex], _T(","), saTokens);

                CString strAppName            = _T("");
                CString strKeyName            = _T("");
                CString strStringToWrite    = _T("");
                CString strINIFile            = strDirectory + _T("DisabledEntries_Reg.ini");

                strAppName = saTokens[2].Trim() + _T("\\") + saTokens[5].Trim();
                strKeyName = saTokens[0].Trim();
                strStringToWrite = saTokens[1].Trim();

                m_objINIUtility.WriteToINIFile(strAppName, strKeyName, strStringToWrite, strINIFile);
            }

            RemoveSelectedItemsFromList_Registry(vecListSelectedItems, strDisabledEntries);
            RefreshStartupList_Enable();

            MessageBox(_T("Selected items are disabled file successfully."), _T("Startup Manager"), MB_OK);
        }
        else
        {
            MessageBox(_T("You have selected no entry/entries to disable."), _T("Startup Manager"), MB_OK);
        }
    }
}
  1. Enable selected startup entries
C++
void CStartupDlg::EnableSelectedEntries()
    /* ===================================================================================
    NAME OF FUNCTION:   EnableSelectedEntries
    CREDIT:             Satish Jagtap
    PURPOSE:            Enable selected disabled registry entries.
    PARAMETERS:         None
    RETURN VALUE:       None
    CALLS TO: -         1) CCommonUtilities::GetSelectedItemsFromList
                        2) CCommonUtilities::SplitString
                        3) CINIUtility::ReadWholeSectionDataFromINI
                        4) CRegistryUtility::SetApplicationOnStartup
                        5) RefreshStartupList_Disable
    CALLED FROM: -      1) OnEditEnableEntry
    Added date: -       1 Jan, 2016
   ===================================================================================*/
{
    vector<CString> vecListSelectedItems;
    TCHAR szPath[MAX_PATH];
    CString strDirectory = _T("");

    if(SUCCEEDED(SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, FALSE)))
    {
        strDirectory = szPath;
        strDirectory.Replace(_T("\\"), _T("/"));
        strDirectory += _T("/VedStartupManager/");
    }

    if(m_lstctrlStartupDetailsRegistry.IsWindowVisible())
    {
        m_objCommonUtilities.GetSelectedItemsFromList(m_lstctrlStartupDetailsRegistry, vecListSelectedItems);

        if(vecListSelectedItems.size() > 0)
        {
            int nSelectedItems    = vecListSelectedItems.size();
            CString strFilePath = _T("");
            
            for(int nIndex = 0; nIndex < nSelectedItems; nIndex++)
            {
                CStringArray saTokens;
                CString strAppName            = _T("");
                CString strKeyName            = _T("");
                CString strStringToWrite    = _T("");
                CString strRoot                = _T("");
                CString strSubKey            = _T("");
                CString strINIFile            = strDirectory + _T("DisabledEntries_Reg.ini");

                m_objCommonUtilities.SplitString(vecListSelectedItems[nIndex], _T(","), saTokens);

                strRoot       = saTokens[2].Trim();
                strAppName = saTokens[2].Trim() + _T("\\") + saTokens[5].Trim();
                strKeyName = saTokens[0].Trim();
                strSubKey  = saTokens[5].Trim();

                vector<pair<CString, CString>> vecWholeSectionData;

                m_objINIUtility.ReadWholeSectionDataFromINI(strINIFile, strAppName, vecWholeSectionData);

                HKEY hRoot;
                CString strApplicationPath;

                if(strRoot.CompareNoCase(_T("HKEY_LOCAL_MACHINE")) == 0)
                    hRoot = HKEY_LOCAL_MACHINE;
                else if(strRoot.CompareNoCase(_T("HKEY_CURRENT_USER")) == 0) 
                    hRoot = HKEY_CURRENT_USER;

                m_objRegistryUtility.SetApplicationOnStartup(hRoot, strSubKey, saTokens[0], saTokens[1]);
                WritePrivateProfileString(strAppName, saTokens[0], NULL, strINIFile);

                RefreshStartupList_Disable();
            }
        }
        else
        {
            MessageBox(_T("You have selected no entry/entries to disable."), _T("Startup Manager"), MB_OK);
        }
    }
}

Note: To view more functionalities please go through source code attached along with this article.

Using An Application

Image 5

This application help you to manage windows startup entries efficiently. You can manage easily manage 32 bit and 64 bit startup entries. You can do following operations with startup entries using this utility:

  1.     Add New Startup Entry: Add new startup entry to registry
  2.     Enable entry: Unable disabled entry
  3.     Disable Entry: Disabled registry startup entry
  4.     Remove Entry: Remove strartup entry from registry
  5.     Edit Entry: Edit existing startup entry
  6.     Execute Entry: Execute startup entry
  7.     Export To Text File: Export details of startup entry to text file
  8.     Open entry Location: Open location of startup entry

Image 6

Points of Interest

In this article to disable startup entries from registry, I used INI file as an intermediate source to store disabled entries. Disabled entries are shown under different branch of tree control for easy access. In this application I created separate branches for 32 bit and 64 bit startup entries.

Remarks

  1. This utility is only limited to "RUN" and "RUNONCE" subkeys.
  2. In this utility, I have not provided to disable startup entries from, "STARTUP FOLDERS".

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Satish Jagtap
Software Developer (Senior) IntellirichDevsoft Pvt. Ltd.
India India
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --