【问题标题】:How to execute "net use" command from Inno Setup installer on Windows 7?如何在 Windows 7 上从 Inno Setup 安装程序执行“net use”命令?
【发布时间】:2012-10-23 07:12:05
【问题描述】:

我正在开发一个 Inno Setup 安装程序,它调用 net use 来连接到共享服务器。安装程序可以连接到服务器,如果它在 Windows XP 上运行,但不是在 Windows 7 上运行。我认为它与 UAC 有关,因为我键入相同的命令,服务器连接在 Windows 7 上,但安装程序正在运行 @987654322 @特权。

我正在通过ExecShellExec 脚本函数使用以下net use 命令:

/c net use \\servername password /user:username

实际上,这里是显示net use 命令调用的脚本的一部分:

[Code] 
var 
  ErrorCode: Integer; 
  cmdString: String; 
  intvalue: Integer; 
  str: String; 

function InitializeSetup(): Boolean; 
begin 
  cmdString := '/c net use \\servername password /USER:username'; 
  ShellExec('', ExpandConstant('{cmd}'), cmdString , '', SW_SHOWNORMAL, 
    ewWaitUntilTerminated, ErrorCode) 
  if (ErrorCode = 0) then 
  begin 
    MsgBox(ExpandConstant('{cmd}'), mbInformation, MB_OK); 
  end; 
end;

有人可以建议如何在 Windows 7 上使用 Inno Setup 中的 net use 吗?我们只想连接到服务器并让用户输入名称和密码。

谢谢!

【问题讨论】:

  • 我已经尝试net use 映射网络共享(虽然没有密码),但它有效。事实是,我使用Exec 直接调用了net.exe,而不是通过命令行(也许命令行甚至返回mazy 结果,不知道,但我会尝试)。同时,我将向您发布我的测试代码。对于其他人,我对这个问题所做的更新来自很长的评论讨论,所以我要求 OP 清理 workspace
  • 虽然net.exe 很方便,但最好直接使用API​​(在这种情况下,WNetUseConnection 与给定答案一样)。有时命令会意外停止并等待输入,如果您尝试隐藏运行它可能会导致真正的问题(如果您没有隐藏运行它,您会得到一个丑陋的控制台窗口)。毕竟,它是为控制台管理员使用而设计的,而不是软件——这就是 API 的用途。
  • 您好 Miral,我们在 Windows 7 上遇到了 net.exe 问题,看起来 net 命令实际上并没有被执行,而返回值显示它没问题。我想知道这是否是一个错误,或者我错过了什么。
  • 请记住,设置(提升时)以不同的用户或执行级别作为桌面的其余部分运行。连接不会像您期望的那样被保留。
  • 嗨,Deanna,感谢您的回复,这有助于我了解问题的原因。

标签: windows-7 inno-setup uac net-use


【解决方案1】:

如何连接到调用凭据对话框的远程资源?

对您的问题使用不同的观点,实际上正如这个答案的标题所说,我建议您使用带有CONNECT_INTERACTIVECONNECT_PROMPT 标志的WNetUseConnection 函数调用。这将结合空的用户 ID 和密码参数调用凭据对话框(这就是您想要的)。在 Inno Setup 脚本中,它可能如下所示:

