Create a installer with inno setup and postgreSQL in Windows X64 - postgresql

I've created an installer for my application that also installs postgreSQL.
The first question:
What is the best way to configure my database, I mean, is it better to use the postgres default user account? Or should I create a new user. Also is it better to use default public schema or should I create a new schema? As one can see, I'm seeking the best practices to use databases. Also, what kind of care do I need to take with possible already installed versions of postgreSQL from any other application?
The second question:
How to create a user using the installer?
I'm trying to create a new user different from the default user but how can I set a password for this user? I would like to do this without prompting the user in a command shell.
If it's helpful, I will happily post any of my code!

Let's go for some points that you've asked in your question.
What is the best way to configure my database, I mean, is it better to use the postgres default user account?
That doesn't matter at all as long as you have defined a strong password for the user to install it you will be good.
is it better to use default public schema or should I create a new schema?
That will depends on your software. If you want to have everything well defined and organized on the use of the database go on, create a schema to your system. If your system will be the only one using PostgreSQL why botter? Read this answer on this matter from DBA forum PostgreSQL and default Schemas
Also, what kind of care I might to take with possible already installed versions of postgreSQL of any other application?
That's a trick one and the very first problem you will have. I find out the hard way that you can't install PostgreSQL database if you already have one previously installed. Not even if you uninstall it (in this case you have to delete all associated registries from windows registry of PostgreSQL).
My advice here is that you put a message on your installer that your system needs a fresh install of PostgreSQL on the target machine and it can't have a previously installed one on it otherwise the install will fail. I know that sucks, but I couldn't find anything to do here. One other thing that I did was to add a note on the installer messages to the user that if He still want to install the system on that machine He would have to contact the "support" to do it manually.
How to create a user using the installer?
From here I will add some commands to you install PostgreSQL in unattended mode.
I'm trying to create a new user different from default user but how to set a password to this user?
The command you will need to install PostgreSQL with a user different from the default one will be:
postgresqlInstallFile[withversion].exe --mode unattended --superaccount super_user_name --superpassword yourStrongPassowordHere
It would be great here if you could ask for the password on your installer program and use a variable within above command.
That alone will install the database with a user defined by you. Here is the documentation about all parameters for PostgreSQL Unattended Install
The second problem is regarding the database of you system. The best course of action I could find was to make a Dump file from the database that I need to install (this database would be empty, with just the structure), added this dump file to the installer so I could import it to the fresh installation of the database.
The problem with this approach is you can't create a database or restore it to PostgreSQL without entering the password for the super account. What I did was
Add messages to the user that He should pay attention to the installer messages and steps so he can't get it wrong
After installing PostgreSql database comes the step to create the database so I use the command:
[path_for_postgresq]/createdb.exe -U user_you_created -W -E UTF8 -O user_you_created "NameOfYourDatabase"
Before I run the above command I showed a message to the user that he will see a prompt screen asking for a password, so He have to enter it and hit Enter. You can't add it as a parameter (PostgreSQL says it is for security measures)
After the database creation it is time to import the dump that I've added on the installer so I used:
[path_for_postgresq]/pg_restore -U user_you_created -c -d NameOfYourDatabase DumpFileOfYourDatabase.backup
Once again, before this command I showed a message to the user asking to enter the password for the database restore command.
Here I will add the code I made for the NSIS installer. Just the PostgreSQL part of it. There are a lot more on my installer you may need something more.
;--------------------------------
;Include Modern UI
!include "MUI.nsh"
;Include Process checker
!include nsProcess.nsh
;Include ZipDLL
!include zipdll.nsh
; include for some of the windows messages defines
!define ALL_USERS
!include winmessages.nsh
;--------------------------------
;General Configuration
Name "Name of your Installer"
OutFile "fileNameOfYourInstaller.exe"
ShowInstDetails "show"
InstallDir $PROFILE\FolderWhereToInstallYourSystem
; Request application privileges for Windows Vista
RequestExecutionLevel admin
; HKLM (all users) vs HKCU (current user) defines
!define env_hklm 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
!define env_hkcu 'HKCU "Environment"'
;--------------------------------
;Interface Settings
!define MUI_ABORTWARNING
;--------------------------------
;Pages
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
;--------------------------------
;Languages
!insertmacro MUI_LANGUAGE "English"
Function .onInit
SetOutPath $TEMP
# the plugins dir is automatically deleted when the installer exits
InitPluginsDir
File /oname=re.bmp re.bmp #here is an image for a splash screen of the installer
splash::show 2000 re
Pop $0 ; $0 has '1' if the user closed the splash screen early,
; '0' if everything closed normally, and '-1' if some error occurred.
FunctionEnd
Function verifyInstallationDIR
IfFileExists $INSTDIR PathGood
MessageBox MB_OK "The chosen directory is not valid for installation.$\r$\nPlease start again and inform a valid path."
Quit ;if $INSTDIR wasn't created the installer will close
PathGood:
FunctionEnd
Section
SetOutPath $TEMP
CreateDirectory $INSTDIR
#Message to the user to PAY ATTENTIOM
MessageBox MB_OK "Please carefully read all messages through installation steps!"
Call verifyInstallationDIR
#Files needed to the installer
File "resources\DatabaseDumpFile.backup"
File "resources\postgresql-9.3.9-3-windows-x64.exe"
#Call postgresql installation in an unattended mode
ExecWait 'postgresqlInstallFile[withversion].exe --mode unattended --superaccount super_user_name --superpassword yourStrongPassowordHere'
Postgresql_Running_Check:
; is app.exe process running? result is stored in $R0
${nsProcess::FindProcess} "postgres.exe" $R0
${If} $R0 > 0
MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION "PostgreSQL process is not running yet. Wait 30 seconds and click Retry or Cancel to cancel installation." /SD IDCANCEL IDRETRY Postgresql_Running_Check
Quit
${EndIf}
;Create the database
MessageBox MB_OK "The System DataBase will be created. A console window will appear asking for a password. Please when it happens type:$\r$\n$\r$\nyourStrongPassowordHere"
ExecWait '$PROGRAMFILES64\PostgreSQL\9.3\bin\createdb.exe -U user_you_created -W -E UTF8 -O user_you_created "NameOfYourDatabase"'
MessageBox MB_OK "The System Installer will import the configuration data to the database. It will ask again for the password. Please when it happens type:$\r$\n$\r$\nyourStrongPassowordHere"
ExecWait '$PROGRAMFILES64\PostgreSQL\9.3\bin\pg_restore -U user_you_created -c -d NameOfYourDatabase DatabaseDumpFile.backup'
SectionEnd
Hope it helps.

