打开 NFC - 错误 LNK2019:无法解析的外部符号 __imp__ShellExecuteW@24

Lui*_*nez 2 c++ nfc visual-studio visual-c++ open-nfc

我有一个错误,但我不知道 xc2xb4 是什么问题。

\n\n

我正在尝试为一个项目编译一个 Open NFC 示例。示例是 test_ndef_url。我不知道问题是否出在编码错误或Windows库上,shellapi.h。

\n\n

test_ndef_url代码是:

\n\n
    /*\n * Copyright (c) 2007-2012 Inside Secure, All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the "License");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an "AS IS" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/*******************************************************************************\n\n  Implementation of the Example 1 for Open NFC.\n\n*******************************************************************************/\n\n/* Allow use of features specific to Windows XP or later. */\n#ifndef _WIN32_WINNT\n/* Change this to the appropriate value to target other versions of Windows. */\n#define _WIN32_WINNT 0x0601\n#endif\n\n/* Suppress many files from the compilation */\n#define WIN32_LEAN_AND_MEAN\n#include "windows.h"\n#include "shellapi.h"\n#include <stdio.h>\n#include <stdlib.h>\n\n#include "open_nfc.h"\n\n#include "win32_test_core.h"\n\n/* Type definititions */\n/* ------------------ */\n\n/* Local prototypes */\n/* ---------------- */\n\n/* Global variables */\n/* ---------------- */\n\nstruct __testContext\n{\n   char16_t*      pURL;\n   bool_t        bVirtualTag;\n   bool_t        bReadTest;\n   W_HANDLE    hRegistry;\n} ;\n\nstruct __testContext g_testCtx = { null, W_FALSE, W_FALSE, W_NULL_HANDLE };\n\n/* Callback function of type tWBasicGenericHandleCallbackFunction */\nstatic void ReadMessageOnAnyTagCompletedURL(void *pCallbackParameter, W_HANDLE hMessage, W_ERROR nError)\n{\n   if(nError == W_SUCCESS)\n   {\n      W_HANDLE hRecord = WNDEFGetRecord(hMessage, 0);\n      WBasicCloseHandle(hMessage);\n\n      if(WRTDIsURIRecord(hRecord))\n      {\n         char16_t aURIValue[256];\n\n         if(WRTDURIGetValue(hRecord, (char16_t*)&aURIValue, 256) == W_SUCCESS)\n         {\n            printf("The URL read in the tag is \\"%S\\"\\n", aURIValue);\n\n            ShellExecute(NULL, L"open", (char16_t*)aURIValue, NULL, NULL, SW_SHOWNORMAL);\n         }\n      }\n      else\n      {\n         printf("Error URL: Error detected in the tag message.\\n");\n      }\n\n      WBasicCloseHandle(hRecord);\n   }\n   else if(nError == W_ERROR_ITEM_NOT_FOUND)\n   {\n      printf("Error URL: This tag does not contain a message of the right type.\\n");\n   }\n   else if(nError == W_ERROR_TIMEOUT)\n   {\n      printf("Error URL: Lost the communication with the tag.\\n");\n   }\n   else\n   {\n      printf("Error URL: Error 0x%08X returned during the tag detection.\\n", nError);\n   }\n\n   printf("Present a new tag to be read or press Ctrl+C to stop the application\\n");\n}\n\n/* Callback function of type tWBasicGenericCallbackFunction */\nstatic void WriteMessageOnAnyTagCompleted(void *pCallbackParameter, W_ERROR nError)\n{\n   switch(nError)\n   {\n      case W_SUCCESS:\n         printf("The message is written in the tag.\\n");\n         break;\n      case W_ERROR_LOCKED_TAG:\n         printf("The operation failed because the tag is locked.\\n");\n         break;\n      case W_ERROR_TAG_FULL:\n         printf("The message is too large for the remaining free space in the tag.\\n");\n         break;\n      default:\n         printf("An error occured during the writing operation (code 0x%x)\\n", nError);\n         break;\n   }\n   StopApplication();\n}\n\n/* Receive the event of the virtual tag */\nstatic void VirtualTagEventHandler(void *pCallbackParameter, uint32_t nEventCode)\n{\n   switch(nEventCode)\n   {\n      case W_VIRTUAL_TAG_EVENT_SELECTION:\n         printf("The tag is selected by the reader.\\n");\n         break;\n      case W_VIRTUAL_TAG_EVENT_READER_LEFT:\n         printf("The reader left the tag without reading the content.\\n");\n         break;\n      case W_VIRTUAL_TAG_EVENT_READER_READ_ONLY :\n         printf("The reader read the tag.\\nPresent again a reader to read the virtual tag or press Ctrl+C to stop the application\\n");\n         break;\n      case W_VIRTUAL_TAG_EVENT_READER_WRITE:\n      default:\n         printf("This event should not occur for a read-only virtual tag.\\n");\n         break;\n   }\n}\n\n/**\n * GetSpecificTestSyntax\n *\n * @return     String describing the command line syntax specific to this test\n **/\nchar16_t * GetSpecificTestSyntax( void )\n{\n   return L"[url <URL> | virtualurl <URL>\\n"\n          L" - If the parameter is not present, the application waits to read a tag with an URL.\\n"\n          L" - If \\"url\\" is present, the application waits for a Tag to write the URL.\\n"\n          L" - If \\"virtualurl\\" is present, the application simulates a tag containing the URL.\\n\\n"\n          L"The following tags are supported: Type 2, Type 4-A, Type 4-B, Type 5-2K, Type 5-32K and Type 6.\\n\\n" ;\n}\n\n/**\n * VerifyTestConditions\n *\n * @param[in]  nArgc       number of arguments\n *\n * @param[in]  pArgv       arguments array\n *\n * @return     W_SUCCESS   Arguments syntax is correct\n *             W_ERROR_xxx is syntax error is detected\n **/\n\nW_ERROR VerifyTestConditions( int32_t nArgc, char16_t* pArgv[] )\n{\n   if(nArgc == 3)\n   {\n      if(wcscmp(pArgv[1], L"url") == 0)\n      {\n         g_testCtx.pURL = pArgv[2];\n      }\n      else if(wcscmp(pArgv[1], L"virtualurl") == 0)\n      {\n         g_testCtx.bVirtualTag = W_TRUE;\n         g_testCtx.pURL = pArgv[2];\n      }\n      else\n      {\n         nArgc = 0;\n      }\n   }\n\n   if((nArgc != 1) && (nArgc != 3))\n   {\n      return W_ERROR_BAD_PARAMETER;\n   }\n\n   g_testCtx.bReadTest = (nArgc == 1) ? W_TRUE : W_FALSE ;\n\n   return W_SUCCESS;\n}\n\n/**\n * LaunchTest\n *\n **/\n\nW_ERROR LaunchTest( void )\n{\n   W_HANDLE hMessage = W_NULL_HANDLE;\n\n   if(g_testCtx.bReadTest != W_FALSE)\n   {\n      WNDEFReadMessageOnAnyTag(ReadMessageOnAnyTagCompletedURL, null, W_PRIORITY_MAXIMUM,\n         W_NDEF_TNF_WELL_KNOWN, L"U", &g_testCtx.hRegistry);\n\n      printf("Present the tag to be read or press Ctrl+C to stop the application\\n");\n   }\n   else\n   {\n      if(WNDEFCreateNewMessage(&hMessage) != W_SUCCESS)\n      {\n         printf("Error: Cannot create the new message.\\n");\n         goto return_function;\n      }\n      if(WRTDURIAddRecord(hMessage, g_testCtx.pURL) != W_SUCCESS)\n      {\n         printf("Error: Cannot add the URI record in the message.\\n");\n         goto return_function;\n      }\n\n      if(g_testCtx.bVirtualTag == W_FALSE)\n      {\n         printf("Ready to write the URL \\"%S\\"\\n", g_testCtx.pURL);\n\n         WNDEFWriteMessageOnAnyTag(WriteMessageOnAnyTagCompleted, null, W_PRIORITY_MAXIMUM, hMessage, W_NDEF_ACTION_BIT_ERASE | W_NDEF_ACTION_BIT_FORMAT_ALL, &g_testCtx.hRegistry);\n\n         printf("Present the tag to be written or press Ctrl+C to stop the application\\n");\n      }\n      else\n      {\n         W_ERROR nError;\n         W_HANDLE hVirtualTag;\n         static const uint8_t aPUPI[] = { 0x01, 0x02, 0x03, 0x04 };\n\n         printf("Ready to simulate a tag with the URL \\"%S\\"\\n", g_testCtx.pURL);\n\n         /* Create the virtual tag, the maximum length is set to the size of the message */\n         nError = WVirtualTagCreate(W_PROP_NFC_TAG_TYPE_4_B, aPUPI, sizeof(aPUPI),\n            WNDEFGetMessageLength(hMessage), &hVirtualTag);\n         if(nError != W_SUCCESS)\n         {\n            printf("Cannot create the virtual tag\\n");\n         }\n         else\n         {\n            /* Write the message in the virtual tag */\n            nError = WNDEFWriteMessageSync(hVirtualTag, hMessage, W_NDEF_ACTION_BIT_ERASE | W_NDEF_ACTION_BIT_LOCK | W_NDEF_ACTION_BIT_FORMAT_ALL);\n            if(nError != W_SUCCESS)\n            {\n               printf("Cannot write the message in the virtual tag\\n");\n               WBasicCloseHandle(hVirtualTag);\n            }\n            else\n            {\n               /* Start the tag simulation */\n               nError = WVirtualTagStartSync(hVirtualTag, VirtualTagEventHandler, null, W_TRUE);\n               if(nError != W_SUCCESS)\n               {\n                  printf("Cannot activate the virtual tag\\n");\n                  WBasicCloseHandle(hVirtualTag);\n               }\n               else\n               {\n                  printf("Present a reader to read the virtual tag or press Ctrl+C to stop the application\\n");\n               }\n            }\n         }\n      }\n   }\n\nreturn_function:\n\n   WBasicCloseHandle(hMessage);\n\n   /* Go pending on WaitForSingleObject (Card/Tag operation completed or Ctrl-C) */\n\n   return W_SUCCESS;\n}\n\n/**\n * CloseTest\n *\n **/\nvoid CloseTest( void )\n{\n   WBasicCloseHandle( g_testCtx.hRegistry );\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

