Ошибка ShellExecuteEx на USB-накопителе с защитой от записи? - PullRequest
4 голосов
/ 09 июля 2011

Я пытаюсь протестировать приложение на USB-накопителе с защитой от записи, я хочу использовать API-интерфейс ShellExecuteEx (мне нужно использовать этот вызов API, потому что мне нужен вызов lpVerb: = "runas") для выполнения второй программы, но я продолжаю получать «Ошибка защиты от записи» с вызовом ShellExecuteEx.Кажется, я не могу понять, что пытается записать на диск, у меня нет кода, который пишет на диск, и я даже использовал самые последние Microsoft Standard User Analyzer и Application Verifier попытаться проверить, что пытается записать на диск безуспешно.Вот ошибка, которую я продолжаю получать:

[Ошибка защиты от записи]

Write Protect Error

Ничто в следующем коде не пытается писать вэтот диск, API ShellExecuteEx вызывает неправильный способ сделать то, что я пытаюсь сделать?Если нет, как я могу получить эту ошибку при появлении.Буду признателен за любую помощь.

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

1 Ответ

6 голосов
/ 09 июля 2011

Проблема заключается в том, что ShellExecuteEx довольно сложный процесс, начиная новый фоновый поток, затем вызывая много COM-содержимого. По соображениям безопасности запись должна быть включена где-то.

Вы можете попытаться отключить UAC. Но не хорошее решение.

Когда вы смотрите на соответствующие решения для повышения прав процесса программным способом (проводной манифест - это еще один статический способ повышения прав), вы можете найти только два , указанных в этом ответе SO :

  • Использовать ShellExecuteEx с параметром runas;
  • Создание повышенного COM-объекта с волшебным префиксом «Высота: администратор! Новый:».

Стоит прочитать всю статью «Vista UAC: Полное руководство» , чтобы понять, как ShellExecuteEx работает.

Итак, вот мой ответ: так как вам нужно запустить процесс с повышенными правами, и нет никакого существующего API «CreateProcessElevated», а есть только хороший большой ShellExecute , проще всего использовать манифест файл для 2-го исполняемого файла.

Если вы хотите, чтобы файл project1.exe запускался с правами «AsInvoker», но только с правами администратора специально, у вас есть две возможности:

  • Используйте внешний файл .manifest и не встраивайте файл в исполняемый файл как ресурс - затем замените содержимое .manifest на одну версию с параметром "AsInvoker" или "requireAdministrator" - но трудно для чтения только СМИ, не так ли:;
  • Используйте внешний 3-й исполняемый файл (назовем его Elevate.exe), содержащий манифест с уровнем «requireAdministrator», который запустит 2-й исполняемый файл. Вы можете предоставить exe и командную строку в качестве параметра этой Elevate.exe программе.
...