Related

Automating Database Connection

For a homework, I have a few steps I have to go through every single time I want to connect to the database and it's becoming a really annoying and time-wasting act.
I've already automated part of it. However, my latest attempt at automating the last few commands hasn't been successful.
Initially, I've set up a shortcut to a PuTTy terminal:
Create new Shortcut
Select "C:\Program Files\PuTTY" as the entry point (Start in)
Enter "C:\Program Files\PuTTY\putty.exe" <MY_USERNAME>#arcade.iro.umontreal.ca -pw <MY_PASSWORD> as the Target
Then after double-clicking this shortcut, I entered these two lines (to create and then execute a bash script):
echo "psql -h postgres && \c ift2935 && set search_path to inscriptions_devoir;" > sql.sh
. sql.sh
Eventually, my goal would be to simply be able to write . sql.sh after opening my shortcut to be all set up and ready to go (and actually, maybe even that can be automatized somehow with the shortcut?). However, as it is, my shell script only runs the psql -h postgres command, which successfully launches PostGreSQL.
My question is:
How do I get the two other commands (\c ift2935 and set search_path to inscriptions_devoir;) to automatically run inside PostGreSQL?
EDIT:
Forgot to mention: after the first command of my script executes, I can then type \q to leave PostGreSQL and then the terminal outputs this:
-bash: c: command not found
Which, I think, indicates that the terminal interrupts its current process to actually run PostGreSQL and, on exit, it resumes the script, moving onto the second command, which fails because \c means nothing as a shell command.
While connected to the database, run:
ift2935=> ALTER ROLE <MY_USERNAME> SET search_path TO inscriptions_devoir;
This is your database user. Unless PGUSER is set, this should be the same as your operating system user, but you can always find it with SELECT current_user;.
Then the setting will automatically be active the next time you connect.
In your shell script, change the call to
psql -h postgres -d ift2935
Alternatively, and slightly better in my opinion, is the following, more complicated procedure:
Edit the file .bash_profile in your home directory and add
export PGHOST=postgres
export PGDATABASE=ift2935
Then disconnect and reconnect (this file is executed when you start a login shell).
Instead of running . sql.sh, simply type psql, which is less cumbersome.
Off topic: It is widely held that industriousness is the motor of progress. Nothing could be farther from the truth. Laziness is the mother of invention, specifically laziness paired with curiosity. If you plan to go into the computer engineering business, I promise you a bright future.
I think you should try using the pgpass file.
https://www.postgresql.org/docs/current/libpq-pgpass.html

