“您必须输入带有驱动程序的完整路径或格式为...的UNC路径." Inno Setup错误消息 [英] "You must enter a full path with driver [...] or a UNC path in the form ..." inno setup error message
问题描述
很抱歉,我的代码很糟糕.我遇到此错误消息:
Apologies if my code is terrible. I am running into this error message:
安装程序当前以非管理员用户身份启动,然后在开始复制文件之前以管理员用户身份杀死并重新启动自身.仅在选择注册"安装时出现错误消息.
The installer currently starts as a non-admin user then kills and restarts itself as an admin user right before files start being copied. The error message only comes up when 'Register' install is selected.
如果我在安装位置输入任何顶级驱动器,就会发生这种情况.如果我在网络共享上输入一个文件夹,则会遇到另一个错误(另一个特权问题),并且如果我在C:\驱动器上输入一个文件夹(如在C:\ xyz中),那么它将正常工作.
This occurs if I enter any top-level drive in the install location. If I enter a folder on a network share, I'll get a different error (another privilege issue) and if I input a folder on the C:\ drive (as in C:\xyz) then it works fine.
#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;
推荐答案
事实证明,问题出在行上
As it turns out, the problem lies in the lines
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);
在此代码部分中,将使用管理特权重新启动启动器.在参数部分,"/DIR"选项是Inno Setup选项,它将覆盖默认的InstallDirectory.需要将其设置为非顶级驱动器(即不是"C:\"或"O:\",而是"C:\ xyz").
In this section of code, the launcher is re-launched with administrative privileges. IN THE PARAMS SECTION, the '/DIR' option is an Inno Setup option, which overrides the default InstallDirectory. This needs to be set to something that is not a top-level drive (i.e., not 'C:\' or 'O:\', but 'C:\xyz').
只要更改,上面的程序存根就可以正常工作.
As long as that is changed, the above program stub will work fine.
这篇关于“您必须输入带有驱动程序的完整路径或格式为...的UNC路径." Inno Setup错误消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!