Windows API Import시 32bit, 64bit Excel 모두 사용하도록 PtrSafe 지정

Windows API PtrSafe 선언에 대해 알아본다. 엑셀 VBA로 코딩하다 보면 Windows API를 Import하여 사용하다가 간혹 만나는 PtrSafe 관련 오류의 원인과 해결방법을 확인할 수 있다.

1. Windows API PtrSafe 오류 발생 예시 코드

Windows API Sleep, OutputDebugString을 import하여 선언하는 코드이다.

Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)

(참고: 위 코드는 Logging 패턴: OutputDebugString , DebugView 활용 – 생산성 Skill (prodskill.com) 에서 소개한 코드이다.)

2. Windows API PtrSafe 오류 메시지

VBA 코드를 편집하거나 컴파일할 때 다음과 같은 오류가 발생한다.

VBA 컴파일 오류: Declare 문 PtrSafe 특성 표시 필요
VBA 컴파일 오류: Declare 문 PtrSafe 특성 표시 필요

——————————————-
Microsoft Visual Basic for Applications
——————————————-

컴파일 오류입니다:

이 프로젝트의 코드를 업데이트해야 64비트 시스템에서 사용할 수 있습니다. Declare 문을 검토하고 업데이트한 다음 PtrSafe 특성으로 표시하십시오.

3. Windows API PtrSafe 오류 발생 원인

MS-Office 2010부터 64bit를 지원했고, 이 이후의 64bit 엑셀에서 Windows API를 Imprt할 때 PtrSafe 키워드를 지정해야 하기 때문에 발생한다.

참조: The code in this project must be updated for use on 64-bit systems – Office | Microsoft Docs

Compile error when you edit a VBA macro in the 64-bit version of an Office 2010 program
Compile error when you edit a VBA macro in the 64-bit version of an Office 2010 program

위 URL의 자료 내용 일부를 발췌하여 아래 붙여둔다.


Symptoms

Consider the following scenario:

  • You write a Microsoft Visual Basic for Applications (VBA) macro code that uses Declare statements.
  • Your VBA macro code uses compilation constants. For example, your macro code uses one the following compilation constants:
    • #If VBA7
    • #If Win64
  • You use an #Else block in a conditional block. In the #Else block, you use syntax for a Declare statement designed to run in Microsoft Visual Basic for Applications 6.0.
  • You edit the code in a 64-bit version of a Microsoft Office 2010 program.
  • You try to change the Declare statement in the #Else block.

In this scenario, you receive the following error message:

Microsoft Visual Basic for Applications

Compile error:

The code in this project must be updated for use on 64-bit
systems. Please review and update Declare statements and then
mark them with the PtrSafe attribute.

4. Windows API PtrSafe 오류 해결 방법

MS-Office 2010의 VBA 버전이 7.0이고, 그 이전은 6.x 이다. VBA 7.0 부터 PtrSafe 키워드가 필요하기 때문에, VBA 버전이 7.0 이후인지 아닌지에 따라 Windows API import 코드를 나누어서 선언하면 된다.

참조: PtrSafe keyword (VBA) | Microsoft Docs

PtrSafe keyword
PtrSafe keyword

위 URL의 자료 내용 일부를 발췌하여 아래 붙여둔다.


PtrSafe keyword

  • Article
  • 09/14/2021
  • 2 minutes to read
  • 5 contributors

The PtrSafe keyword is used in this context: Declare statement.

Declare statements with the PtrSafe keyword is the recommended syntax. Declare statements that include PtrSafe work correctly in the VBA7 development environment on both 32-bit and 64-bit platforms only after all data types in the Declare statement (parameters and return values) that need to store 64-bit quantities are updated to use LongLong for 64-bit integrals or LongPtr for pointers and handles.

To ensure backwards compatibility with VBA version 6 and earlier, use the following construct:

#If VBA7 Then 
Declare PtrSafe Sub... 
#Else 
Declare Sub... 
#EndIf

When running in 64-bit versions of Office, Declare statements must include the PtrSafe keyword. The PtrSafe keyword asserts that a Declare statement is safe to run in 64-bit development environments.

Adding the PtrSafe keyword to a Declare statement only signifies that the Declare statement explicitly targets 64-bits. All data types within the statement that need to store 64-bits (including return values and parameters) must still be modified to hold 64-bit quantities by using either LongLong for 64-bit integrals or LongPtr for pointers and handles.


“VBA7” 상수 또는 “Win64” 상수가 정의되어 있는지를 판단하면 되고, 이때 컴파일러 지시자(Compiler Directive) #If 구문을 사용한다.

코드는 다음과 같이 구성한다.

'방법1
#If VBA7 Then
    '64bit Windows API import
#Else
    '32bit Windows API import
#End If

'방법2
#If Win64 Then
    '64bit Windows API import
#Else
    '32bit Windows API import
#End If

'방법1, 방법2는 동일한 효과가 있으므로 한 방법을 선택하면 됨

5. Windows API PtrSafe 오류 해결 예시 코드

5.1. 32bit, 64bit 엑셀에서 혼용하여 사용되는 경우

#If VBA7 Then 'For 64 Bit Systems
    Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
    Private Declare PtrSafe Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
#Else 'For 32 Bit Systems
    Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
#End If

5.2. 64bit 엑셀에서만 사용되는 경우

64bit 엑셀에서만 사용된다는 보장이 있다면 PtrSafe 키워드를 지정한 하나의 구문만 사용한다.

Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
Private Declare PtrSafe Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

ko_KR한국어