1

I am trying to pass error and error_msg variables to PowerShell script by reference. But it is not working. It is not reflecting changes done inside the checkHost.ps1.

var
  error_msg: String;
  error: String;
  ok: String;

function NextButtonClick(CurPageID: Integer): Boolean;
begin
  error_msg := 'all well';
  Result := True;
  error := 'false';
  ok := 'true';

  exec('powershell.exe',
    '-noexit -executionpolicy bypass ' +
    '"D:\Hyperv_ins_BM\checkHost.ps1 [ref]error   [ref]error_msg"',
    ExpandConstant('{tmp}'), SW_SHOW, ewWaitUntilTerminated, ResultCode);
end; 

Can anybody help?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Mitra
  • 31
  • 5
  • Why do you need to pass the parameters by reference? – Bill_Stewart Nov 30 '17 at 18:15
  • I added this as the first thing in the checkHost.ps1. Param( [Parameter(Mandatory=$True,Position=1)] [string][ref]$error, [Parameter(Mandatory=$True,Position=2)] [string][ref]$error_msg ) – Mitra Nov 30 '17 at 18:27
  • You can pass a parameter by adding the parameter on the script's command line - use the powershell.exe `-File` parameter - by why does it have to be by reference? – Bill_Stewart Nov 30 '17 at 18:28
  • I need to print error message in inno msgbox generated by this checkHost.ps1 script. – Mitra Nov 30 '17 at 18:29
  • 1
    IIRC the only way to do that would be for the PowerShell script to provide the error message to stdout and the PascalScript code would read that. If you really want to show an error dialog, you should do it from inside the PowerShell script. Alternatively, dispense with PowerShell and implement that code in PascalScript. – Bill_Stewart Nov 30 '17 at 18:34
  • As an aside, I wouldn't recommend showing an error dialog in an installer unless you have a way to bypass it when installing silently. – Bill_Stewart Dec 01 '17 at 21:35

2 Answers2

0

It's not possible. PowerShell is a plain console application as any other, it's not an API.


As @Bill_Steward suggested, have the PowerShell script output its results to a file and read that back in Inno Setup:

function CheckHost(var ErrorMessage: string): Boolean;
var
  Parameters: string;
  TempPath: string;
  AErrorMessage: AnsiString;
  ResultCode: Integer;
