4

書き込み保護された USB ドライブでアプリケーションをテストしようとしています。ShellExecuteEx API (lpVerb := "runas" が必要なため、この API 呼び出しを使用する必要があります) 呼び出しを使用して 2 番目のプログラムを実行したいのですが、 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.

[起動.マニフェスト]

<?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.
4

1 に答える 1

6

この問題はShellExecuteEx、新しいバックグラウンド スレッドを開始し、多くの COM を呼び出すという、非常に複雑なプロセスであるという事実に起因しています。セキュリティ上の理由から、どこかで書き込みを有効にする必要があります。

UAC を無効にしてみてください。しかし、良い解決策ではありません。

プログラムでプロセス権限を昇格するための対応するソリューションを見ると (ワイヤード マニフェストは昇格のもう 1 つの静的な方法です)、この SO 回答で引用されている 2 つのみを見つけることができます。

  • runasパラメータを指定して ShellExecuteEx を使用します。
  • 魔法の "Elevation:Administrator!new:" プレフィックスを使用して昇格した COM オブジェクトを作成します。

ShellExecuteExの仕組みを理解するには、 「Vista UAC: The Definitive Guide」の記事全体を読む価値があります。

だからここに私の答えがあります:昇格された権限でプロセスを実行する必要があり、既存の「CreateProcessElevated」APIはなく、大きなShellExecuteしかないため、2番目の実行可能ファイルにマニフェストファイルを使用するのが最も簡単です。

project1.exe ファイルを「AsInvoker」権限で実行するが、意図的に管理者権限のみで実行する場合は、次の 2 つの可能性があります。

  • 外部.manifestファイルを使用し、そのファイルをリソースとして exe に埋め込まないでください。次に、.manifestコンテンツを「AsInvoker」または「requireAdministrator」パラメーターのいずれかを使用して 1 つのバージョンに置き換えますが、読み取り専用メディアでは難しいですね。 ;
  • Elevate.exe2 番目の実行可能ファイルを起動する「requireAdministrator」レベルのマニフェストを含む、外部の 3 番目の実行可能ファイル (これを と呼びます) を使用します。このElevate.exeプログラムのパラメーターとして exe とコマンド ラインを指定できます。
于 2011-07-09T08:16:16.860 に答える