2

次のコードがあります。

#include <windows.h>
#include <stdio.h>
#include <shlwapi.h>

#pragma comment ( lib, "shlwapi.lib" )

int __cdecl wmain( int argc, PWSTR argv[] )
{
HANDLE Job( CreateJobObject( NULL, NULL ) );
if( !Job )
{
    wprintf( L"Could not create job object, error %d\n", GetLastError() );
    return 0;
}

HANDLE IOPort( CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 1 ) );
if( !IOPort )
{
    wprintf( L"Could not create IO completion port, error %d\n", GetLastError() );
    return 0;
}

JOBOBJECT_ASSOCIATE_COMPLETION_PORT Port;
Port.CompletionKey = Job;
Port.CompletionPort = IOPort;

if( !SetInformationJobObject( Job, JobObjectAssociateCompletionPortInformation, &Port, sizeof( Port ) ) )
{
    wprintf( L"Could not associate job with IO completion port, error %d\n", GetLastError() );
    return 0;
}

PROCESS_INFORMATION ProcessInformation;
STARTUPINFO StartupInfo = { sizeof(StartupInfo) };
PWSTR CommandLine = PathGetArgs(GetCommandLine());

if( !CreateProcess( NULL, CommandLine, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInformation ) )
{
    wprintf( L"Could not run process, error %d\n", GetLastError() );
    return 0;
}

if( !AssignProcessToJobObject( Job, ProcessInformation.hProcess ) )
{
    wprintf( L"Could not assign process to job, error %d\n", GetLastError() );
    return 0;
}

ResumeThread( ProcessInformation.hThread );
CloseHandle( ProcessInformation.hThread );
CloseHandle( ProcessInformation.hProcess );

DWORD CompletionCode;
ULONG_PTR CompletionKey;
LPOVERLAPPED Overlapped;

int ProcessCount = 0;

while ( GetQueuedCompletionStatus( IOPort, &CompletionCode, &CompletionKey, &Overlapped, INFINITE ) && CompletionCode != JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO )
{
    if ( CompletionCode == JOB_OBJECT_MSG_NEW_PROCESS ) ProcessCount++;
    if ( ( CompletionCode == JOB_OBJECT_MSG_EXIT_PROCESS ) || ( CompletionCode == JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS) ) ProcessCount--;

    wprintf( L"Waiting for %d processes to finish...\n", ProcessCount );
}

wprintf( L"All done\n" );

return 0;
}

このコードは Windows 7 では問題なく動作しますが、AssignProcessToJobObject は Windows XP ではエラー コード 5 (アクセスが拒否されました) で失敗します。MSDN によると: Windows 7、Windows Server 2008 R2、Windows XP with SP3、Windows Server 2008、Windows Vista、および Windows Server 2003: プロセスがまだジョブに割り当てられていてはなりません。そうである場合、関数は ERROR_ACCESS_DENIED で失敗します。この動作は、Windows 8 および Windows Server 2012 以降で変更されました。

誰かがこのコードを修正するのを手伝ってくれませんか?

ありがとう!

更新: 問題を見つけることができましたが、まだ解決方法がわかりません:(問題は、XPマシンに標準ユーザー(管理者権限なし)でログインし、cmdを開くことですrunas (管理者権限を持つユーザー) を使用すると、このコマンドはジョブ オブジェクトとして作成されます。プロセス エクスプローラーで確認できます。このコマンドからアプリケーションを起動したい場合、AssignProcessToJobObject はエラー アクセス拒否で失敗します。 thios cmd は既にジョブに割り当てられています。

私の問題を解決する方法はありますか?

4

1 に答える 1

2

コードが実行されている環境で、親プロセスが含まれるジョブが既に作成されている可能CREATE_BREAKAWAY_FROM_JOB性があります。新しいプロセスが現在のジョブから中断できるように、プロセス作成フラグに追加してみてください。 .

Visual Studio がデバッガーの下で何かを実行するときに、ジョブで何かを実行するかどうかを思い出せません。

また、現在のプロセスのジョブ ステータスを照会してみてください。これは、既に job にある場合に表示されます。

于 2012-11-20T08:51:23.717 に答える