[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program

[Code]
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif
const
  NO_ERROR = 0;
  ERROR_ACCESS_DENIED = 5;
  ERROR_BAD_NET_NAME = 67;
  ERROR_ALREADY_ASSIGNED = 85;
  ERROR_INVALID_PASSWORD = 86;
  ERROR_INVALID_PARAMETER = 87;
  ERROR_MORE_DATA = 234;
  ERROR_NO_MORE_ITEMS = 259;
  ERROR_INVALID_ADDRESS = 487;
  ERROR_BAD_DEVICE = 1200;
  ERROR_NO_NET_OR_BAD_PATH = 1203;
  ERROR_BAD_PROVIDER = 1204;
  ERROR_EXTENDED_ERROR = 1208;
  ERROR_NO_NETWORK = 1222;
  ERROR_CANCELLED = 1223;
  RESOURCETYPE_ANY = $00000000;
  RESOURCETYPE_DISK = $00000001;
  RESOURCETYPE_PRINT = $00000002;
  CONNECT_UPDATE_PROFILE = $00000001;
  CONNECT_INTERACTIVE = $00000008;
  CONNECT_PROMPT = $00000010;
  CONNECT_REDIRECT = $00000080;
  CONNECT_COMMANDLINE = $00000800;
  CONNECT_CMD_SAVECRED = $00001000;
type
  TNetResource = record
    dwScope: DWORD;
    dwType: DWORD;
    dwDisplayType: DWORD;
    dwUsage: DWORD;
    lpLocalName: string;
    lpRemoteName: string;
    lpComment: string;
    lpProvider: string;
  end;
  TResourceType = (
    rtAny,
    rtDisk,
    rtPrinter
  );

function WNetUseConnection(hwndOwner: HWND; const lpNetResource: TNetResource;
  lpPassword, lpUserID: string; dwFlags: DWORD; lpAccessName: PAnsiChar;
  var lpBufferSize, lpResult: DWORD): DWORD;
  external 'WNetUseConnection{#AW}@mpr.dll stdcall';

function UseConnection(const ARemoteName: string; 
  AResourceType: TResourceType): DWORD;
var
  BufferSize: DWORD;
  ResultFlag: DWORD;
  NetResource: TNetResource;
begin
  case AResourceType of
    rtAny: NetResource.dwType := RESOURCETYPE_ANY;
    rtDisk: NetResource.dwType := RESOURCETYPE_DISK;
    rtPrinter: NetResource.dwType := RESOURCETYPE_PRINT;
  end;
  NetResource.lpLocalName := '';
  NetResource.lpRemoteName := ARemoteName;
  NetResource.lpProvider := '';  
  BufferSize := 0;
  Result := WNetUseConnection(WizardForm.Handle, NetResource,
    '', '', CONNECT_INTERACTIVE or CONNECT_PROMPT, '',
    BufferSize, ResultFlag); 
end;

procedure UseConnectionButtonClick(Sender: TObject);
var
  S: string;
  ResultCode: DWORD;
begin
  ResultCode := UseConnection('\\MySuperSecret\Place', rtDisk);
  case ResultCode of
    NO_ERROR: S := 'NO_ERROR';
    ERROR_ACCESS_DENIED: S := 'ERROR_ACCESS_DENIED';
    ERROR_ALREADY_ASSIGNED: S := 'ERROR_ALREADY_ASSIGNED';
    ERROR_BAD_DEVICE: S := 'ERROR_BAD_DEVICE';
    ERROR_BAD_NET_NAME: S := 'ERROR_BAD_NET_NAME';
    ERROR_BAD_PROVIDER: S := 'ERROR_BAD_PROVIDER';
    ERROR_CANCELLED: S := 'ERROR_CANCELLED';
    ERROR_EXTENDED_ERROR: S := 'ERROR_EXTENDED_ERROR';
    ERROR_INVALID_ADDRESS: S := 'ERROR_INVALID_ADDRESS';
    ERROR_INVALID_PARAMETER: S := 'ERROR_INVALID_PARAMETER';
    ERROR_MORE_DATA: S := 'ERROR_MORE_DATA';
    ERROR_INVALID_PASSWORD: S := 'ERROR_INVALID_PASSWORD';
    ERROR_NO_MORE_ITEMS: S := 'ERROR_NO_MORE_ITEMS';
    ERROR_NO_NET_OR_BAD_PATH: S := 'ERROR_NO_NET_OR_BAD_PATH';
    ERROR_NO_NETWORK: S := 'ERROR_NO_NETWORK';
  end;
  MsgBox(S, mbInformation, MB_OK);
end;

procedure InitializeWizard;
var
  UseConnectionButton: TNewButton;
begin
  UseConnectionButton := TNewButton.Create(WizardForm);
  UseConnectionButton.Parent := WizardForm;
  UseConnectionButton.Left := 8;
  UseConnectionButton.Top := WizardForm.ClientHeight - UseConnectionButton.Height - 8;
  UseConnectionButton.Width := 155;
  UseConnectionButton.Caption := 'Use connection...';
  UseConnectionButton.OnClick := @UseConnectionButtonClick;
end;

【讨论】:

  • 您好 TLama,感谢您的代码。我试过了,但在这里不起作用。我的网络服务器要求用户输入用户名和密码,在 Windows 7 上,安装后,当用户尝试连接服务器时,会弹出一个窗口要求用户输入用户名和密码。另一个区别是我不映射驱动器只是连接到服务器,我也尝试映射驱动程序但也没有工作。有什么想法吗?
  • 这就是我所期望的。我想我找到了方法,WNetUseConnection 函数。在某些情况下,它会调用凭据对话框。我会试着为你准备一个例子。我会马上回来更新 ;-) 但这更像是对如何连接到显示凭据对话框的网络资源?之类的问题的答案
  • 我已经发布了承诺的脚本代码,我已经在 Windows 7 和 Windows XP 模式下进行了测试。
  • 您好 TLama,您帖子中的脚本令人印象深刻。我试过了,它在我的xp上可以工作,但在我的Windoes 7上不行。我输入了用户凭据,但服务器没有挂载,结果代码是useconnection 1219。在XP上,服务器已挂载但访问错误关于 setup.exe。也许 net.exe 更合适?
  • error code 1219 表示不允许同一用户使用多个用户名多次连接到服务器或共享资源。断开与服务器或共享资源的所有先前连接,然后重试。,您不是已经连接到该资源(但我对网络真的很烂)?而且,我不认为 net.exe 为什么会更合适。这是 MSDN 和开发人员建议的方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多