CreateProcessA %appdata%

CreateProcessA %appdata%

我正在尝试使用 CreateProcessA 调用 %appdata% 目录下的应用程序。

例如,使用以下内容:

CreateProcessA(
    NULL, "%appdata%\myfile.exe", NULL, NULL, FALSE,
    CREATE_NO_WINDOW, NULL, NULL, &sI, &pI
);

调用 myfile.exe 时是否需要使用完整路径,或者我是否可以在调用 CreateProcessA 时使用 %appdata%

MSDN 所述,并且由于您将 NULL 作为第一个参数传递给 CreateProcessA,因此 CreateProcessA 的第二个参数:lpApplicationName 正在扮演要执行的命令行的角色。除非lpApplicationName指向某个目录下的exe,否则系统会按如下顺序查找

  1. The directory from which the application loaded.
  2. The current directory for the parent process.
  3. The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory
  4. The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
  5. The directories that are listed in the PATH environment variable. Note that this function does not search the per-application path specified by the App Paths registry key. To include this per-application path in the search sequence, use the ShellExecute function.

因此,除非 CreateProcessA 的第二个参数采用 {directory}/{executable_name}.{ext} 形式,否则您必须:

  1. 将executable_name放在应用程序加载的同一目录中
  2. 将executable_name放在父进程的同一目录下
  3. 将 executable_name 放在 Windows System32 目录中:C:\Windows\System32
  4. 将executable_name放在Windows目录中:C:\Windows
  5. 在 PATH
  6. 中包含 executable_name 所在的目录

正如 Ben 所述,请查看 ExpandEnvironmentStrings 以修改 PATH 环境变量。

CreateProcess中的第二个参数应该是一个可写缓冲区。如果您的可执行路径不包含命令行参数,则将可执行路径放在第一个参数中,并保留第二个参数 NULL

对于 Windows Vista 及更高版本使用 SHGetKnownFolderPath

FOLDERID_LocalAppData returns "c:\users\username\AppData\Local"
FOLDERID_RoamingAppData returns "c:\users\username\AppData\Roaming"

ExpandEnvironmentStrings("%APPDATA%", ...) returns 等同于 FOLDERID_RoamingAppData

除非您确信用户名与 ANSI 兼容,否则您应该使用 Unicode。

wchar_t *ptr;
if(S_OK == SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &ptr))
{
    //or FOLDERID_LocalAppData
    std::wstring path = ptr;
    CoTaskMemFree(ptr);

    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi;
    path += L"\myfile.exe";
    CreateProcessW(NULL, &path[0], NULL, NULL, FALSE, 
            CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
}