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

Open NFC - Error LNK2019: unresolved external symbol __imp__ShellExecuteW@24

本文关键字:外部 符号 imp ShellExecuteW@24 NFC 错误 LNK2019 打开      更新时间:2023-10-16

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

我正试图为一个项目编译一个开放NFC的例子。示例为test_ndef_url。我不知道这个问题是由于编码错误还是由于windows库。

Test_ndef_url代码为:

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

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

    #include <winapifamily.h>
/*****************************************************************************
*                                                                             *
* shellapi.h -  SHELL.DLL functions, types, and definitions                   *
*                                                                             *
* Copyright (c) Microsoft Corporation. All rights reserved.                   *
*                                                                             *
*****************************************************************************/
#ifndef _INC_SHELLAPI
#define _INC_SHELLAPI
#include <SpecStrings.h>
//
// Define API decoration for direct importing of DLL references.
//
#ifndef WINSHELLAPI
#if !defined(_SHELL32_)
#define WINSHELLAPI       DECLSPEC_IMPORT
#else
#define WINSHELLAPI
#endif
#endif // WINSHELLAPI
#ifndef SHSTDAPI
#if !defined(_SHELL32_)
#define SHSTDAPI          EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
#define SHSTDAPI_(type)   EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE
#else
#define SHSTDAPI          STDAPI
#define SHSTDAPI_(type)   STDAPI_(type)
#endif
#endif // SHSTDAPI
#ifndef SHDOCAPI
#if !defined(_SHDOCVW_)
#define SHDOCAPI          EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
#define SHDOCAPI_(type)   EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE
#else
#define SHDOCAPI          STDAPI
#define SHDOCAPI_(type)   STDAPI_(type)
#endif
#endif // SHDOCAPI

#if !defined(_WIN64)
#include <pshpack1.h>
#endif
#ifdef __cplusplus
extern "C" {            /* Assume C declarations for C++ */
#endif  /* __cplusplus */

#pragma region Desktop Family
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)

DECLARE_HANDLE(HDROP);
_Success_(return != 0)
SHSTDAPI_(UINT) DragQueryFileA(_In_ HDROP hDrop, _In_ UINT iFile, _Out_writes_opt_(cch) LPSTR lpszFile, _In_ UINT cch);
_Success_(return != 0)
SHSTDAPI_(UINT) DragQueryFileW(_In_ HDROP hDrop, _In_ UINT iFile, _Out_writes_opt_(cch) LPWSTR lpszFile, _In_ UINT cch);
#ifdef UNICODE
#define DragQueryFile  DragQueryFileW
#else
#define DragQueryFile  DragQueryFileA
#endif // !UNICODE
SHSTDAPI_(BOOL) DragQueryPoint(_In_ HDROP hDrop, _Out_ POINT *ppt);
SHSTDAPI_(void) DragFinish(_In_ HDROP hDrop);
SHSTDAPI_(void) DragAcceptFiles(_In_ HWND hWnd, _In_ BOOL fAccept);
SHSTDAPI_(HINSTANCE) ShellExecuteA(_In_opt_ HWND hwnd, _In_opt_ LPCSTR lpOperation, _In_ LPCSTR lpFile, _In_opt_ LPCSTR lpParameters,
    _In_opt_ LPCSTR lpDirectory, _In_ INT nShowCmd);
SHSTDAPI_(HINSTANCE) ShellExecuteW(_In_opt_ HWND hwnd, _In_opt_ LPCWSTR lpOperation, _In_ LPCWSTR lpFile, _In_opt_ LPCWSTR lpParameters,
    _In_opt_ LPCWSTR lpDirectory, _In_ INT nShowCmd);
#ifdef UNICODE
#define ShellExecute  ShellExecuteW
#else
#define ShellExecute  ShellExecuteA
#endif // !UNICODE
_Success_(return > 32) // SE_ERR_DLLNOTFOUND
SHSTDAPI_(HINSTANCE) FindExecutableA(_In_ LPCSTR lpFile, _In_opt_ LPCSTR lpDirectory, _Out_writes_(MAX_PATH) LPSTR lpResult);
_Success_(return > 32) // SE_ERR_DLLNOTFOUND
SHSTDAPI_(HINSTANCE) FindExecutableW(_In_ LPCWSTR lpFile, _In_opt_ LPCWSTR lpDirectory, _Out_writes_(MAX_PATH) LPWSTR lpResult);
#ifdef UNICODE
#define FindExecutable  FindExecutableW
#else
#define FindExecutable  FindExecutableA

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

Warning 1   warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification    File:win32_test_core.obj    Project:test_ndef_url
Error   2   error LNK2019: unresolved external symbol __imp__ShellExecuteW@24 referenced in function _ReadMessageOnAnyTagCompletedURL   File:win32_test_ndef_url.obj    Project:test_ndef_url
Error   3   error LNK1120: 1 unresolved externals   File:test_ndef_url.exe  Project:test_ndef_url

我需要帮助。

您丢失了ShellExecute函数(好的,ShellExecuteW,但这是您现在不需要担心的细节)的实际主体(或函数主体的占位符)。头文件中的内容是声明,但是您仍然需要定义。在本例中,它位于中。

做这些:

  1. 谷歌"MSDN ShellExecute"。MSDN是微软开发者网络,也是获取Windows API文档的地方。
  2. 第一个链接是https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153%28v=vs.85%29.aspx(目前;微软网站在保持链接稳定以供将来参考方面做得很糟糕。
  3. 这是函数的文档。向下滚动到页面底部。有一个表格列出了这个功能的"需求"。其中之一是"库",即"Shell32"。
  4. 你需要链接到这个库。最简单的方法,在Visual c++(你正在使用)和一个标准的Windows库(这是)是添加以下一行到你的源文件之一(可能在最顶部):#pragma comment (lib, "Shell32")。(注意没有分号)

就是这样。对于更大的项目,有更好的(更可伸缩、更灵活和可移植的)方法,但是对于这个小示例,您应该可以接受。