Как получить CreateProcess / CreateProcessW для выполнения процесса в пути> символов MAX_PATH - PullRequest
3 голосов
/ 27 сентября 2008

Я пытаюсь заставить CreateProcess или CreateProcessW выполнять процесс с именем http://msdn.microsoft.com/en-us/library/ms682425.aspx, мне нужно убедиться, что lpApplicationName не равно NULL, а затем lpCommandLine может содержать до 32 768 символов.

Я пробовал это, но я получаю ERROR_PATH_NOT_FOUND.

Я изменил на CreateProcessW, но все равно получаю ту же ошибку. Когда я префикс lpApplicationName с \\? \, Как описано в http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx при вызове CreateProcessW, я получаю другую ошибку, которая заставляет меня думать, что я немного ближе: ERROR_SXS_CANT_GEN_ACTCTX.

Мой вызов CreateProcessW:

CreateProcessW(w_argv0,arg_string,NULL,NULL,0,NULL,NULL,&si,&ipi);

где w_argv0 - \\?\<long absolute path>\foo.exe.

arg_string содержит "<длинный абсолютный путь> \ foo.exe" foo

si устанавливается следующим образом:

    memset(&si,0,sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;>

и пи пуст, как в:

    memset(&pi,0,sizeof(pi));

Я посмотрел в журнале системных событий, и каждый раз, когда я пытаюсь сделать это с идентификатором события 59, появляется новая запись, источник SideBySide: Создать контекст активации не удалось для .Manifest. Ссылочное сообщение об ошибке: Операция успешно завершена.

Файл, который я пытаюсь выполнить, работает нормально по пути

Для пояснения, ни один компонент <длинного абсолютного пути> не может быть больше символов MAX_PATH. Само название исполняемого файла, конечно, нет, даже с .manifest в конце. Но весь путь вместе длиннее символов MAX_PATH.

Я получаю ту же ошибку, независимо от того, вставляю ли я ее манифест или нет. Манифест называется foo.exe.manifest и находится в том же каталоге, что и исполняемый файл, если он не встроен. Содержит:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.VC80.DebugCRT' version='8.0.50727.762' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
</assembly>

Кто-нибудь знает, как заставить это работать? Возможно:

  • какой-либо другой способ вызова CreateProcess или CreateProcessW для выполнения процесса в пути> символов MAX_PATH

  • что я могу сделать в файле манифеста

Я собираюсь с Visual Studio 2005 на XP SP2 и работаю с native.

Спасибо за вашу помощь.

Ответы [ 2 ]

2 голосов
/ 28 сентября 2008

Встраивание манифеста и использование GetShortPathNameW сделали это для меня. Одного или другого одного было недостаточно.

Перед вызовом CreateProcessW с использованием префикса \\? - с префиксом полного пути процесса для выполнения в качестве первого аргумента я проверяю:

wchar&#95;t *w_argv0;
wchar&#95;t *w_short_argv0;

...

if (wcslen(w&#95;argv0) >= MAX&#95;PATH)
{
    num&#95;chars = GetShortPathNameW(w&#95;argv0,NULL,0);
    if (num&#95;chars == 0) {
        syslog(LOG&#95;ERR,"GetShortPathName(%S) to get size failed (%d)",<br/>               w&#95;argv0,GetLastError());
        /*
        ** Might as well keep going and try with the long name
        */
    } else {
        w&#95;short&#95;argv0 = malloc(num&#95;chars * sizeof(wchar&#95;t));
        memset(w&#95;short&#95;argv0,0,num&#95;chars * sizeof(wchar&#95;t));
        if (GetShortPathNameW(w&#95;argv0,w&#95;short&#95;argv0,num&#95;chars) == 0) {
            syslog(LOG&#95;ERR,"GetShortPathName(%S) failed (%d)",w&#95;argv0,<br/>            GetLastError());
            free(w&#95;short&#95;argv0);
            w&#95;short&#95;argv0 = NULL;
        } else {
            syslog(LOG_DEBUG,"using short name %S for %S",w&#95;short&#95;argv0,<br/>            w&#95;argv0);
        }
    }
}

и затем вызовите CreateProcessW (w_short_argv0? W_short_argv0: w_argv0 ...);

запоминание на свободе (w_short_argv0); после этого.

Это может решить не все случаи, но позволяет мне создавать больше дочерних процессов, чем я мог раньше.

1 голос
/ 27 сентября 2008

Я не вижу никаких ссылок в документации CreateProcess о том, что синтаксис '\\? \' Допустим для имени модуля. На странице «Наименование файла или каталога» также не указано, что CreateProcess поддерживает его, а такие функции, как CreateFile, ссылаются на страницу «Наименование файла».

Я делаю вижу, что вы не можете использовать имя модуля длиннее MAX_PATH в lpCommandLine, что говорит о том, что CreateProcess не поддерживает слишком длинные имена файлов. Сообщение об ошибке также указывает на то, что при попытке добавить «.manifest» в путь к приложению возникает ошибка (т. Е. Длина превышает MAX_PATH).

GetShortPathName () может быть в этом немного полезен, хотя он не гарантирует возврата имени, меньшего MAX_PATH (хотя он явно указывает, что синтаксис '\\? \' Допустим). В противном случае вы можете попробовать настроить переменную окружения PATH и передать ее в CreateProcess () в lpEnvironment. Или вы можете использовать SetCurrentDirectory () и передавать только имя исполняемого файла.

...