3

I wanted to make a simple program for classifying files by their extensions, but when tried to compile got the error

Severity Code Description Project File Line Error LNK2019 unresolved external symbol __imp__PathFileExistsW@4 referenced in function "void __cdecl classifyFiles(void)" (?classifyFiles@@YAXXZ)

My code is where PathFileExists is called is this:

void classifyFiles() {
    for (int i = 0; i < files.max_size(); i++) {
        //if each folder doesn't exist, create folder
        LPCWSTR folderName = (L"\\" + extensions.at(i)).c_str();
        if (!PathFileExistsW(folderName)) {
            CreateDirectory(folderName, NULL);
        };
        LPCWSTR destination = (extensions.at(i) + files.at(i)).c_str();
        //move file
        MoveFile(files.at(i).c_str(), destination);
    }
}

I googled a little and it seems it is not enough with including the Shlwapi.h header and also need to link the library. But I can't find any answer about how to do it in Visual Studio.

Note: I am also having problem finding were are each menu and everything (this is my first time with Visual Studio), so please make it clear where to find what and if possible include screenshots.

References: https://msdn.microsoft.com/en-us/library/windows/desktop/bb773584(v=vs.85).aspx

Carlos
  • 121
  • 1
  • 1
  • 8
  • Please see [this question](http://stackoverflow.com/questions/20058864/how-to-include-libraries-in-visual-studio-2012) – meJustAndrew Jul 03 '16 at 07:21
  • @meJustAndrew This is a headache. I can't find where to download the file from windows, so maybe I don't have to do that. I got to download it from an X website. I make a new line in library directories but I can't set the dll, because it doesn't appear on the screen. Do you have any idea of what should I do to make this shlwapi library to work? – Carlos Jul 03 '16 at 07:59
  • I SOLVED THE PROBLEM. THE PROBLEM WAS THAT I WAS USING AN IF. YOU CAN'T USE IF'S WITH BOOL TYPES. There is not need to adding any weird extra configuration. – Carlos Jul 03 '16 at 08:34
  • Update: You also need to write #pragma comment(lib, "Shlwapi.lib"). But if I kept using the if I kept having the same error no matter if wrote the pragma. I don't even know why are these errors so tricky – Carlos Jul 03 '16 at 08:41
  • 1
    Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – IInspectable Jul 03 '16 at 12:26
  • 1
    The pragma directive is **one** way to pass settings to the linker. How to specify linker settings using your IDE is explained in your IDE's manual. – IInspectable Jul 03 '16 at 12:29
  • @IInspectable I hate microsofts' articles. I've tried reading a couple of them no one resolved my problems, specially because at some point they are not very precise as some other SO answers I've seen (I made a new project and worked, the problem was that I deleted some files by "accident"). I don't know where to find a manual for VS and if I found one I wouldn't know how to look for what I was looking for, since I didn't know what did linker mean until yesterday (I still don't understand if fully). PS: Please stop the hate or I'm going to get banned from asking at SO longer – Carlos Jul 03 '16 at 20:15
  • From [PathFileExists](https://msdn.microsoft.com/en-us/library/windows/desktop/bb773584.aspx): *"Library: Shlwapi.lib"*. Documentation for the linker and how your IDE can be used to set up your project: [.Lib Files as Linker Input](https://msdn.microsoft.com/en-us/library/ba1z7822.aspx). – IInspectable Jul 04 '16 at 15:20

3 Answers3

9

Add shlwapi.lib to your dependency list:

Configuration Properties -> Linker -> Input -> Additional Dependencies

Jiminion
  • 5,080
  • 1
  • 31
  • 54
2

There are two things I did for the build to succeed: Add
#pragma comment(lib, "Shlwapi.lib")
after the includes. In my specific case changing the following line of code made a difference, for some reason, even if they are the same. Changing:

if (!PathFileExistsW(folderName))

To:

if (PathFileExistsW(folderName) == FALSE)

For some reason using the value of PathFileExists like the first outputted a linking error even if everything else was in order. The next day I tested it again and it worked both ways. Maybe it was my imagination and was making some mistake.

Carlos
  • 121
  • 1
  • 1
  • 8
  • 1
    Actually, you always want to compare to `FALSE`, since a false condition is always 0 (and `FALSE` is a constant 0). A true condition can be *any* non-zero value, and may not necessarily be `TRUE` (which is a constant 1). The original code that you say is "wrong" was actually fine and is idiomatic C++. – Cody Gray - on strike Jul 03 '16 at 09:51
  • It doesn't matter **where** you put the linker directive. It is a linker setting after all, an the compiler will emit it into the object code, irrespective of where it sees it. – IInspectable Jul 03 '16 at 12:25
  • There is *NO DIFFERENCE* between using `!` vs `== FALSE` for a `BOOL` value. Whichever one you use has *NO EFFECT* whatsoever on the linker at all. `!` correctly interprets a zero as false and a non-zero as true. The function is clearly documented as returning "*TRUE if the file exists; otherwise, FALSE*". There is no other value returned. `!` works just fine on all APIs that return a `BOOL`. – Remy Lebeau Jul 03 '16 at 17:46
  • Well, then it is very strange that with only changing that line I could build the code – Carlos Jul 03 '16 at 20:05
  • @Cody Gray: I know that, but I felt like if for some reason a number different than 1 (like a negative) was returned it shouldn't be treated as true. Anyways, it's the first time I use the BOOL type. If the code I said was wrong is actually good, then I'm just more confused. Changing that line got rid off the linking error. I had the pragma line before and kept having the error. Now I have another trouble with FindFirstFile returning always INVALID_HANDLE_VALUE. – Carlos Jul 03 '16 at 20:08
  • I tested it again and it seems you are right, there is no difference. (Still strange why didn't it work!) – Carlos Jul 03 '16 at 20:32
  • Remy is actually correct here. `PathFileExists` is specifically documented as either returning TRUE or FALSE. That is not the typical case, though. Generally when you see a Windows API function that returns a BOOL, it returns FALSE if it fails, or non-zero if it succeeds. That non-zero *might* be TRUE, but it might not be. You cannot assume that failure is anything else but FALSE. That's why you compare to FALSE, or just use the logical negation operator, as suggested. Perhaps your first attempt received a compiler *warning*, something about coercing an integer to a boolean? – Cody Gray - on strike Jul 04 '16 at 11:43
  • MSVC issues a warning in these cases, calling it something like a "performance warning". This is not an error, just a warning, but it looks kind of scary if you don't know what's up. Google it for more information (a good strategy with errors/warnings anyway). Their suggested workaround is to compare explicitly against FALSE. The customary pattern is: `if (WinAPIFunction(...) != FALSE) { // it worked }`. The exact same object code is generated in both cases, so it's basically a stupid warning. – Cody Gray - on strike Jul 04 '16 at 11:44
  • There's no need to add the `== FALSE` in the code. With the `!` operator works fine (at least in VS2013). Not sure what madness is going on in your code :) – newlog May 12 '17 at 15:42
  • It is better to add shlwapi.lib to your dependency list than to add a #pragma. – Jiminion Apr 05 '18 at 13:57
  • @Carlos I also encounter the same issue, only adding #pragma can successfully build. Then I found that the build error is actually from another test project, not the project I added lib dependency. FYI. – Houcheng Mar 21 '19 at 05:59
  • Somehow this wasn't enough in my case, had to manually add it to the linker dependencies... – rogerdpack Dec 23 '22 at 07:19
0

First you need to add VC++ directories Then you need to set linker input.

Ivan Rubinson
  • 3,001
  • 4
  • 19
  • 48