How can I use variable on NSIS include / to get another variable - nsis

Is there anyway to include file by mention it with variable? I mean
StrCpy $1 "bla.nsh"
!include $1
?
or maybe getting value of variable that called by another variable such as:
StrCpy $1 "EN"
StrCpy $2 ${LANG_${1}_WELCOME_MESSAGE}
?
Thanks.

Variables can only be used at runtime (running on the end-users machine), you need to use defines:
!define foo "bar"
!include "${foo}.nsh"
Edit:
You should be using the LangString instruction if you want to add custom translated strings, you can access a langstring at runtime with $(mystringid).

Actually, Anders right. Think about that, when the compiler compiling your code, it need to know which files it need to include with your EXE file.
About the variable, you can use only with defines. again, because when you are compiling, the compiler will compile all the needed (in use) variables / defines, and you can't tell him use one that never been declared.. its little different from server side languages because here you are compiling and pack your code into EXE file which is assembled in your computer.

Related

Registers like $0

Can someone explain and/or provide reference for understanding how NSIS registers work. For example, $0, $1. I see examples of using them.
Like {If} $0 == ''
Do something
I don't understand how you can put values into $0 or how values are there dynamically?
Please help, thank you.
From the NSIS Sourceforge docs, located here, Registers are already-defined variables available for use:
These variables can be used just like user variables, but are usually used in shared functions or macros. You don't have to declare these variables so you won't get any name conflicts when using them in shared code. When using these variables in shared code it's recommended that you use the stack to save and restore their original values. These variables can also be used for communication with plug-ins because they can be read and written by the plug-in DLLs.
Variables are handled like strings in NSIS, so to put a value into one of these Register variables, such as $0, you would do a command like:
StrCpy $0 WhatValueYouWantToBeInZero

What's the purpose of SetRegView lastused?

What's the purpose of SetRegView lastused?
The docs only talk about the 32/64 bit registry views, which I understand.
I thought it might be acting as a stack, like this person, being able to switch back to the view before the one currently in use. But the response to someone asking that question was:
No stack. Just the last one used.
In which case, if you're already in the 32 bit view, it's just equivalent to SetRegView 32? That doesn't seem right, what am I missing?
My google-fu only got me so far, finding this example from Mozilla (snippet from full script):
; Since the Maintenance service can be installed either x86 or x64,
; always use the 64-bit registry.
${If} ${RunningX64}
; Previous versions always created the uninstall key in the 32-bit registry.
; Clean those old entries out if they still exist.
SetRegView 32
DeleteRegKey HKLM "${MaintUninstallKey}"
; Preserve the lastused value before we switch to 64.
SetRegView lastused
SetRegView 64
${EndIf}
Then in a couple places later in the script:
${If} ${RunningX64}
SetRegView lastused
${EndIf}
Looking at the context there, if you call SetRegView 32, followed by SetRegView lastused, does that mean any future uses of SetRegView lastused will always result in the 32 bit registry view?
Not it is not a stack (but you could argue that it should be). It is simply the last set 32/64 state.
The SetRegView instruction is transformed into a NSIS opcode called EW_SETFLAG by MakeNSIS and its implementation in a installer looks something like this:
if (get_last_used)
g_exec_flags[flag] = g_exec_flags_last_used[flag] ; Restore previous
else
g_exec_flags_last_used[flag] = g_exec_flags[flag] ; Set last used
g_exec_flags[flag] = new_value ; Assign new value
These flags are also available to plug-ins in the exec_flags_t struct.
It is only useful if you mainly deal with one registry view but once in a while need to read from the other view:
Section
SetRegView 64
ReadRegStr $0 HKLM "Software\Foo" "Bar"
SetRegView lastused ; We are now back to the default view (32-bit in this case)
SectionEnd
or if you mainly use the 64-bit view:
Function .onInit
SetRegView 64
FunctionEnd
Section
SetRegView 32
ReadRegStr $0 HKLM "Software\Foo" "Bar"
SetRegView lastused ; We are now back to the previous view (64-bit in this case)
SectionEnd
I guess it is implemented this way because it simply reuses the lastused functionality used by other flags. It also simplifies things because it never has to allocate more memory. I also don't know why it is undocumented.

Error linking module in ocaml