begin
  TempPath := ExpandConstant('{tmp}\checkHost.err');
  Parameters :=
    '-ExecutionPolicy bypass -File "C:\path\to\script\checkHost.ps1" ' +
    '-ErrorFile "' + TempPath + '"';
  Result :=
    Exec('powershell.exe', Parameters, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and
    (ResultCode = 0);
  if not Result then
  begin
    if LoadStringFromFile(TempPath, AErrorMessage) then
    begin
      ErrorMessage := AErrorMessage;
    end;
  end;
  DeleteFile(TempPath);
end;

The above is based on How to get an output of an Exec'ed program in Inno Setup?


Use the function like:

var
  ErrorMessage: string;
begin
  if CheckHost(ErrorMessage) then
  begin
    MsgBox('Host check succeeded', mbInformation, MB_OK);
  end
    else
  begin
    MsgBox(ErrorMessage, mbError, MB_OK);
  end;
end;

The PowerShell script may look like:

param (
    $errorFile
)

if (checkHost())
{
    exit 0
}
else
{
    Set-Content -Path $errorFile -Value "Host check failed for some reason" 
    exit 1
}

Though, as @Bill_Steward mentioned too, it's quite possible that you can implement your check in pure Pascal Script. But that's for a different question.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • I will try your suggested way. Thanks a lot! – Mitra Dec 01 '17 at 05:29
  • I tried it but it seems powershell script is not creating any file in {tmp} location. So message coming as empty. – Mitra Dec 01 '17 at 08:07
  • Sorry, but if you need help, you have to provide us way more information. + Test with a very simple script first, like the script is my answer (but of course with the call to nondefined function `checkHost()` replaced with `$False`). – Martin Prikryl Dec 01 '17 at 08:12
-1

I tried below as sample code. The checkHost.err is created and test is added there too.

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT    FILES!

#define PUBLISHER "AtoZ Technology, Inc."
#define PUBLISHER_URL "http://www.xyzabc.com/"
#define PRODUCT_NAME "test"



[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.)

AppPublisher={#PUBLISHER}
AppPublisherURL={#PUBLISHER_URL}
AppCopyright=Copyright (C) 2013-2016 {#PUBLISHER}
AppName=test installer
AppId=TestInstaller
AppVerName=Test Installer
DefaultDirName={pf}\Test Install
DefaultGroupName=Test Install
Compression=lzma2
ArchitecturesAllowed=x64
ArchitecturesInstallIn64BitMode=x64
OutputBaseFilename=test_installer
OutputDir="D:\Test"
LicenseFile=lics.txt
SetupLogging=yes
VersionInfoProductName=Test  ]

VersionInfoProductTextVersion= "1.0"

[Files]
Source: "checkHost.ps1"; DestDir: "{app}"; Flags: ignoreversion

[Code]
function CheckHost(var ErrorMessage: string): Boolean;
var
Parameters: string;
TempPath: string;
AErrorMessage: AnsiString;
ResultCode: Integer;
begin                                                              
begin
TempPath := ExpandConstant('{tmp}\checkHost.err');
Parameters := '-noexit -ExecutionPolicy bypass -File     "D:\Test\checkHost.ps1" ' + '-errorFile "' + TempPath + '"';
Result :=
Exec('powershell.exe', Parameters, ExpandConstant('{tmp}'), SW_SHOW,   ewWaitUntilTerminated, ResultCode) and
(ResultCode = 0);
if Result then
begin
if LoadStringFromFile(TempPath, AErrorMessage) then
begin
  ErrorMessage := AErrorMessage;
end;
end;
DeleteFile(TempPath);
end;

var
ModelPage: TInputOptionWizardPage;
models: Variant;
model_info: String;
i: Integer;
procedure InitializeWizard;
begin
ModelPage := CreateInputOptionPage(wpWelcome,
'Model Information', '',
'Please specify the model you would like to install, then click Next.',
 True, False);

 for i:= 0 to 2  do
 begin 
  model_info := 'model' + IntToStr(i);
  model_info := model_info + ' ( HDD ' + '10 GB';
  model_info := model_info + ' SSD ' + '2 GB' + ' )';
  ModelPage.Add(model_info);      
 end;

  ModelPage.SelectedValueIndex := 0;
  end;
  var

  model: String;
  ErrorMessage: string;

  function NextButtonClick(CurPageID: Integer): Boolean;
   begin

   Result := True;

   if CurPageID = ModelPage.ID then
    begin
     if CheckHost(ErrorMessage) <> true then
      begin
      MsgBox(ErrorMessage, mbError, MB_OK);
      end;              
    end;

    end;

But it seems LoadStringFromFile() is not working cause empty value is printed in the msgbox().

Mitra
  • 31
  • 5
  • 1) You have just reposted my code. That won't help us with debugging your problem. We need to see your `D:\Test\checkHost.ps1`. 2) *"seems not working"* is not helpful either. So what do you know? What is the `ResultCode`? Do you see anything in PowerShell console? 3) Do not post additional information as an answer. This is not an answer. Append additional information to your question instead. – Martin Prikryl Dec 01 '17 at 15:45
  • Are you aware that with modifications that you have made (`if Result then` instead of `if not Result then`), you load the error only when `Result` is true, while you display the error only when `Result` is false? (`CheckHost(ErrorMessage) <> true`) So you effectively never show the error? – Martin Prikryl Dec 01 '17 at 15:49
  • Param( [Parameter(Mandatory=$True)] [string]$errorFile ) try { Set-Content $errorFile -Value "all done. system is fine" } catch { exit 1 } – Mitra Dec 01 '17 at 16:15
  • the error is not any system generated error. It will be generated when host is not machine some hardware/software requirement. So Result always will be true. Thats why I kept the check like that. – Mitra Dec 01 '17 at 16:16
  • resultCode is 0 in this case. – Mitra Dec 01 '17 at 16:20
  • Powershell console is not throwing any error. And it is creating the file in {tmp} location also with the text. – Mitra Dec 01 '17 at 16:21
  • Again, but then the `CheckHost(ErrorMessage) <> true` is never true! – Martin Prikryl Dec 01 '17 at 16:28
  • Sorry for my bad. I will add all the info to my question from now on. – Mitra Dec 01 '17 at 16:54
  • I finally resolved it. I forgot to pass the string by reference. – Mitra Dec 05 '17 at 15:55