【问题标题】:CreateProcess() fails with an access violation [duplicate]CreateProcess() 因访问冲突而失败 [重复]
【发布时间】:2012-07-05 13:17:36
【问题描述】:

我的目标是在我的程序中执行一个外部可执行文件。首先,我使用了system() 函数,但我不想让用户看到控制台。所以,我搜索了一下,发现CreateProcess()函数。但是,当我尝试将参数传递给它时,我不知道为什么,它失败了。我从 MSDN 拿了这段代码,做了一点改动:

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

void _tmain( int argc, TCHAR *argv[] )
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
    /*
    if( argc != 2 )
    {
        printf("Usage: %s [cmdline]\n", argv[0]);
        return;
    }
    */
    // Start the child process. 
    if( !CreateProcess( NULL,   // No module name (use command line)
        L"c:\\users\\e\\desktop\\mspaint.exe",        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    ) 
    {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return;
    }

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
}

但是,此代码以某种方式引发了访问冲突。我可以在不向用户显示控制台的情况下执行 mspaint 吗?

非常感谢。

【问题讨论】:

  • 一方面,CreateProcess 要求其第二个参数(如果提供)是非常量字符串。我不确定这在实践中是否存在问题,但为了完整起见,我想提一下。
  • ...否则,AV 发生在哪里?你有调用栈吗?
  • @reuben Uhm...我不太确定,但我猜这是调用堆栈的输出:kernel32.dll!76da70ac() [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll] &gt; msvcr100d.dll!_nh_malloc_dbg(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine) Line 302 + 0x1d bytes C++

标签: c winapi createprocess


【解决方案1】:

第二个参数是LPTSTR,即指向一个非常量字符数组的指针。 docs具体说:

此参数不能是指向只读内存的指针(例如 const 变量或文字字符串)

传递字符串文字的原因是一个问题:

系统在命令行中添加终止空字符 将文件名与参数分开的字符串。这将 将原始字符串分成两个字符串进行内部处理。

这意味着在您的情况下,它会尝试修改只读内存,从而导致崩溃。

【讨论】:

  • 我也无法分配 LPTSTR。如果我可能会问,我的第二个参数必须是什么来执行位于“c:\users\e\desktop\”的 mspaint?非常感谢。
  • @JohnDoe: wchar_t path[] = L"C:\\users\\e\\desktop\\"
  • wchar_t path[] = L"C:\\blahblah"LPWSTR path = L"C:\\blahblah" 不同,但与wchar_t* path = L"C:\\blahblah" 相同。您应该使用@hmjd 建议的内容,或者您​​应该定义LPWSTR path,然后为该变量分配内存并将路径复制到它。
  • @DenisV - wchar_t path[] = L"C:\\users\\e\\desktop\\" 肯定与wchar_t* path = L"C:\\blahblah" 不一样(但后者实际上与LPWSTR path = L"C:\\blahblah" 相同,这很糟糕)。
  • @GSerg,这可能是我了解这些东西的地方,当时是那个博客的狂热读者。人们仍然犯这个错误的事实(这意味着操作系统不使用额外的缓冲区并且编译器默默地将字符串文字转换为char*)有点令人不安,即使它让我偶尔投赞成票;)跨度>
【解决方案2】:

试试这个,应该可以的。

TCHAR lpszClientPath[500]= TEXT("c:\\users\\e\\desktop\\mspaint.exe");
if(!CreateProcess(NULL, lpszClientPath, NULL, NULL, FALSE,  NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE|CREATE_UNICODE_ENVIRONMENT,NULL, NULL, &si, &pi))
            {
    printf( "CreateProcess failed (%d).\n", GetLastError() );
        return;
            }
...
...

【讨论】:

    【解决方案3】:

    把你的代码改成这样:

    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>
    
    void _tmain( int argc, TCHAR *argv[] )
    {
        TCHAR ProcessName[256];
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        wcscpy(ProcessName,L"c:\\users\\e\\desktop\\mspaint.exe");
        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
        /*
        if( argc != 2 )
        {
            printf("Usage: %s [cmdline]\n", argv[0]);
            return;
        }
        */
        // Start the child process. 
        if( !CreateProcess( NULL,   // No module name (use command line)
            ProcessName,        // Command line
            NULL,           // Process handle not inheritable
            NULL,           // Thread handle not inheritable
            FALSE,          // Set handle inheritance to FALSE
            0,              // No creation flags
            NULL,           // Use parent's environment block
            NULL,           // Use parent's starting directory 
            &si,            // Pointer to STARTUPINFO structure
            &pi )           // Pointer to PROCESS_INFORMATION structure
        ) 
        {
            printf( "CreateProcess failed (%d).\n", GetLastError() );
            return;
        }
    
        // Wait until child process exits.
        WaitForSingleObject( pi.hProcess, INFINITE );
    
        // Close process and thread handles. 
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-13
      • 1970-01-01
      • 2021-03-26
      • 1970-01-01
      相关资源
      最近更新 更多