【问题标题】:ShellExecuteEx error on a write protected USB drive?写保护的 USB 驱动器上的 ShellExecuteEx 错误?
【发布时间】:2011-07-08 21:03:44
【问题描述】:

我正在尝试在写保护的 USB 驱动器上测试应用程序,我想使用 ShellExecuteEx API(我需要使用此 API 调用,因为我需要 lpVerb := "runas")调用来执行第二个程序,但我不断收到 ShellExecuteEx 调用的“写保护错误”。我似乎无法弄清楚正在尝试写入驱动器的内容,我没有正在写入驱动器的代码,我什至使用最新的 Microsoft Standard User AnalyzerApplication Verifier 来尝试验证正在尝试写入的内容开车没有成功。这是我不断收到的错误:

[写保护错误]

以下代码中没有任何内容试图写入此驱动器,ShellExecuteEx API 调用错误的方式来执行我想要执行的操作吗?如果没有,我怎样才能从弹出中得到这个错误。任何帮助将不胜感激。

[WP-ON.reg]

REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies]
"WriteProtect"=dword:00000001

[WP-OFF.reg]

REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\StorageDevicePolicies]
"WriteProtect"=dword:00000000

注意:每次更新注册表时,您必须弹出并重新插入设备。

[project1.dpr]

program project1;

{.$APPTYPE CONSOLE}

uses
  Windows, SysUtils;

begin
  Windows.MessageBox(Windows.GetActiveWindow(),
    PChar('Hello World!'), PChar('project1'), MB_OK);
end.

[launch.manifest]

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity processorArchitecture="x86" version="2.0.1.0" name="eyeClaxton.asInvoker.Launch" type="win32" />
<description>asInvoker Launch</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="x86" />
    </dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
        <requestedPrivileges>
            <requestedExecutionLevel level="asInvoker" uiAccess="false" />
        </requestedPrivileges>
    </security>
</trustInfo>
</assembly>

[launch.dpr]

program launch;

uses
  Windows, ShellAPI;

{$R 'MANIFEST.RES'}

procedure ShellEx(const theFilename, theParams: string);

  function RunAsAdmin(): Boolean;
  var
    OSVerInfo: TOSVersionInfo;
  begin
    OSVerInfo.dwOSVersionInfoSize := System.SizeOf(OSVerInfo);
    Result := (Windows.GetVersionEx(OSVerInfo)) and (OSVerInfo.dwMajorVersion > 5);
  end;

var
  ShellExInfo: TShellExecuteInfo;
  Directory: array[0..MAX_PATH] of Char;
begin
  Windows.ZeroMemory(@ShellExInfo, System.SizeOf(ShellExInfo));
  ShellExInfo.cbSize := System.SizeOf(TShellExecuteInfo);
  ShellExInfo.Wnd := Windows.GetActiveWindow();
  ShellExInfo.nShow := SW_SHOWNORMAL;
  ShellExInfo.fMask := SEE_MASK_FLAG_NO_UI;

  if (RunAsAdmin()) then  // If OS is greater than Windows XP
    ShellExInfo.lpVerb := PChar('runas');

  Windows.ZeroMemory(@Directory, System.SizeOf(Directory));
  Windows.GetCurrentDirectory(SizeOf(Directory), Directory);
  ShellExInfo.lpDirectory := PChar(string(Directory));
  ShellExInfo.lpFile := PChar('"' + string(Directory) + '\' + theFilename + '"');
  ShellExInfo.lpParameters := PChar('"' + theParams + '"');

  //
  // ShellExecuteEx causes a "Write Protect" error to popup.
  //
  if (not ShellAPI.ShellExecuteEx(@ShellExInfo)) then
    Windows.MessageBox(Windows.GetActiveWindow(),
      PChar('File ' + ShellExInfo.lpFile + ' not found!'),
      PChar('asInvoker Launch'), MB_OK or MB_ICONERROR);
end;

begin
  ShellEx('project1.exe', System.ParamStr(1));

end.

【问题讨论】:

  • 尝试使用Process Monitor technet.microsoft.com/en-us/sysinternals/bb896645 ,使用此工具您可以检查任何进程的文件系统活动。
  • 我怀疑 ShellExecuteEx 正在尝试写入驱动器。第二个程序如何访问该文件?你确定第二个程序正在启动吗?
  • @Peter 提供了第二个程序源代码(project1.dpr)。它只显示一个消息框。问题是第二个程序甚至没有启动,因为 ShellExecute 返回一个错误。
  • 似乎是一个已识别的限制,它出现在 XP SP3 中:它通常是随 Windows 更新引入的安全功能。见powerbasic.com/support/pbforums/showthread.php?t=37689
  • @A.Bouchez 您的评论是正确的,我刚刚在 Vista 和 Windows 7 上进行了测试,它按预期工作,但在 Windows XP SP3 上却没有。

标签: delphi delphi-7 shellexecuteex


【解决方案1】:

问题在于ShellExecuteEx 是一个相当复杂的过程,启动一个新的后台线程,然后调用很多 COM 的东西。出于安全原因,应该在某处启用写入。

您可以尝试禁用 UAC。但不是一个好的解决方案。

当您查看以编程方式提升进程权限的相应解决方案时(有线清单是另一种静态提升方式),您只能找到两个quoted in this SO answer

  • 使用带有runas参数的ShellExecuteEx;
  • 使用神奇的“Elevation:Administrator!new:”前缀创建提升的 COM 对象。

值得阅读整篇 "Vista UAC: The Definitive Guide" 文章以了解 ShellExecuteEx 的工作原理。

所以这是我的答案:因为您需要运行具有提升权限的进程,并且没有现有的“CreateProcessElevated”API,而只有好的大 ShellExecute,所以最简单的方法是使用第二个可执行文件的清单文件。

如果您希望您的 project1.exe 文件以“AsInvoker”权限运行,但故意仅以管理员权限运行,您有两种可能性:

  • 使用外部.manifest 文件,并且不要将该文件作为资源嵌入到exe 中-然后将.manifest 内容替换为带有“AsInvoker”或“requireAdministrator”参数的一个版本-但读取时很难- 只有媒体,不是吗:;
  • 使用外部第三个可执行文件(我们称之为Elevate.exe),其中包含一个“requireAdministrator”级别的清单,它将启动第二个可执行文件。您可以将 exe 和命令行作为参数提供给这个 Elevate.exe 程序。

【讨论】:

  • 我不需要 project1.exe 在 Windows XP 上运行提升,如果检测到 XP,我将测试操作系统版本,然后调用 WinExec API。测试和工作!非常感谢您的帮助。
猜你喜欢
  • 2011-07-14
  • 1970-01-01
  • 2012-08-24
  • 2017-09-11
  • 1970-01-01
  • 2017-11-17
  • 2011-03-24
  • 1970-01-01
  • 2012-03-14
相关资源
最近更新 更多