PostgreSQL COPY FROM PROGRAM using ImageMagick

I have 1000 images, and thanks to ImageMagick I can retrieve a lot of information regarding an image by writing "identify -verbose [PATH OF IMAGE]" in the cmd.
I installed ImageMagick with 'legacy on' , to access individual tools rather than the monolithic version of the library.
If I write "identify -verbose C:\\temp\\cbirCorel10k\\1.jpg" in the command prompt it works perfectly, outputting data I need.
My problem is when I insert this code into PROGRAM of PostgreSQL like so :
copy manyline(txt)
from program 'identify -verbose C:\\temp\\cbirCorel10k\\1.jpg'
It gives me this error, and please note that I do have permissions on the image and parent folders to be accessed:
ERROR: program "identify -verbose C:\temp\cbirCorel10k\1.jpg"
failed SQL state: 38000 Detail: child process exited with exit code
1
I want that the output from that command line, is inputted into the table 'manyline' under column 'txt'.
Please note that the following code works well, but I want to make use of the PROGRAM function.
copy manyline(txt)
from 'C:\\temp\\something.txt'
The postgresql server needs permissions to run that program and read that file. it usually runs under username postgres (unless they've changed that recently). this is a "service user" and can be hard to find in the windows GUI; especially on "home" editions of windows. I can't say for sure if granting NETWORK SERVICE access is enough.
easiest solution is to use the psql command-line interface and do
\copy manyline(txt) from program 'identify -verbose C:\\temp\\cbirCorel10k\\1.jpg'
\copy is a psql built-in which runs the command (opens the file etc) as the current user, instead of asking the server to run it. this also works well where the server is not local.

Script to add group/user to "log on as a service"

I am trying to create a script that add a certain user/group to "log on as a service" in my Windows 2008 box. However I have tried using the ntrights.exe, downloaded it and ran the line ntrights +r SeInteractiveLogonRight -u CSSGroup in cmd but it failed because of the incompatibility.
Can someone help me or point me in any other useful direction?
These things are stored in the registry. Only System has access. So use psexec
psexec -s -i <your script>
to run script as system giving you access to the security info (which you'll have to turn on and compare to regkeys when turned off as they are in binary structures).
You can also take ownership of the keys and give yourself permission to access.
HKEY_LOCAL_MACHINE\SECURITY

Find pg_dump.exe path in NSIS to call with Exec function (or is there a better way to talk to postgres?)

I am building a Windows 7 installer with NSIS for internal company use.
One step in the install is to backup a Postgres DB using pg_dump.exe, then restore a file packaged in the installed usign pg_restore.exe. These two executables are normal helper tools include with any Postgres installation, so they can be expected to exist on the user's machine.
I want to execute this operation like so:
ExecWait 'C:\path\to\file\pg_dump.exe --host localhost --port 5432 --username "postgres" --no-password --format custom --blobs --verbose --file $OUTDIR/myDB.backup myDB' $0
DetailPrint 'Backup DB process return $0'
But the problem I'm having is that the path of executables differs from machine to machine. So I am trying to run a search operation to find the files. Such as this
${Locate} "C:\" "/L=F /M=pg_dump.exe" "locateBackup"
Or this (using locate plugin)
${locate::Open} "C:\" `/F=1 /D=0 /X=exe /-PN="Oracle" /-PF="$WINDIR\System|$WINDIR\System32|$WINDIR\Help" /N=pg_dump.exe /B=1` $0
${locate::Find} $0 $1 $2 $3 $4 $5 $6
Both of those methods fail on Windows 7. The installer crashes when the search traverses certain directories; I'm not sure why.
Next thing I'd like to try is to look up the executables location in the Windows registry, with the NSIS command ReadRegStr, maybe something like this
ReadRegStr $0 HKLM Software\pg_dump ""
DetailPrint "Its installed at: $0"
But I can't find the right registry key for looking up pg_dump (or pg_restore).
Is there a way to identify the path of installed executables on Windows 7 using native NSIS functions?
Or is there a better way to backup and restore Postgres databases with NSIS installers?
You can find the installation directory (if it was installed through the one-click installer) in
HKLM\PostgreSQL\Installation\postgresql-9.1\Base Directory
apparently this key is version dependent. And there can be more than one entry (if more than one version is installed). So you will need to enumerate the entries and pick whatever version fits you.
Then append \bin to the value obtained from "Base Directory" and pg_dump/pg_restore should be there.

Unable to run PostgreSQL as Windows service

I had this in my Windows services:
C:/Program Files/PostgreSQL/8.4/bin/pg_ctl.exe runservice -N "postgresql-8.4" -D "D:/PostgreSQL/8.4/data" -w
It never finishes executing. But if I did this on the dos shell:
C:/Program Files/PostgreSQL/8.4/bin/pg_ctl.exe start -N "postgresql-8.4" -D "D:/PostgreSQL/8.4/data" -w
Notice that I only changed the "runservice" to "start" and it works just fine.
Any idea?
The command runservice can only be executed by the service manager
in order to fix my localhost windows 7 to start postgres as a service
i used the following command to start the data
pg_ctl -D "C:\Program Files\PostgreSQL\9.1\data" start
Then checked the status for errors
pg_ctl -D "C:\Program Files\PostgreSQL\9.1\data" status
if you get error 1063 , its more than likely permissions, i executed the following command
cacls "C:\Program Files\PostgreSQL\9.1\data" /E /T /C /G postgres:F
then reran the start/status, it showed everything fine, but still service manager would not start the service
So, in Services->postgresql->options->logon i set the log on as the Local system account instead of the postgres user, and voila it worked
this happened to me because i set my data directory to be somewhere the postgres windows user account didn't have access to.
I had this problem in Windows after a system crash. Running the first command showed invalid data in C:\Program Files\PostgreSQL\9.1\data\postmaster.pid. Deleting that file did the trick. Reference.
I faced the same issue after moving manually the database data files (PG_DATA directory) without recreating all the necessary permissions.
Here is how I solved my issue:
1. Check permissions on old PG_DATA directory:
cacls "c:\path\to\old\pgdata\dir"
2. Check permissions on new PG_DATA directory:
cacls "d:\path\to\NEW\pgdata\dir"
3. Compare outputs from 1. and 2.
Find the differences between users and/or permissions then synchronize them.
Nota: I found it easier to use explorer for the synchronization step rather than using cacls directly from the command line.
If you changed pg_hba.conf , maybe you missed somewhere in file. For example there must be CIDR after IP in that file. It must be like 192.168.1.100/32
If you forgot to put 32, then server doesnt restart.
Investigation of startup logs could be a clue. For the case problem is in the pg_hba.conf you could see something like this:
2018-11-13 00:39:34.841 PST [8284] FATAL: could not load pg_hba.conf
2018-11-13 00:39:34.842 PST [8284] LOG: database system is shut down
You need to check your logfiles and the windows eventlog for some hint of what the problem is. If there is nothing at all there, you need to break out something like Process Monitor and get a stacktrace of where it's hung.
I have had this issue in the past, and it was that the installer did not set up the permissions correctly for the user that the service was to run as.
I've also ran into this problem with postgresql throwing and error after trying to initialize the database cluster. After analyzing the log files and running command line scripts for 4 hours I've got the solution to anyone running into this problem for Windows Versions.
This is not a detailed description as to why its happening. I've installed odoo 10, 11, 12 and 13 numerous times on countless client servers and windows systems and this is the first time I've ever ran into this problem. I cant say if its because I have MS VS Enterprise installed and Android Studio on this machine or what. But Below is the easy answer on how to fix it and initialize the cluster and create the database files in the data folder.
Open the data folder for postgresql. - For Odoo installs it will normally be "C:\Program Files (x86)\Odoo 13.0\PostgreSQL" Unless you chose another location when installing.
Remove any or all files from this folder - If not you will get an error when running initdb.exe
Right click the data folder and open up the properties for it. Click on the Security tab and then click the advanced button on the bottom.
You need to change the owner of this folder to openpgsvc. Click Change and type in openpgsvc and click ok. Once done click the check box below saying that you want this change to affect containers with this container as well.
Then on the Permissions tab click the add button on the bottom. You need to add openpgsvc as a user and give this user full rights. Click apply and and ok to close out of all the folder properties.
Now you need to open cmd.exe - Once open we are going to call initdb.exe and pass some values to it as well.
First run chdir and change the working directory to the location of initdb.exe. For me, running odoo 13 on a windows 10 machine the location is this..
"C:\Program Files (x86)\Odoo 13.0\PostgreSQL\bin"
There is one variable that need to be passed as well to make this work here is the list. NEEDS TO BE INCLUDED IN THE CALL TO initdb.exe
Postgres Data Dir: "C:\Program Files (x86)\Odoo 13.0\PostgreSQL\data"
The End Result with the parameter would look like this for my installation:
"C:\Program Files (x86)\Odoo 13.0\PostgreSQL\bin\initdb.exe" -D "C:\Program Files (x86)\Odoo 13.0\PostgreSQL\data"
Hit Enter and let it rip. The output of this command should look like this below.
Cmd.exe running initdb.exe script
Make sure there is no buggy empty file Program at C:\ like C:\Program
In this case, explorer will warn whenever you log on into Windows.
File Name Warning
-----------------
There is a file or folder on your computer called "C:\Program" which
could cause certain applications to not function correctly. Renaming it
to "C:\Program1" would solve this problem. Would you like to rename
it now?
Installing PostgreSQL 10 On Windows 7 (yes the clock is ticking...). I first tried the latest version 11 which completely failed to install... not a good sign for Windows users. Anyway.
Quick answer: Change the account in the Windows Services panel from Network to Local.
Details of my case
During installation I created/selected a data folder in the user profile folder, because obviously the folder suggested by default, within the program folder, wouldn't work, and if it worked it would be a very idea to put data here (I don't know whether it's usual to do that on Unix/Linux, but for Windows it's it's not allowed for a long time).
At the end (when populating the data cluster) I received an error:
Failed to load SQL Modules into database Cluster
but the installation was able to complete. I found two pages about previous error, here and here, but they didn't seem relevant to my case, so I just started pgAdmin and, on the left "browser", saw the server wasn't active.
I tried to start it from here (had to type the main password), but it went inactive immediately again. So I tried to use the Windows services panel to start "postgresql-x64-10", no joy. I copied the command from this panel and pasted it into a Windows console (cmd.exe) where I finally received this
error 1063.
Searching I found this related question, and was convinced the problem was about permissions.
Solution working for my case
In the services panel I changed the account used to start the service from Network Service to Local System as suggested in a comment by #AlexanderRios.
sc create "postgresql-9.2" binPath= "\"C:/Program Files (x86)/PostgreSQL/9.2/bin/pg_ctl.exe\" runservice -N \"postgresql-9.2\" -D \"C:/Program Files (x86)/PostgreSQL/9.2/data\" -w" DisplayName= "postgresql-9.2" start= auto
Try this on CMD run as Administrator
(Add your parameters depend on your version)
Stop all postgres processes
Go to the postgres data folder (C:\Program Files\PostgreSQL\9.6\data)
Delete the postmaster.opts and postmaster.pid files
From the control panel, in administrative
tools and the services console start the postgres service
open pgAdmin III and then in right pane find server then just right click and connect, enter the password. after connected go to the browser and refresh ODOO. Problem solved.
See image to get better understanding