Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么只有在Visual Studio下运行可执行文件时CreateFileA才会失败?_C_Visual Studio_Winapi_File Io_Createfile - Fatal编程技术网

为什么只有在Visual Studio下运行可执行文件时CreateFileA才会失败?

为什么只有在Visual Studio下运行可执行文件时CreateFileA才会失败?,c,visual-studio,winapi,file-io,createfile,C,Visual Studio,Winapi,File Io,Createfile,我使用WinAPI编写了一个简单的check_file_ref函数来检查两个路径是否引用同一个文件。代码很好。它是用Visual Studio 2017在C flag/TC中编译的 奇怪的是,当可执行文件在Visual Studio ie execute下运行而不进行调试时,CreateFileA winapi总是失败,返回无效的文件句柄。否则,当可执行文件在VisualStudio之外运行时,它将按预期工作 工作目录在任何情况下都是相同的 主要条款c: #include <stdio.h

我使用WinAPI编写了一个简单的check_file_ref函数来检查两个路径是否引用同一个文件。代码很好。它是用Visual Studio 2017在C flag/TC中编译的

奇怪的是,当可执行文件在Visual Studio ie execute下运行而不进行调试时,CreateFileA winapi总是失败,返回无效的文件句柄。否则,当可执行文件在VisualStudio之外运行时,它将按预期工作

工作目录在任何情况下都是相同的

主要条款c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

/**
 * Check whether two paths reference the same file.
 * @param p1 File path 1.
 * @param p2 File path 2.
 * @return 0 same file, 1 different files, < 0 on failure.
 */
int
check_file_ref(char const * p1, char const * p2)
{
    if ( !p1 || !p2 )
        return -1;
    if ( p1 == p2 )
        return 0;
    if ( strcmp(p1, p2) == 0 )
        return 0;

    int ret;
    DWORD share, flags;
    HANDLE f1, f2;
    BY_HANDLE_FILE_INFORMATION s1, s2;

    ret = -1;
    share = FILE_SHARE_READ | FILE_SHARE_WRITE;
    flags = FILE_ATTRIBUTE_NORMAL;

    f1 = CreateFileA(p1, GENERIC_READ, share, NULL, OPEN_EXISTING, flags, NULL);
    f2 = CreateFileA(p2, GENERIC_READ, share, NULL, OPEN_EXISTING, flags, NULL);

    if ( f1 == INVALID_HANDLE_VALUE ) {
        fprintf(stderr, "Could not open %s file, error %d\n", p1, GetLastError());
        goto cleanup;
    }
    if ( f2 == INVALID_HANDLE_VALUE ) {
        fprintf(stderr, "Could not open %s file, error %d\n", p2, GetLastError());
        goto cleanup;
    }
    if ( GetFileInformationByHandle(f1, &s1) == 0 ) {
        fprintf(stderr, "Could not get %s file information, error %d\n", p1, GetLastError());
        goto cleanup;
    }
    if ( GetFileInformationByHandle(f2, &s2) == 0 ) {
        fprintf(stderr, "Could not get %s file information, error %d\n", p2, GetLastError());
        goto cleanup;
    }

/*
    The identifier (low and high parts) and the volume serial number uniquely
    identify a file on a single computer. To determine whether two open handles
    represent the same file, combine the identifier and the volume serial number
    for each file and compare them.

    See
    https://docs.microsoft.com/fr-fr/windows/desktop/api/fileapi/nf-fileapi-getfileinformationbyhandle
    https://docs.microsoft.com/fr-fr/windows/desktop/api/fileapi/ns-fileapi-_by_handle_file_information
*/
    ret = !(s1.dwVolumeSerialNumber == s2.dwVolumeSerialNumber
        &&  s1.nFileIndexLow == s2.nFileIndexLow
        && s1.nFileIndexHigh == s2.nFileIndexHigh);

cleanup:
    CloseHandle(f2);
    CloseHandle(f1);
    return ret;
}


int main()
{
    int ret;
    char workingDir[256];

    /* Both paths reference the same file.
       One is relative, the other absolute. */
    char * p1 = "hello.txt";
    char * p2 = "C:/Users/bro/source/repos/tests/x64/Debug/hello.txt";

    ret = GetModuleFileNameA(NULL, workingDir, sizeof(workingDir));
    printf("working dir: %s\n", (ret == 0 ? "err" : workingDir));

    /* Should return 0. */
    ret = check_file_ref(p1, p2);
    printf("p1: %s\n", p1);
    printf("p2: %s\n", p2);
    printf("check_file_ret ret %d ", ret);

    if      ( ret == 0 ) printf("(same file)\n");
    else if ( ret == 1 ) printf("(different files)\n");
    else                 printf("(error)\n");

    return 0;
}
可执行文件在visual Studio下运行:

可执行文件直接从命令行运行:


为什么只有在Visual Studio下运行可执行文件时CreateFileA才会失败?

从VisualStudio运行应用程序时,默认工作目录是项目位置,由VS宏$ProjectDir定义。您可以通过打开项目属性来更改它:在解决方案资源管理器中右键单击该项目,然后从关联菜单中选择属性。这里选择调试并更改工作目录属性。例如,在您的情况下,解决方案可以是$OutDir或到所需位置的绝对路径。

检查并比较GetCurrentDirectory-GetModuleFileName不适用于工作目录。GetLastError不提供信息。您应该在调用失败后立即使用它。您将连续调用CreateFile两次,然后在两次调用完成后调用GetLastError。如果打开f1时出现问题,错误代码为lostYou正确,谢谢!从visual运行时的工作目录是C:[..]\tests\tests,直接是C:[..]\tests\tests\x64\DebugGovind Parma,这一点很明显。最初我没有使用GetLastError。我添加它是为了调试。永远不要依赖相对文件路径,始终使用绝对文件路径。如果要打开其路径相对于应用程序自身路径的文件,请首先通过GetModueFileName检索应用程序的路径,然后根据需要替换文件名部分。