delphi application has permissions issues. Why? - delphi

Delphi 2010
Windows 7 - 64 bit.
I have an app which is reasonably trivial. It is a database app. It starts, finds it's current directory, looks for a database file IN THAT DIRECTORY, opens it, and displays some data. It works fine on my dev computer. I take it to another computer, also Windows 7, 64 bit, and I get an error. (Specifically from the database library - Component Ace - saying that a column doesn't exist). I have to believe this is a generic access error. When I right click on the desktop icon, and choose RUN AS ADMINISTRATOR, it runs fine. I have not explicitly locked anything down. I am on the computer as the Admin user. It is Admin that has installed the app. I am trying to distribute this app to multiple people. The install routine I am using is InnoSetup. What type of permission problem as I running into?
For completeness sake, I am including the INNO SETUP.iss file.
Thanks
GS
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "DocAssist"
#define MyAppVerName "DocAssist 3.2"
#define MyAppPublisher "GS"
#define MyAppExeName "DocAssist.exe"
[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{6F34D198-14A0-4398-8E82-34232956CC5B}
AppName={#MyAppName}
AppVerName={#MyAppVerName}
AppPublisher={#MyAppPublisher}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
AllowNoIcons=yes
OutputDir=D:\Projects\DocAssist\DISTR
OutputBaseFilename=DocAssistV3Setup
Compression=lzma
SolidCompression=yes
AppCopyright=GS
VersionInfoVersion=3.2
[Languages]
Name: english; MessagesFile: compiler:Default.isl
[Tasks]
; Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked
Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons};
[Files]
Source: D:\Projects\DocAssist\DISTR\DocAssist.exe; DestDir: {app}; Flags: ignoreversion
Source: D:\Projects\DocAssist\DISTR\DocAssist.ABS; DestDir: {app}; Flags: ignoreversion
Source: D:\Projects\DocAssist\DISTR\StopWords.txt; DestDir: {app}; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
Source: DocAssist Version 3_2.pdf; DestDir: {app}; Flags: isreadme
; Add-in dll
Source: D:\Projects\DocAssist\DISTR\DocAssistCom.dll; DestDir: {app}; Flags: regserver
Source: D:\Projects\DocAssist\DISTR\gdiplus.dll; DestDir: {app}; Flags: ignoreversion
[Icons]
Name: {group}\{#MyAppName}; Filename: {app}\{#MyAppExeName}
Name: {group}\{cm:UninstallProgram,{#MyAppName}}; Filename: {uninstallexe}
Name: {commondesktop}\{#MyAppName}; Filename: {app}\{#MyAppExeName}; Tasks: desktopicon
[Run]
Filename: {app}\{#MyAppExeName}; Description: {cm:LaunchProgram,{#MyAppName}}; Flags: nowait postinstall skipifsilent
[Registry]
Root: HKLM; Subkey: SOFTWARE\DocAssist; ValueType: none; Permissions: admins-full; Flags: uninsdeletekey createvalueifdoesntexist;
Root: HKLM; Subkey: SOFTWARE\DocAssist; ValueType: string; ValueName: InstallDir; ValueData: {app}; Permissions: admins-full; Flags: uninsdeletekey createvalueifdoesntexist

You should not write to files in your program files directory. This has been deprecated since Windows 95, but starting with Windows Vista it has become more strict and writing there is not allowed by default, unless you are an administrator.
There are many other places you can write to, and App Data is a commonly used folder, as is My Documents. You can use the SHGetSpecialFolderLocation api to find the exact location of these special folders (because it ma differ per installation).
B.t.w. if you have to use the application directory, resort to Application.ExeName or ParamStr(0) rather than on the current directory.

Related

Electron Build Windows Folder Structure

Given an application made in electron. The folder structure would look something like:
App
- assets
-models
- exe files
index.html
main.js
When executing the build following the recommendation of the site by entering the following command:
electron-packager . --overwrite --asar=true --platform=win32 --arch=ia32 --icon=assets/icons/win/icon.ico --prune=true --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName="Electron Tutorial App"
The electron v.1.7.9 creates the build correctly, however it inside the release-builds / resources folder the app.asar file, so all the content that was inside my models folder becomes inaccessible. Inside this folder were .exe files that should be run on demand.
The system then looks for the files in the following url: parth_do_projeto / resources / app.asar / assets / models /, that is, it considers that the app.assar is a folder, but after the app.asar build is a file.
Since there were .exe files inside the original folder, the app.asar can not absorb executables.
What would be the way I keep these .exe files? If you build the build without the --asar parameter, the program works correctly, enter, all my project folder / source code is exposed.
My question is what is the best way to generate the build, keeping the code closed and making use of .exe files?
The short answer to your question is to use the unpackDir option for the asar option inside of electron-packager. Here is a sample of what this might look like:
'use strict';
... ...
var packager = require('electron-packager');
var electronPackage = require('electron/package.json');
var pkg = require('./package.json');
// pull the electron version from the package.json file
var electronVersion = electronPackage.version;
... ...
var opts = {
name: pkg.name,
platform: 'win32',
arch: 'ia32', // ia32, x64 or all
dir: './', // source location of app
out: './edist/', // destination location for app os/native binaries
ignore: config.electronignore, // don't include these directories in the electron app build
icon: config.icon,
asar: {unpackDir: config.excludeFromASAR}, // compress project/modules into an asar blob excluding some things.
overwrite: true,
prune: true,
electronVersion: electronVersion , // Tell the packager what version of electron to build with
appCopyright: pkg.copyright, // copyright info
appVersion: pkg.version, // The version of the application we are building
win32metadata: { // Windows Only config data
CompanyName: pkg.authors,
ProductName: pkg.name,
FileDescription: pkg.description,
OriginalFilename: pkg.name + '.exe'
}
};
// Build the electron app
gulp.task('build:electron', function (cb) {
console.log('Launching task to package binaries for ' + opts.name + ' v' + opts['appVersion']);
packager(opts, function (err, appPath) {
console.log(' <- packagerDone() ' + err + ' ' + appPath);
console.log(' all done!');
cb();
});
});

How to set a global environment variable from Inno Setup installer?

How do I set a global environment variable in Inno Setup?
Background: I am using the Inno install utility and need to set a global environment variable before I do the actual install.
Try this:
[Registry]
Root: HKCU; Subkey: "Environment"; ValueType:string; ValueName: "VARIABLE_NAME"; \
ValueData: "new_value"; Flags: preservestringtype
You might need to add this:
[Setup]
; Tell Windows Explorer to reload the environment
ChangesEnvironment=yes
Alternatively try:
[Run]
Filename: "{app}\MyProg.exe"; BeforeInstall: SetEnvPath
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
function SetEnvironmentVariable(lpName: string; lpValue: string): BOOL;
external 'SetEnvironmentVariable{#AW}#kernel32.dll stdcall';
procedure SetEnvPath;
begin
if not SetEnvironmentVariable('VARIABLE_NAME', 'new_value') then
MsgBox(SysErrorMessage(DLLGetLastError), mbError, MB_OK);
end;
Reference: Inno Setup Frequently Asked Questions - Setting Environment Variables
If the variable change is not propagated (see Environment variable not recognized [not available] for [Run] programs in Inno Setup)
[Run]
...; AfterInstall: RefreshEnvironment
[Code]
const
SMTO_ABORTIFHUNG = 2;
WM_WININICHANGE = $001A;
WM_SETTINGCHANGE = WM_WININICHANGE;
type
WPARAM = UINT_PTR;
LPARAM = INT_PTR;
LRESULT = INT_PTR;
function SendTextMessageTimeout(hWnd: HWND; Msg: UINT;
wParam: WPARAM; lParam: PAnsiChar; fuFlags: UINT;
uTimeout: UINT; out lpdwResult: DWORD): LRESULT;
external 'SendMessageTimeoutA#user32.dll stdcall';
procedure RefreshEnvironment;
var
S: AnsiString;
MsgResult: DWORD;
begin
S := 'Environment';
SendTextMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
PAnsiChar(S), SMTO_ABORTIFHUNG, 5000, MsgResult);
end;
More details:
Inno Setup: Setting a System Environment Variable
Under more modern (in other words, proper) operating systems, such as
Windows 2000, XP, and Windows 2003 Server, environment variables are
stored in the Registry under the following key:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\
Environment
Variables are added by creating a new value under this key or by
modifying a value if it already exists. To delete a variable, you
simply delete its Registry value, unless you are removing part of an
expanded value, such as PATH, in which case you only remove the part
you want.
At this point, Windows will not be aware of your changes unless you
log off or reboot. To get around this, SetEnv will broadcast a
WM_SETTINGCHANGE to all of the windows in the system. This allows
other running applications—for example, Explorer.exe—to be notified of
your change. If you run SetEnv from a command prompt, this will not
update the environment variable for the current DOS window. This is
mainly due to the fact that a process (SetEnv) cannot change the
environment of its parent (The Command Prompt). However, any new
DOS/Command Prompts that you open will show the new variable/value.
The solutions in #Adrian's answer (actually copied from #TLama's answer to similar question) are correct for many situations.
But it won't work for [Run] tasks with runasoriginaluser flag (what is implied by postinstall flag). I.e. the variable won't be propagated to an application run with common "Run My Program" check box on the "Finished" page.
The reason is that the tasks with runasoriginaluser are executed by a un-elevated hidden parent process of the Inno Setup installer. The SetEnvironmentVariable will change environment for the installer, but not for its parent process. Unfortunately, the parent process of the installer cannot be controlled (imo).
As a workaround, to set the variable for the runasoriginaluser tasks, you have to inject an intermediate process between the installer parent process and the task, and have the intermediate process set the variable.
Such an intermediate process can easily be the cmd.exe with its set command:
[Run]
Filename: "{cmd}"; Parameters: "/C set MYVAR=MyValue & ""{app}\MyProg.exe"""; \
Description: "Run My Program"; Flags: postinstall runhidden
The runhidden flag hides the cmd.exe console window, not the application (assuming it's a GUI application). If it's a console application, use start to start it in its own (visible) console window.
What would be wrong with running two setup.exe with the first one doing the setting of the environment variables, and the second doing the things needed for the true setup. The first one would be run with setup.exe /VERYSILENT
I am doing to add an system wide environment variable:
[Setup]
; Tell Windows Explorer to reload the environment
ChangesEnvironment=True
[Registry]
Root: "HKLM"; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; ValueName: "EGPL_GeoLibrarian_Drive"; ValueData: "L"; Flags: createvalueifdoesntexist preservestringtype

Is there a handy tool for just localizing APKs (resources.arsc) besides apktool?

I wanted to localize my Android 4.0.4 (3G) Pad into Uighur language.
I decompiled, added a new values-ug-rCN translation in res folder, compiled back to get resources.arsc file.
All APKs went fine excep Phone.apk.
I can decompile to get xmls, but when compiling, it gave me the following errors:
(The error was reproduced using the latest ApkTool1.5.2, both with/without installing framework.apk)
E:\apktool152\x>apktool.bat if framework-res.apk
I: Framework installed to: C:\Documents and Settings\Administrator\apktool\frame
work\1.apk
E:\apktool152\x>apktool d Phone.apk
I: Baksmaling...
I: Loading resource table...
W: Skipping "android" package group
I: Loaded.
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: C:\Documents and Settings\Administrator\apk
tool\framework\1.apk
I: Loaded.
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Done.
I: Copying assets and libs...
E:\apktool152\x>apktool b Phone
I: Checking whether sources has changed...
I: Smaling...
I: Checking whether resources has changed...
I: Building resources...
E:\apktool152\x\Phone\res\values-de\strings.xml:194: error: Multiple substitutio
ns specified in non-positional format; did you mean to add the formatted="false"
attribute?
E:\apktool152\x\Phone\res\values-de\strings.xml:195: error: Unexpected end tag s
tring
E:\apktool152\x\Phone\res\values-es\strings.xml:194: error: Multiple substitutio
ns specified in non-positional format; did you mean to add the formatted="false"
attribute?
E:\apktool152\x\Phone\res\values-es\strings.xml:195: error: Unexpected end tag s
tring
E:\apktool152\x\Phone\res\values-es-rUS\strings.xml:197: error: Multiple substit
utions specified in non-positional format; did you mean to add the formatted="fa
lse" attribute?
E:\apktool152\x\Phone\res\values-es-rUS\strings.xml:198: error: Unexpected end t
ag string
E:\apktool152\x\Phone\res\values-it\strings.xml:194: error: Multiple substitutio
ns specified in non-positional format; did you mean to add the formatted="false"
attribute?
E:\apktool152\x\Phone\res\values-it\strings.xml:195: error: Unexpected end tag s
tring
aapt: warning: string 'modem_power' has no default translation in E:\apktool152\
x\Phone\res; found: en_GB zh_CN
aapt: warning: string 'modem_power_summary' has no default translation in E:\apk
tool152\x\Phone\res; found: en_GB zh_CN
Exception in thread "main" brut.androlib.AndrolibException: brut.androlib.Androl
ibException: brut.common.BrutException: could not exec command: [aapt, p, --min-
sdk-version, 15, --target-sdk-version, 15, -F, C:\DOCUME~1\ADMINI~1\LOCALS~1\Tem
p\APKTOOL187345540728029844.tmp, -0, arsc, -I, C:\Documents and Settings\Adminis
trator\apktool\framework\1.apk, -S, E:\apktool152\x\Phone\res, -M, E:\apktool152
\x\Phone\AndroidManifest.xml]
at brut.androlib.Androlib.buildResourcesFull(Androlib.java:358)
at brut.androlib.Androlib.buildResources(Androlib.java:283)
at brut.androlib.Androlib.build(Androlib.java:206)
at brut.androlib.Androlib.build(Androlib.java:176)
at brut.apktool.Main.cmdBuild(Main.java:228)
at brut.apktool.Main.main(Main.java:79)
Caused by: brut.androlib.AndrolibException: brut.common.BrutException: could not
exec command: [aapt, p, --min-sdk-version, 15, --target-sdk-version, 15, -F, C:
\DOCUME~1\ADMINI~1\LOCALS~1\Temp\APKTOOL187345540728029844.tmp, -0, arsc, -I, C:
\Documents and Settings\Administrator\apktool\framework\1.apk, -S, E:\apktool152
\x\Phone\res, -M, E:\apktool152\x\Phone\AndroidManifest.xml]
at brut.androlib.res.AndrolibResources.aaptPackage(AndrolibResources.jav
a:357)
at brut.androlib.Androlib.buildResourcesFull(Androlib.java:336)
... 5 more
Caused by: brut.common.BrutException: could not exec command: [aapt, p, --min-sd
k-version, 15, --target-sdk-version, 15, -F, C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\
APKTOOL187345540728029844.tmp, -0, arsc, -I, C:\Documents and Settings\Administr
ator\apktool\framework\1.apk, -S, E:\apktool152\x\Phone\res, -M, E:\apktool152\x
\Phone\AndroidManifest.xml]
at brut.util.OS.exec(OS.java:89)
at brut.androlib.res.AndrolibResources.aaptPackage(AndrolibResources.jav
a:355)
... 6 more
E:\apktool152\x>
I just wanted to translate the xmls inside values, and compile back to get resources.arsc.
I can go past the errors relevant to values xmls, by removing de, es, it translations if need be.
But I don't know the other errors.
So how can I solve this problem?
Or is there another alternative tools just for the task?
I switched to a modefied version of ApkTool called something like ApkTool 1.5 b-sf found in a Chinese site, and after installing framework-res.apk, it complied correctly!
Hope this helps some people.

Inno Setup Registry entry for custom URL protocol

I'm hoping someone can help me translate the following into a correctly formatted InnoSetup [Registry] entry to use in my InnoSetup Installer? The goal here is to create a new custom URL protocol on the user's machine.
HKEY_CLASSES_ROOT
ctp
(Default) = "URL:Alert Protocol"
URL Protocol = ""
DefaultIcon
(Default) = "myapp.exe"
shell
open
command
(Default) = "C:\Program Files\MyApp\myapp.exe"
I read through the InnoSetup Help doc but couldn't figure out how to translate the above into a proper InnoSetup Registry section:
[Registry]
Root: HKCR; Subkey: ".....etc.
The final result after the installer runs is that the user clicks on a link on a web site formatted as "ctp://myapp.exe" and that local app will launch on the user's machine. Am I approaching this correctly?
Thanks very much for any responses.
Try it this way:
[Registry]
Root: HKCR; Subkey: "ctp"; ValueType: "string"; ValueData: "URL:Custom Protocol"; Flags: uninsdeletekey
Root: HKCR; Subkey: "ctp"; ValueType: "string"; ValueName: "URL Protocol"; ValueData: ""
Root: HKCR; Subkey: "ctp\DefaultIcon"; ValueType: "string"; ValueData: "{app}\YourApp.exe,0"
Root: HKCR; Subkey: "ctp\shell\open\command"; ValueType: "string"; ValueData: """{app}\YourApp.exe"" ""%1"""
#TLama's answer is correct, but might not work for everybody.
HKCU is actually a merge between HKLM\Software\Classes and HKCU\Software\Classes and writting to HKCU directly may require administrative access on some systems, thus it's not compatible with InnoSetup's PrivilegesRequired=lowest. The official HKCU documentation explains:
If you write keys to a key under HKEY_CLASSES_ROOT, the system stores
the information under HKEY_LOCAL_MACHINE\Software\Classes. If you
write values to a key under HKEY_CLASSES_ROOT, and the key already
exists under HKEY_CURRENT_USER\Software\Classes, the system will store
the information there instead of under
HKEY_LOCAL_MACHINE\Software\Classes.
The alternative is HKA (see [Registry] section) which resolves to HKLM in administrative installs and HKCU in non-administrative ones. The documentation also states that:
HKCU and HKA should only be used for settings which are compatible
with roaming profiles.
Using HKCR is not recommended, use HKA with the Subkey parameter set
to "Software\Classes" instead.
So, if you care about non-administrative installs, your [Registry] section should look like this:
[Registry]
Root: HKA; Subkey: "Software\Classes\ctp"; ValueType: "string"; ValueData: "URL:Custom Protocol"; Flags: uninsdeletekey
Root: HKA; Subkey: "Software\Classes\ctp"; ValueType: "string"; ValueName: "URL Protocol"; ValueData: ""
Root: HKA; Subkey: "Software\Classes\ctp\DefaultIcon"; ValueType: "string"; ValueData: "{app}\myapp.exe,0"
Root: HKA; Subkey: "Software\Classes\ctp\shell\open\command"; ValueType: "string"; ValueData: """{app}\myapp.exe"" ""%1"""
For more info see the links above, and also the following ones:
InnoSetup - Creating File Associations
InnoSetup - Non Administrative Install Mode
Microsoft - Registering an Application to a URI Scheme

Check if psqlodbc has been unistalled or not from the system

Im working on software that required psqlodbc drivers and postgresSQl 9.0 database,
we have a installer designed using delphi 7 to install both psqlodbc and postgreSQl 9 silently
one after the other on click of a single button, here everything runs fine,
but the problem is during uninstall,
i first want to unistall psqlodbc and then postgreSQl 9 also on a sinlge button click,
i want to run the postgreSQl 9 unistaller using shellpApi only after psqlodbc has been unstalled,
as of now im checking for 'cmd.exe' is running or not to start postgreSQl uninstaller, but sometimes after unstalling psqlodbc the 'cmd.exe' remain n the postgreSQl unistaller cannot be executed,
so any please tell me
how to check if psqlodbc uninstall process is completely.
the files are
1.psqlodbc.msi
2.postgresql-9.0.2-1-windows.exe
install/uninstall is handled wit bat file
thanks in advanced:)
You can check registry if driver is available. When it is installed you will get:
c:\tmp\pg>reg query "hklm\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI"
! REG.EXE VERSION 3.0
HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI
APILevel REG_SZ 1
ConnectFunctions REG_SZ YYN
Driver REG_SZ C:\Program Files\psqlODBC\0900\bin\psqlodbc30a.dll
DriverODBCVer REG_SZ 03.00
FileUsage REG_SZ 0
Setup REG_SZ C:\Program Files\psqlODBC\0900\bin\psqlodbc30a.dll
SQLLevel REG_SZ 1
UsageCount REG_DWORD 0x1
And when you unistall it you will get (localized version):
c:\tmp\pg>reg query "hklm\SOFTWARE\ODBC\ODBCINST.INI\PostgreSQL ANSI"
Błąd: system nie może odnaleźć określonego klucza rejestru lub wartości.
c:\tmp\pg>
(this menas: Error: system cannot find key or value in registry)
See: reg /? on how to use it and for return code you can use in batch.
You can also search registry uninstall information under HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall
I got how to check if psqlodbc has been uninstalled completely so that i can start unistalling postgres
For that i found the solution
On stackoverflow itself
function TForm1.ExecAndWait(const CommandLine: string) : Boolean;
var
StartupInfo: Windows.TStartupInfo; // start-up info passed to process
ProcessInfo: Windows.TProcessInformation; // info about the process
ProcessExitCode: Windows.DWord; // process's exit code
begin
// Set default error result
Result := False;
// Initialise startup info structure to 0, and record length
FillChar(StartupInfo, SizeOf(StartupInfo), 0);
StartupInfo.cb := SizeOf(StartupInfo);
// Execute application commandline
if Windows.CreateProcess(nil, PChar(CommandLine),
nil, nil, False, 0, nil, nil,
StartupInfo, ProcessInfo) then
begin
try
// Now wait for application to complete
if Windows.WaitForSingleObject(ProcessInfo.hProcess, INFINITE)
= WAIT_OBJECT_0 then
// It's completed - get its exit code
if Windows.GetExitCodeProcess(ProcessInfo.hProcess,
ProcessExitCode) then
// Check exit code is zero => successful completion
if ProcessExitCode = 0 then
Result := True;
finally
// Tidy up
Windows.CloseHandle(ProcessInfo.hProcess);
Windows.CloseHandle(ProcessInfo.hThread);
end;
end;
end;
so step # 1
if ExecAndWait('msiexec /x C:\psqlodbc09\psqlodbc.msi') then
begin
//uninstall postgresNow...!!
end;

Resources