代码部分定义为 shellapi.h,其中 ShellExecute 为:

\n\n
    #include <winapifamily.h>\n\n/*****************************************************************************\\\n*                                                                             *\n* shellapi.h -  SHELL.DLL functions, types, and definitions                   *\n*                                                                             *\n* Copyright (c) Microsoft Corporation. All rights reserved.                   *\n*                                                                             *\n\\*****************************************************************************/\n\n#ifndef _INC_SHELLAPI\n#define _INC_SHELLAPI\n\n#include <SpecStrings.h>\n\n//\n// Define API decoration for direct importing of DLL references.\n//\n#ifndef WINSHELLAPI\n#if !defined(_SHELL32_)\n#define WINSHELLAPI       DECLSPEC_IMPORT\n#else\n#define WINSHELLAPI\n#endif\n#endif // WINSHELLAPI\n\n#ifndef SHSTDAPI\n#if !defined(_SHELL32_)\n#define SHSTDAPI          EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE\n#define SHSTDAPI_(type)   EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE\n#else\n#define SHSTDAPI          STDAPI\n#define SHSTDAPI_(type)   STDAPI_(type)\n#endif\n#endif // SHSTDAPI\n\n#ifndef SHDOCAPI\n#if !defined(_SHDOCVW_)\n#define SHDOCAPI          EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE\n#define SHDOCAPI_(type)   EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE\n#else\n#define SHDOCAPI          STDAPI\n#define SHDOCAPI_(type)   STDAPI_(type)\n#endif\n#endif // SHDOCAPI\n\n\n#if !defined(_WIN64)\n#include <pshpack1.h>\n#endif\n\n#ifdef __cplusplus\nextern "C" {            /* Assume C declarations for C++ */\n#endif  /* __cplusplus */\n\n\n#pragma region Desktop Family\n#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)\n\n\n\nDECLARE_HANDLE(HDROP);\n\n_Success_(return != 0)\nSHSTDAPI_(UINT) DragQueryFileA(_In_ HDROP hDrop, _In_ UINT iFile, _Out_writes_opt_(cch) LPSTR lpszFile, _In_ UINT cch);\n_Success_(return != 0)\nSHSTDAPI_(UINT) DragQueryFileW(_In_ HDROP hDrop, _In_ UINT iFile, _Out_writes_opt_(cch) LPWSTR lpszFile, _In_ UINT cch);\n#ifdef UNICODE\n#define DragQueryFile  DragQueryFileW\n#else\n#define DragQueryFile  DragQueryFileA\n#endif // !UNICODE\nSHSTDAPI_(BOOL) DragQueryPoint(_In_ HDROP hDrop, _Out_ POINT *ppt);\nSHSTDAPI_(void) DragFinish(_In_ HDROP hDrop);\nSHSTDAPI_(void) DragAcceptFiles(_In_ HWND hWnd, _In_ BOOL fAccept);\n\nSHSTDAPI_(HINSTANCE) ShellExecuteA(_In_opt_ HWND hwnd, _In_opt_ LPCSTR lpOperation, _In_ LPCSTR lpFile, _In_opt_ LPCSTR lpParameters,\n    _In_opt_ LPCSTR lpDirectory, _In_ INT nShowCmd);\nSHSTDAPI_(HINSTANCE) ShellExecuteW(_In_opt_ HWND hwnd, _In_opt_ LPCWSTR lpOperation, _In_ LPCWSTR lpFile, _In_opt_ LPCWSTR lpParameters,\n    _In_opt_ LPCWSTR lpDirectory, _In_ INT nShowCmd);\n#ifdef UNICODE\n#define ShellExecute  ShellExecuteW\n#else\n#define ShellExecute  ShellExecuteA\n#endif // !UNICODE\n_Success_(return > 32) // SE_ERR_DLLNOTFOUND\nSHSTDAPI_(HINSTANCE) FindExecutableA(_In_ LPCSTR lpFile, _In_opt_ LPCSTR lpDirectory, _Out_writes_(MAX_PATH) LPSTR lpResult);\n_Success_(return > 32) // SE_ERR_DLLNOTFOUND\nSHSTDAPI_(HINSTANCE) FindExecutableW(_In_ LPCWSTR lpFile, _In_opt_ LPCWSTR lpDirectory, _Out_writes_(MAX_PATH) LPWSTR lpResult);\n#ifdef UNICODE\n#define FindExecutable  FindExecutableW\n#else\n#define FindExecutable  FindExecutableA\n