I am a complete beginner with Ocaml programming and I am having trouble linking a module into my program. Actually I am doing some regular expression checking and I have written a function that basically tokenizes a string based on a separator string using the Str module . So i use the functions defined in the library like this:
Str.regexp_string /*and so on*/
However, when I try to compile the ml file, I get an error suggesting that I have an undefined global Str . We use List functions by typing in List.length and so on just like I did for Str without having to explicitly include the specific module. I tried
open Str;;
include Str;; /*None of these work and I still get the same error*/
However if in the toplevel I use
load "str.cma" /*Then the program works without problems*/
I want to include the module in the ml file because I have to in the end link 3 cmo's to get the final executable(which is not run in the toplevel). I know this is a really basic question but I am having trouble solving it. Thanks in advance.
You don't need to add anything in your file foo.ml.
You do need to tell the compiler where to find the Str module when compiling foo.ml . To do so, add it to the command line used to compile foo.ml:
ocamlc str.cma foo.ml
or
ocamlopt str.cmxa foo.ml
List and other modules from the standard library are accessible by default, so you don't need to tell the compiler about those often used modules.
Just add str to the libraries field of your dune file.
I think you need to use '-cclib ' compiler directive.
The module name shouldn't include the file ending like .cma.
Below is what I did when trying to use the unix and threads modules.
I think you need to use some combination of the 'custom' and 'cclib' compiler directives.
ocamlc -custom unix.cma threa.ml -cclib -lunix
Look at chapter 7 of this book for help:
http://caml.inria.fr/pub/docs/oreilly-book/html/book-ora063.html
And look at coverage of compiler directives here:
http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual022.html#c:camlc
ocamlc calc.ml str.cma -o calc
File "calc.ml", line 1:
Error: Error while linking calc.cmo:
Reference to undefined global `Str'
Code is very simple, to cut down scruff.
let split_into_words s =
Str.split ( Str.regexp "[ \n\t]+") s ;;
let _ =
split_into_words "abc def ghi" ;;
On ocaml 4.0.2. Obviously, there is a problem here, but I am too much of a beginner to understand what it is. From toplevel it seems work fine with #load "str.cma", so there is something here we don't understand. Anyone know what it is?

example of using external libraries or packages in Common Lisp

In Common Lisp, quicklisp is a popular library management tool. I'm going to use that tool and I'm going to try and use CL-WHO. I use the SBCL 1.0.57 implementation. I'm going to answer my own question below.
As a beginner, it's not clear how ASDF and quicklisp actually work together. And so it's not clear how to actually use packages or libraries that you've downloaded through quicklisp in an external source file. The quicklisp FAQ, at least at this moment, does not help. In python, it's incredibly simple: you can just put 'import somemodule' and life is great. Is there an equivalent for CL+quicklisp?
If you search, you find many results. Here are some of the most relevant ones I've found:
Lisp importing/loading file
How to use packages installed by quicklisp?
When I was reading through these originally, at least one question came to mind: do I actually have to care about ASDF if I'm using quicklisp? Quicklisp seems to be a higher level management tool. Other people suggest using quickproject. But is that really necessary?
The analogy to Python's imports is the system definition... well, this is a very loose analogy, but, it's the way to go. You declare dependencies in the system definition and then in source code you expect it to be there, so that if you later refer to the bits of the foreign code, you just do it.
Eg. in the system definition you might have: (usually it would be in my-program.asd file)
(defsystem :my-program
:version "0.0.1"
:serial t
:description "My program"
:components ((:file "some-source-file"))
;; `some-external-package' here is the "import", i.e. here you
;; declared that you will be using code from this package.
;; ASDF will generally "know" how to get the code of that package
;; from here on. But if it doesn't, then there are ways to "help it"
;; similar to how in Python there's a procedure to prepare your local
;; files to be used by easy_install
:depends-on (:some-external-package))
Later on in your code you just assume that the some-external-package is available to your program, e.g.:
(some-external-package:exported-symbol)
should just work. ("Your code" is the some-source-file.lisp, you've specified in the components).
This is the ASDF documentation on how to define systems
After you have this file in the place where ASDF might find it*, assuming you have ASDF installed (available to your Lisp, SBCL comes bundled with it), you'd load this system using (asdf:load-system :my-program) Explained here.
* - A quick way to test it would be to do
(push "/path/to/your/system/definition/" asdf:*central-registry*)
Download cl-who through the instructions on the quicklisp page and run this:
#!/usr/bin/sbcl --script
(load "~/quicklisp/setup.lisp")
(ql:quickload "asdf")
(asdf:load-system 'cl-who)
(with-open-file (*standard-output* "out.html" :direction :output)
(cl-who:with-html-output (*standard-output* nil :indent t)
(:html
(:head
(:title "Test page"))
(:body
(:p "CL-WHO is really easy to use")))))
To the beginner, or someone who's really lazy, there's no reason why you should have to write 3 lines at the top instead of just one (like in python).

How to use Protobuf-Net with MonoTouch?

Has anyone actually managed to accomplish this?
I tried the approach suggested here, but no matter how i generate the precompiled serializer, mtouch fails to copy it to the app bundle, thus resulting in a runtime exception. I think this happens because the resulting binary may not be compatible with MonoTouch.
I have tried the following:
1) I used the provided iOs and Mono binaries included in the latest (r450 as this time) build in order to generate the precompiled serializer.
2) I used the source code to produce two different assemblies, built for MonoTouch. The first assembly is built using the symbols FEAT_SAFE;MONOTOUCH;NO_RUNTIME and the second is built using the symbols FEAT_SAFE;MONOTOUCH;FEAT_COMPILER. I have defined the symbol MONOTOUCH and used it the same as MONODROID symbol is used (see file CallbackAttribute.cs and Helpers.cs in the protobuf-net source).
I the used this two assemblies and tried to generate the precompiled serializer from a MonoTouch application in the simulator.
But no matter which version of the precompiled serializer i use, the assembly is still not included in the app bundle, with mtouch issuing: "Warning: Library 'MyLibrary.dll' missing in app bundle, cannot extract content", despite the fact that i do reference it in my code.
I finally got it. It seems that when the actual assembly name is different from the file name that contains it mtouch will not include it in the application bundle. And that was happening in my case. I am generating the assembly like this:
model.Compile("Taxi.ProtoBufSerializers.MQTTContractsSerializer", "MQTTContractsSerializer.dll");
So, given that Protobuf-Net sets the assembly name to the first parameter of this method and saves it in the file name given by the second parameter, mtouch will fail to include it in the application bundle.
However, i wanted to keep my namespace so i fiddled with Protobuf-Net's source code to generate the assembly like this:
File path: Given as the second parameter;
Assembly name: Path.GetFileNameWithoutExtension(path);
Module name: Path.GetFileName(path).
I am not performing any validations on the path at this time, but i don't need to do this just yet.
And voila: The sample works both on the simulator and the device.
Last but not least, i don't know if this is the way mtouch is supposed to behave or if it is a bug. I will however file a bug report against it.
I have only gotten it to work on the simulator. I created the custom serialization assembly on VS.NET 2010. One issue I had was that the IL/DLL that gets created had the wrong namespace. I did something like this:
model.Compile("X.Y.Serializer.MySerializer", "X.Y.Serializer.dll")
But the IL was something like:
.assembly X.Y.Serializer.MySerializer
{
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module X.Y.Serializer.MySerializer
I.e. the class name was in the assembly name.
So I wrote a perl program to:
Decompile DLL -> IL
Fix IL
Compile IL -> DLL
Here is the script:
#!/usr/bin/perl
# Usage: fix-protobuf-assembly assembly bad-namespace
#
# Example: fix-protobuf-assembly X.Y.Serializer.dll X.Y.Serializer.MySerializer
# X.Y.Serializer.MySerializer gets converted to X.Y.Serializer
use strict;
use File::Slurp;
use Cwd;
print "Current directory is " . getcwd() . "\n";
my $asm_file = shift || die "missing assembly file";
my $bad_ns = shift || die "missing namespace";
die "no such file '$asm_file'" if (! -f $asm_file);
my $il_file = $asm_file;
$il_file =~ s#dll$#il#;
Run("ildasm /out=$il_file $asm_file");
my $il = read_file($il_file) || die "error reading $il_file: $!";
my $ns = $bad_ns;
$ns =~ s#\.[^.]+$##;
if (($il =~ s#(\.assembly|module) $bad_ns#$1 $ns#g) == 0)
{
die "$bad_ns not found in input dll; aborting";
}
write_file($il_file, $il);
Run("ilasm /dll $il_file");
sub Run
{
my($command) = #_;
warn "Running $command ...\n";
system($command) && die "error running last command; bailing out";
}
Maybe I just missed the proper way to call Compile() and my hack is unnecessary.
The assembly worked fine on Windows and iOS simulator. But it then gave a runtime JIT compile violation error on the device. I just created a SO question:
JIT compile error with protobuf-net on MonoTouch/iOS device (iPhone/iPad)
I did try using MonoDevelop on Mac w/ standard console project to first create the serialization assembly. I had some issues, but to be honest I was sleepy and grumpy and it could have been user error, and quickly decided to jump over to Windows since my project has other components that I develop there.
I used .NET 4.0 projects on Windows and everything worked OK. I just had to create a lightweight version of two MT-only libraries so that I could access the classes that would be serialized.
Yes, we have been using it on a project since 2012 to improve performance over XML serialization. Mostly because the RESTFul services we had at the time could not do JSON over 1MB in size for some of the files. At this point in 2017, it would be a lot easier for us to use JSON now, instead of the extra hassle of building the custom serializers for each object.

Resources