CreateProcess завершается успешно, но GetLastError() возвращает отказ в доступе

У меня небольшая путаница из-за противоречивых возвращаемых значений от CreateProcess() и GetLastError(). Когда я использую CreateProcess() способом, подобным приведенному ниже, он преуспевает и, кажется, выполняет свои требуемые задачи. Тем не менее, GetLastError() по-прежнему возвращает сообщение «Отказано в доступе».

Если в доступе отказано, почему появляется возможность выполнить задачу. Напротив, если CreateProcess() завершается успешно, почему GetLastError() возвращает отказ в доступе?

Или я неправильно использую GetLastError()? Я должен использовать его только тогда, когда CreateProcess() возвращает ошибочное значение? (Мое оправдание приведенного ниже поведения заключалось в том, что я решил, что лучше перестраховаться, чем сожалеть)

    SetLastError(0);
    hello = CreateProcess(_T("C:\\Windows\\System32\\cmd.exe"), 
        _T("C:\\Windows\\System32\\cmd.exe /C ant debug"),
        NULL,NULL,false,0,NULL,
        _T("C:\\My\\Directory"),&siStartupInfo, &piProcessInfo);
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ALLOCATE_BUFFER 
        |FORMAT_MESSAGE_IGNORE_INSERTS,NULL,GetLastError(), 
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
        (LPTSTR)&errorText, 0, NULL); 
    AfxMessageBox(errorText);

Является ли такой тип поведения нормальным? В документации CreateProcess() упоминается использование GetLastError() при сбое CreateProcess(), но не упоминается обратное. Не критикуя документацию, просто хотелось бы пояснений.

Это происходит независимо от того, равен ли второй параметр в CreateProcess() NULL или нет. Может быть, это связано с cmd.exe разрешениями? Если это так, не должен ли CreateProcess() потерпеть неудачу? Спасибо.


person JHowzer    schedule 18.06.2012    source источник
comment
Да, вы используете GetLastError неправильно. Вы должны использовать его только тогда, когда CreateProcess терпит неудачу. CreateProcess может (и использует) использовать API, которые могут установить последнюю ошибку, и он не обязан сбрасывать ее на 0, поскольку возвращает значение, указывающее на успех.   -  person Erik    schedule 18.06.2012
comment
Спасибо за ответ. Я только сбрасывал его на ноль, чтобы показать, что это не может быть функция до CreateProcess().   -  person JHowzer    schedule 18.06.2012


Ответы (2)


Из документации GetLastError

В разделе «Возвращаемое значение» документации для каждой функции, которая устанавливает код последней ошибки, указаны условия, при которых функция устанавливает код последней ошибки. Большинство функций, которые устанавливают код последней ошибки потока, устанавливают его при сбое. Однако некоторые функции также устанавливают код последней ошибки при успешном выполнении. [выделено мной]

Я думаю, вы получите опытный результат, потому что в случае успеха CreateProcess не устанавливает значение ошибки, которое возвращает GetLastError. Вместо этого ваш вызов GetLastError возвращает ошибку, установленную другой функцией, вызванной ранее.

person Attila    schedule 18.06.2012
comment
Спасибо. Если я SetLastError(0) непосредственно перед вызовом CreateProcess, не должен ли он возвращать 0, а не 5? - person JHowzer; 18.06.2012
comment
@JHowzer - это зависит от того, как реализован CreateProcess. Если он вызывает другие функции, они также могут установить значение ошибки. - person Attila; 19.06.2012

GetLastError имеет смысл только тогда, когда в документации указано, что это имеет смысл.

GetLastError возвращает последнюю ошибку потока Win32, установленную с помощью SetLastError. Поскольку предполагается, что функции устанавливают или сбрасывают последнюю ошибку только тогда, когда документально подтверждено, что они это делают, если этого не произошло, последняя ошибка вполне может содержать более раннюю ошибку, которая не имеет значения.

Документировано, что CreateProcess установит последнюю ошибку в случае неудачи, а не в случае успеха. Поэтому вы должны игнорировать это.

person Ben    schedule 18.06.2012