Run Code Online (Sandbox Code Playgroud)\n\n

这告诉我 Microsoft Visual Studio 2013 的错误是:

\n\n
Warning 1   warning LNK4075: ignoring \'/EDITANDCONTINUE\' due to \'/SAFESEH\' specification    File:win32_test_core.obj    Project:test_ndef_url\n\nError   2   error LNK2019: unresolved external symbol __imp__ShellExecuteW@24 referenced in function _ReadMessageOnAnyTagCompletedURL   File:win32_test_ndef_url.obj    Project:test_ndef_url\n\nError   3   error LNK1120: 1 unresolved externals   File:test_ndef_url.exe  Project:test_ndef_url\n
Run Code Online (Sandbox Code Playgroud)\n\n

拜托,我需要这方面的帮助。

\n

yzt*_*yzt 5

您缺少函数的实际主体(或函数主体的占位符)ShellExecute(好吧,ShellExecuteW但这是您现在不需要担心的细节。)标头中的内容是声明但您仍然需要定义。在本例中,这是在图书馆中。

执行这些操作:

  1. 谷歌搜索“MSDN ShellExecute”。MSDN 是 Microsoft 开发人员网络,也是获取 Windows API 文档的地方。
  2. 第一个链接是https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153%28v=vs.85%29.aspx(目前;微软的网站在保持链接稳定方面表现不佳)以后的参考。)
  3. 这是该函数的文档。向下滚动到页面底部。有一个表格列出了此功能的“要求”。其中之一是“库”,在本例中为“Shell32.lib”。
  4. 您需要链接到该库。在 Visual C++(您正在使用的)和标准 Windows 库(这是)中,最简单的方法是将以下行添加到您的源文件之一(可能在最顶部):#pragma comment (lib, "Shell32"). (请注意缺少分号。)

就是这样。对于较大的项目,有更好的(更具可扩展性、灵活和可移植性)方法,但对于这个小样本来说,你应该没问题。