2

I have a .net dll, it can be register by RegAsm .net 3.5 and .net 4.5

I use this codes in my setup script:

[Run]
Filename: "{dotnet40}\RegAsm.exe"; Parameters: "my.dll"; WorkingDir: "{app}"; Flags: skipifdoesntexist; StatusMsg: "Registering Controls."
Filename: "{dotnet4064}\RegAsm.exe"; Parameters: "my.dll"; WorkingDir: "{app}"; Flags: skipifdoesntexist; StatusMsg: "Registering Controls."
Filename: "{dotnet20}\RegAsm.exe"; Parameters: "my.dll"; WorkingDir: "{app}"; Flags: skipifdoesntexist; StatusMsg: "Registering Controls."
Filename: "{dotnet2064}\RegAsm.exe"; Parameters: "my.dll"; WorkingDir: "{app}"; Flags: skipifdoesntexist; StatusMsg: "Registering Controls."
  • It works well if .net 3.5 and .net 4.5 is installed on the target machine
  • I have a function in my script to checking .net in InitializeSetup. so i know one of these versions are installed on the system: v3.5 v4 v4.5

But

we get error in some cases like this: if we have not .net 3.5 on the target machine

I guess the error reason is:

{dotnet20}

.NET Framework version 2.0 root directory. {dotnet20} is equivalent to {dotnet2032} unless the install is running in 64-bit mode, in which case it is equivalent to {dotnet2064}.

An exception will be raised if an attempt is made to expand this constant on a system with no .NET Framework version 2.0 present.

My question is how can i handle and ignore this exception and prevent setup rollback:

Internal error: .Net Framework version 2.0 not found.

Community
  • 1
  • 1
Ramin Bateni
  • 15,313
  • 8
  • 61
  • 90
  • 1
    You should use `Check`s and in their functions you should verify that you're able to find the target binary, and also catch when some constant cannot be expanded, [`something like this`](http://pastebin.com/Uw4kEJs1), and ideally for all the entries. Since that's quite a lot of work, I would consider writing this registration purely in some `[Code]` event. Of course, the exception will be raised even there, but it's a bit less work. I don't know any other way to overcome this in `[Run]` section without `Check`s that will prevent the upcoming failure (proper for this situation). – TLama Mar 08 '15 at 19:04
  • Another option might be extracting the way how Inno Setup expands those constants and use that in code. That might be exception-less. – TLama Mar 08 '15 at 19:30
  • @TLama thanks, i tried `check` before your comment and see the error again. so i generate a new version of my app under `.Net 4.5` and remove some codes and... know my setup work well. – Ramin Bateni Mar 08 '15 at 19:36
  • So, when you were trying your attempt, were you catching exceptions when expanding that constant (you have to) ? If yes, wasn't the exception you've seen a dialog shown in the IDE when running from debugger (that's the default behavior; you need to confirm it and continue debugging by F9) ? – TLama Mar 08 '15 at 20:31

1 Answers1

2

If you want to stick to the [Run] section and do not write this in a scripting code, then I think you don't have many options to choose from. An exception is raised whenever a constant cannot be expanded, and that is just this case. The only option I can think of is adding a Check function that will attempt to expand the constant in a protected try..except block and prevent the entry to be processed when an exception is raised. Something like follows (based on your code, shortened):

[Run]
Filename: "{dotnet20}\RegAsm.exe"; Parameters: "File.dll"; Check: RegAsmDotNet20Exists

[Code]
function RegAsmDotNet20Exists: Boolean;
begin
  try
    // process the entry only if the target binary could be found (and so the
    // folder constant could have been properly expanded)
    Result := FileExists(ExpandConstant('{dotnet20}\RegAsm.exe'));
  except
    // this is the fallback in case the folder constant could not be expanded,
    // or something unexpected happened when checking if the binary file to be
    // executed exists; in such case, don't process the entry
    Result := False;
  end;
end;

Another, quite cleaner and a bit safer option would be doing your assembly registration purely from [Code] section in some of the postinstall events. Even though you'd still need to catch exceptions when using those constants, you would get more control over that tool (e.g. you could get the exit code to obtain an error reason if that tool uses it).

TLama
  • 73,451
  • 17
  • 201
  • 368
  • Sidenote; beware that by default [`the debugger shows in the IDE an exception dialog`](http://stackoverflow.com/q/22039048/960757) regardless the exception is handled. – TLama Mar 08 '15 at 21:18
  • Note that it might not expand simply because .net did not create the apppath registry key. This is where Inno looks to get the path. Sometimes the key is missing and Inno fails with internal error. Even though .net is installed. – Andrew Truckle Jun 04 '22 at 04:56