"您必须在表单中输入带有驱动程序[...]或UNC路径的完整路径..." inno设置错误消息

时间:2016-08-08 20:01:02

标签: inno-setup

如果我的代码很糟糕,请道歉。我遇到此错误消息:

enter image description here

安装程序当前以非管理员用户身份启动,然后在文件开始复制之前以管理员用户身份终止并重新启动。只有当注册'注册时才会出现错误消息。选择安装。

如果我在安装位置输入任何顶级驱动器,则会发生这种情况。如果我在网络共享上输入一个文件夹,我将得到一个不同的错误(另一个权限问题),如果我在C:\驱动器上输入一个文件夹(如在C:\ xyz中),那么它可以正常工作。 / p>

#define MyAppName "O"
#define MyAppVersion "0.0"

[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={{9BB6F4FD-5530-4043-BD9E-A405BAEDDDFF}}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
DefaultDirName={sd}\{#MyAppName}
DisableDirPage=yes
AllowNoIcons=yes
OutputDir={desktop}
OutputBaseFilename=dummy
Compression=lzma
SolidCompression=yes

PrivilegesRequired=lowest

[Types]
Name: "server"; Description: "Odin Server Install"
Name: "client"; Description: "Odin Register/Workstation Install"

[Components]
Name: "data_shared_exe"; Description: "Core apps installed"; Types: server;
Name: "C_Odin"; Description: "Database stuff"; Types: server client;
Name: "shortcuts"; Description: "Shortcuts to Odin apps"; Types: server client;

[Code]

var
  SelectOdinSharePage: TInputDirWizardPage;
  SelectOdinInstallPage: TInputDirWizardPage;

  Elevated: Boolean;
  InstallType: Integer;
  DirParam: string;

type
  HINSTANCE = THandle;

// Privilege Escalation code
// Inspired by/Courtesy of http://stackoverflow.com/questions/21556853/make-inno-setup-installer-request-privileges-elevation-only-when-needed
procedure ExitProcess(uExitCode: UINT);
  external 'ExitProcess@kernel32.dll stdcall';
function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
  lpParameters: string; lpDirectory: string; nShowCmd: Integer): HINSTANCE;
  external 'ShellExecuteW@shell32.dll stdcall';

function IsServerInstall(): Boolean;
begin
  Result := (InstallType=0)
end;

function CmdLineParamExists(const Value: string): Boolean;
var
  I: Integer;  
begin
  Result := False;
  for I := 1 to ParamCount do
    if CompareText(ParamStr(I), Value) = 0 then
    begin
      Result := True;
      Exit;
    end;
end;

function CmdLineParamReadInt(const Value: string): integer;
var
  I: Integer;  
begin
  Result := -1;
  for I := 1 to ParamCount do
    if Pos(Value, ParamStr(I)) = 1 then
    begin
      Result := StrToInt(Copy(ParamStr(I), Length(Value)+2, 1));
      //MsgBox(Format('ReadInt: %s', [Copy(ParamStr(I), Length(Value)+2, 1)]), mbInformation, MB_OK);
      Exit;
    end;
end;

function CmdLineParamReadStr(const Value: string): string;
var
  I: Integer;  
begin
  Result := '';
  for I := 1 to ParamCount do
    if Pos(Value, ParamStr(I)) = 1 then
    begin
      Result := Copy(ParamStr(I), Length(Value)+2, Length(ParamStr(I))-Length(Value)-1);
      //MsgBox(Format('ReadStr: %s',[Result]), mbInformation, MB_OK)
      Exit;
    end;
end;

procedure OnTypeChange(Sender: TObject);
begin
  // set the item index in hidden TypesCombo
  WizardForm.TypesCombo.ItemIndex := TNewRadioButton(Sender).Tag;
  InstallType := TNewRadioButton(Sender).Tag;
  // notify TypesCombo about the selection change
  WizardForm.TypesCombo.OnChange(nil);
end;

procedure InitializeWizard();
var
  I: Integer;
  RadioButton: TNewRadioButton;
begin
  // By default, InstallType is 1 ('Register')
  InstallType := 1;

  // Privilege escalation parameters
  Elevated := CmdLineParamExists('/ELEVATE');
  if Elevated then
  begin
    InstallType := CmdLineParamReadInt('/INSTALLTYPE');
    DirParam := CmdLineParamReadStr('/DIR');
    //MsgBox(Format('DirParam: %s', [DirParam]), mbInformation, MB_OK);
  end;

  for I := 0 to WizardForm.TypesCombo.Items.Count - 1 do
  begin
    // create radio button and set the basic properties
    RadioButton := TNewRadioButton.Create(WizardForm);
    RadioButton.Parent := WizardForm.SelectComponentsPage;
    RadioButton.Left := WizardForm.TypesCombo.Left;
    RadioButton.Top := WizardForm.TypesCombo.Top + I * RadioButton.Height;
    RadioButton.Width := WizardForm.TypesCombo.Width;
    // the Tag property substitutes the index property
    RadioButton.Tag := I;
    RadioButton.TabOrder := I;     
    RadioButton.OnClick := @OnTypeChange;
    // check just the first item
    RadioButton.Checked := I = InstallType;
    RadioButton.Caption := WizardForm.TypesCombo.Items[I];
  end;
  // hide the TypesCombo combo box
  WizardForm.TypesCombo.Visible := False;

  SelectOdinSharePage := CreateInputDirPage(wpSelectComponents,
  'Select Odin Exe''s directory', 'Where are the Odin exe''s located?',
  'The Odin exe''s are usually located on the Odin Network Share under "exe" or "exes". ' +
  'Once you have found this directory, click Next. If you would like to select a different folder, click Browse.',
  False, 'New Folder');
  SelectOdinSharePage.Add('');
  SelectOdinSharePage.Values[0] := 'O:';

  SelectOdinInstallPage := CreateInputDirPage(wpSelectComponents,
  'Select Odin Install directory', 'Select where to install Odin core apps',
  'To continue, click Next. If you would like to select a different folder, click Browse.',
  False, 'New Folder');
  SelectOdinInstallPage.Add('');
  SelectOdinInstallPage.Values[0] := 'C:\Program Files (x86)\Odin';

  if Elevated then
  begin
    if IsServerInstall() then SelectOdinInstallPage.Values[0] := DirParam;
    if not IsServerInstall() then SelectOdinSharePage.Values[0] := DirParam;
  end;
end;

function ShouldSkipPage(PageID: Integer): Boolean;
begin
  Result := False;
  if ((PageID=100) and IsServerInstall()) then Result := True;
  if ((PageID=101) and not IsServerInstall()) then Result := True;

  if Elevated then
  begin
    if IsServerInstall() then
    begin
      if ((PageID=7) or (PageID=101)) then Result := True;
    end;
    if InstallType=1 then
    begin
      if ((PageID=7) or (PageID=100)) then Result := True;
    end;
  end;
end;

function NextButtonClick(CurPageID: Integer): Boolean;
var
  Params: string;
  RetVal: HINSTANCE;
begin
  Result := True;
  //MsgBox(Format('Is Server Install: %d', [WizardForm.TypesCombo.ItemIndex]), mbInformation, MB_OK);
  if (CurPageID=101) and IsServerInstall() then
  begin
    Params := ExpandConstant('/DIR="' + SelectOdinInstallPage.Values[0] + '" /ELEVATE /INSTALLTYPE=0');
    RetVal := ShellExecute(WizardForm.Handle, 'runas',
      ExpandConstant('{srcexe}'), Params, '', SW_SHOW);
    if RetVal > 32 then
    begin
      ExitProcess(0);
    end
    else
      MsgBox('Administrative privilege escalation failed. Install aborted. Contact Odin Support.', mbInformation, MB_OK);
      ExitProcess(0);
  end;
  if (CurPageID=100) and (not IsServerInstall()) then
  begin
    Params := ExpandConstant('/DIR="' + SelectOdinSharePage.Values[0] + '" /ELEVATE /INSTALLTYPE=1');

    RetVal := ShellExecute(WizardForm.Handle, 'runas',
      ExpandConstant('{srcexe}'), Params, '', SW_SHOW);
    if RetVal > 32 then
    begin
      ExitProcess(0);
    end
    else
      MsgBox('Administrative privilege escalation failed. Install aborted. Contact Odin Support.', mbInformation, MB_OK);
      ExitProcess(0);
  end;
end;

1 个答案:

答案 0 :(得分:0)

事实证明,问题在于

if (CurPageID=100) and (not IsServerInstall()) then
  begin
    Params := ExpandConstant('/DIR="' + SelectOdinSharePage.Values[0] + '" /ELEVATE /INSTALLTYPE=1');

    RetVal := ShellExecute(WizardForm.Handle, 'runas',
      ExpandConstant('{srcexe}'), Params, '', SW_SHOW);

在此部分代码中,将使用管理权限重新启动启动程序。在PARAMS SECTION中,'/ DIR'选项是Inno Setup选项,它会覆盖默认的InstallDirectory。这需要设置为不是顶级驱动器(即不是'C:\'或'O:\',而是'C:\ xyz')。

只要改变了,上述程序存根就可以正常工作。