Inno Setup referencing a Registry key containing braces using the {reg} constant - inno-setup

I am trying to use the {reg} constant for DefaultDirName where it references a path that contains braces:
DefaultDirName={reg:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{3E4A76D9-EC0E-4806-915C-8BC2B3C0011B},InstallLocation}
However, this does not work as the compiler thinks the GUID in the path is a constant. If I try and escape the brace with another brace as suggested (see below) this does not work either and gives an 'Invalid registry constant' error.
DefaultDirName={reg:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{{3E4A76D9-EC0E-4806-915C-8BC2B3C0011B},InstallLocation}
I have tried all combinations I can think of to try and escape this and get the compiler to recognise this, including using %7d to try and force a closing brace, as suggested in the documentation as well, but this does not seem to compile to a closing brace in this situation. Hopefully someone can advise how to get the compiler to recognise this Registry location or at least tell me whether I am attempting to do something that is not possible. If so, is there another way to attempt this? Given that I have also already tried:
DefaultDirName={code:GetExistingInstallPath}
[Code]
function GetExistingInstallPath(Param: String): String;
begin
RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F34A6950-7E0E-4F92-8B0E-C552F4989DA}',
'InstallLocation', strExistingInstallPath);
Result := strExistingInstallPath;
end;
which does compile, but the strExistingInstallPath returns nothing and hovering over the {code:GetExistingInstallPath} returns an 'Exception: Cannot evaluate "code" constant because of possible side effects.' After a couple of hours trying to get this working, I am getting close to concluding that Inno Setup does not support Registry locations containing braces.
Note, that I need to read this Registry key as the software was not installed by Inno Setup and this is a patch to replace a file, so I need to know where it was originally installed to.

