将项目转换为支持 Unicode 后,CreateProcess 不运行 .cmd 文件

Posted

技术标签:

【中文标题】将项目转换为支持 Unicode 后,CreateProcess 不运行 .cmd 文件【英文标题】:CreateProcess doesn't run .cmd file after converting project to support Unicode 【发布时间】:2014-08-22 04:52:43 【问题描述】:

我已更改旧的 MFC 应用程序以支持 Unicode。现在代码如下所示。基本上我在这里调用一个 .cmd 文件:

STARTUPINFO StartupInfo;
DWORD dwErrorCode;

PROCESS_INFORMATION * processInformation = new PROCESS_INFORMATION[2];

for (int i = 0; i < 2; i++)

    GetStartupInfo(&StartupInfo);

    if (processList[i].bHide)
    
        StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
        StartupInfo.wShowWindow = SW_HIDE;
    

    if (processList[i].sCustomTitle.GetLength())
        StartupInfo.lpTitle = processList[i].sCustomTitle.GetBuffer(processList[i].sCustomTitle.GetLength());

    CreateProcess(NULL, 
        /*I changed LPSTR to LPWSTR*/(LPWSTR)(LPCTSTR)processList[i].sCommandLine,
        NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &StartupInfo, &processInformation[i]);

    [...]

我所做的唯一更改是将LPSTR 更改为LPWSTR。在转换为 Unicode 之前,这没有任何问题。但现在它没有运行。可能是什么原因?在转换为Unicode 支持时,我是否遗漏了任何需要做的事情?

P.S.:我调试并检查了所有参数。他们看起来很好。 sCommandLineCString 变量在 PROCESS_STARTUP_INFO struct 中。

【问题讨论】:

去掉演员表。 “转换为 Unicode 支持”需要转换,而不是强制转换。 @BenVoigt 你的意思是只使用 processList[i].sCommandLine 而不是 (LPWSTR)(LPCTSTR)processList[i].sCommandLine ? 您必须将指针传递给以 NUL 结尾的 Unicode 字符串。您不能通过强制转换来创建 Unicode 字符串。 sCommandLine 是什么数据类型? @BenVoigt 这是一个 CString,所以我想我必须转换它。 CString 有一个隐式转换,你永远不应该写一个强制转换(例外:像printf这样的可变参数函数......但即使这样临时变量更好) 【参考方案1】:

如 cmets 中所述,您不应该转换字符串。您应该使用临时变量,因为documentation 中有以下注释:

此函数的 Unicode 版本 CreateProcessW 可以修改此字符串的内容。因此,此参数不能是指向只读内存的指针(例如 const 变量或文字字符串)。如果此参数是一个常量字符串,该函数可能会导致访问冲突。

最近我遇到了类似的问题。我通过以下方式解决了它(我试图让它防弹):

// The maximum length of the command line string is 32,768 characters,
// including the Unicode terminating null character.
#define MAX_CMD_LINE_LEN 32768

// Use a temporary variable for the command line.
TCHAR szCmdLine[MAX_CMD_LINE_LENGTH];

// Get the length of the command line. Crop the command line if it is too long.
int iLen = min(processList[i].sCommandLine.GetLength(), MAX_CMD_LINE_LEN - 1);

// Copy the command line string to the temporary variable.
_tcsncpy_s(szCmdLine, processList[i].sCommandLine, iLen);

// Create the process by passing the temporary variable holding a copy of your
// original command line string.
CreateProcess(NULL, 
              szCmdLine,
              NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL,
              NULL, &StartupInfo, &processInformation[i]);

此解决方案应该可以编译并适用于 Unicode 和非 Unicode 版本。

【讨论】:

以上是关于将项目转换为支持 Unicode 后,CreateProcess 不运行 .cmd 文件的主要内容,如果未能解决你的问题,请参考以下文章

将 Unicode 笑脸转换为 nsstring ios

Qt读取ANSI格式文件——利用QTextCodec将其他编码格式的QByteArray转换为Unicode格式,或者从文件中读出后直接做转换

在使用 Libreoffice 将任何文件转换为 pdf 时,它将日语(unicode)字符转换为括号

有没有办法将文件中的文本转换为 unicode?在 Python [重复]

如何将 DOS ANSI (CP 437) 文件转换为带有 Unicode 的 Unix ANSI?

VC下fopen如何支持中文