In case of using {reg:...} instead of closing } you have to use %7d
Example:
DefaultDirName={reg:HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\
{{‌​3E4A76D9-EC0E-4806-915C-8BC2B3C0011B%7d,InstallLocation}
When reading Registy in [Code] section if there is NO ExpandConstant used, you do not have to use double opening {{
Example:
RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\
{3E4A76D9-EC0E-4806-915C-8BC2B3C0011B}','InstallLocation', strExistingInstallPath);
P.S. Thanks #Tlama for pointing out my inexactness.

Related

How do I get the current working directory with the least amount of dependencies possible?

I have a Rust application which works as a shell. I want to get the working directory the user is in using as little dependencies as possible.
I tried using
let path = env::current_dir();
print!("{} > ",path.display());
But it gives me the following error: method not found in `Result<PathBuf, std::io::Error>'
I tried running this in the rust playground and it worked alright, so I was wondering if any of you could help me with this
You can use std::env::current_dir to get the current working directory.
You also need to use match, std::result::Result::unwrap, std::result::Result::expect, ?, or something else to handle the Err variant of the Result and access the value inside the Ok variant.

Inno installer - How to retrieve environment variables during install?

Is there a way to assign an environment variable to a variable on runtime? And then edit it?
So for instance, a clients computer has a program installed at c:\Company\CoolProgram and that folder location is in a variable called %InstallLocation%. So if you echo %InstallLocation% you will get c:\Company\CoolProgram
I want to install a plugin into c:\Company. So that CoolProgram and PlugIn will sit next to each other in c:\Company. I read that this could be done by defining a variable and assigning %installLocation% to it, then then trimming off \CoolProgram from the variable. So for example:
#define PluginLocation GetEnv('InstallLocation')
#define PluginLocation2 StringChange(PluginLocation, "\CoolProgram ", "")
So, PluginLocation2 = c:\Company, and that's good. Except this is going on during compile time. The build machines don't have this environment variable, plus not all clients are going to have the same installed location. Therefore %InstallLocation% is actually just empty, and therefore PluginLocation and PluginLocation2 are empty.
So I tried moving the variable definitions down into [Setup], hoping the environment variables would be looked up during runtime on the client. That didnt seem to work. I also tried into [Files] since I have files to move into the new folder, but [Files] appears to be during compile as well.
I think
procedure Test () ;
begin
MsgBox(ExtractFileDir(ExpandConstant( '{app}' ) ) , mbConfirmation, MB_YESNO ) ;
end;
is what You are looking for.
ExpandConstant( '{app}' ) will return location where application is installed.
And: ExtractFileDir will get c:\Company from c:\Company\CoolProgram.

Calling WriteRegMultiStr in NSIS properly

With version 3.02 of NSIS came the addition of the WriteRegMultiStr function. When the function is called in my script the script throws an error:
Usage: WriteRegMultiStr /REGEDIT5 rootkey subkey entry_name hex_string_like_660000000000
root_key=(HKCR[32|64]|HKLM[32|64]|HKCU[32|64]|HKU|HKCC|HKDD|HKPD|SHCTX)
The call itself looks like this:
WriteRegMultiStr /REGEDIT5 HKLM "System\CurrentControlSet\Services\SomeService" "DependsOnService" "service1 service2"
Since there is no documentation on this specific function which was added later on, long after WriteRegStr and WriteRegDWORD were available, I have to wonder - how does one use it?
So far with respect to entering REG_MULTI_SZ values I only found the directive to use a registry-NSIS -plugin. Yet the function exists, so how can it be used?
Addendum:
Encoding the string to hex and passing it with ot without quotation marks yields no desirable result either.
I was actually able to find an answer after digging through the depths of the internet. Since I don't think this has been answered on StackOverflow I will leave a response here, in case anyone wants to use this function.
The structure of the command as described in the opening post is basically correct, but the value must be encoded precisely. My command looks like this:
WriteRegMultiStr /REGEDIT5 HKLM "System\CurrentControlSet\Services\SomeService" "DependsOnService" 54,00,63,00,70,00,69,00,70,00,00,00,41,00,66,00,64
For anyone intending to test this string, this is
Tcpip
Afd
encoded in hexadecimal regedit format. Precisely this is Regedit Version 5.0 format, as opposed to REGEDIT4 format. A conversion editor can be used to achieve this, I used OTConvertIt.
The script should then compile, assuming you run NSIS version 3.02 or higher.
As you found out, the value data must be in the exact same format as .reg files from Windows 2000+.
The reason this instruction works this way is because it is actually the same as WriteRegBin under the hood and very little code was added to support this new functionality.
In the future you might be able to drop the /REGEDIT5 switch and give it plain strings but support for that has not been added yet.
The Registry plug-in does allow you to write these strings in a sane manner.

Inno Setup mixing parameters with Literal Quotes with other parameters

I want to run regedit.exe with some parameters, but one of them needs to have quotes around it and the other doesn't. If I try to compile the following I get an error about mismatched or misplaced quotes:
Filename: "regedit.exe"; Parameters: "/s" """{localappdata}\LEAP\OutlookRedemption\Outlook2013_C2R.reg"""
So would the following work? (I don't want to test this on my machine because these reg entries are for versions of Windows and office that I don't have)
Filename: "regedit.exe"; Parameters: """/s {localappdata}\LEAP\OutlookRedemption\Outlook2013_C2R.reg"""
Ideally you should convert the file into [Registry] entries rather than loading a REG file via regedit. This allows you to add support for uninstallation and filling in values based on user selection during the wizard, among other things.
But no, neither of the examples you have posted are correct. If you really want to still do it that way (which is not the ideal option), this would be how you'd need to do it:
Filename: "regedit.exe"; Parameters: "/s ""{localappdata}\LEAP\OutlookRedemption\Outlook2013_C2R.reg"""

Getting echofunc.vim to work

I came across echofunc.vim today (from a link in SO). Since I'm rubbish at remembering the order of function parameters, it looked like a very useful tool for me.
But the documentation is a bit lean on installation! And I've not been able to find any supplementary resources on the internet.
I'm trying to get it running on a RHEL box. I've copied the script into ~/.vim/plugin/echofunc.vim however no prompt when I type in a function name followed by '('. I've tried adding
let g:EchoFuncLangsUsed = ["php","java","cpp"]
to my .vimrc - still no prompting.
I'm guessing it needs to read from a dictionary somewhere - although there is a file in /usr/share/vim/vim70/ftplugin/php.vim, this is the RH default and does not include an explicit function list.
I'm not too bothered about getting hints on the functions/methods I've defined - just trying to get hints for the built-in functions. I can see there is a dictionary file available here which appears to provide the resources required for echofunc.vim, I can't see how I set this up.
TIA,
It expects a tags file, the last line of the description describes exactly how to generate it:
ctags -R --fields=+lS .
It works here with PHP but not with JS. Your mileage may vary.
I didn't know about this plugin, thanks for the info.
You should try phpcomplete.vim, it shows a prototype of the current function in a scratchpad. It is PHP only, though.

Resources