스크립트의 호환성
AutoHotkey 1.0으로 작성된 스크립트는 대부분 AutoHotkey 1.1 위에서 아무 변경없이 실행됩니다. 그러나 몇 가지 기능은 두 버전 사이의 어떨 수 없는 차이점 때문에 제대로 작동하지 않을 수 있습니다. 가장 문제가 되는 차이점은 DllCall 같은 고급 기능에만 영향을 미치기 때문에, 대부분의 사용자는 신경쓸 필요가 없습니다.
AutoHotkey 1.1은 "AutoHotkey_L"이라고도 알려져 있는데, 반면에 AutoHotkey 1.0은 역으로 "AutoHotkey Basic"이라는 라벨이 붙었습니다. AutoHotkey_L의 예전 버전 중에는 1.0.* 버전 번호를 사용합니다. 그래서 명확하게 하기 위해, 이 문서는 오토핫키의 두 분기를 버전 번호가 아니라 이름으로 지칭합니다.
주의: 가장 흔한 문제는 유니코드 텍스트를 지원하도록 변경한 때문인데, 이는 그냥 ANSI 버전의 AutoHotkey_L를 사용하면 피할 수 있습니다.
기본
큰 충격:
중간 충격:
- Transform Unicode 명령어는 유니코드 버전에서 사용할 수 없습니다
- AutoHotkey.ini 대신에 AutoHotkey.ahk가 기동합니다
- SetFormat, Integer, H는 대소문자를 구분합니다
- A_LastError는 더 많은 명령어에 의하여 변경됩니다
- MsgBox가 쉼표를 더 일관성이 있게 처리합니다
- Gui +Owner는 추가 스타일을 오버라이드합니다
- GUI에 DPI 스케일링이 기본적으로 켜집니다
- SoundSet과 SoundGet은 비스타 이후에 더 잘 작동합니다
- ~틸드는 맞춤 수식 키의 작동에 영향을 미칩니다
x & y::
는 x를 뗄 때x::
와x up::
을 모두 촉발시킵니다
작은 충격:
- var가 type이면 기본적으로 시스템 로케일을 무시합니다
- GroupActivate는 ErrorLevel을 설정하고 GroupAdd의 Label은 다르게 작동합니다
- Run과 RunWait는 Target을 다르게 이해합니다
- Control-Z는 파일끝으로 번역되지 않습니다
- 호환성 모드가 혼란을 야기할 수 있습니다
- A_IsCompiled는 언제나 읽기 전용입니다
- 선두와 후미의 `t 연속열은 더 이상 폐기되지 않습니다
고급
기본
구문 에러
AutoHotkey Basic에서 용인되었던 어떤 구문 에러는 이제 더 이상 AutoHotkey_L에서 용납하지 않습니다. 그런 에러는 대부분 식별하기만 하면 쉽게 교정할 수 있습니다. 다음 에러는 스크립트를 AutoHotkey_L에서 기동하자 마자 즉시 탐지됩니다. 교정해야 스크립트를 실행할 수 있습니다:
- 명령어와 매개변수 사이에 스페이스나 탭 또는 쉼표가 필요합니다. 예를 들어,
MsgBox< foo
그리고If!foo
는 용납되지 않습니다. Hotkey, IfSomething
에서 Something이 무효이며, 허용되지 않습니다.
다른 어떤 구문 에러는 스크립트가 실행 중일 때 탐지됩니다. 에러 메시지를 먼저 보여준 다음에 현재 쓰레드를 종료합니다:
- 흔한 에러: 인식할 수 없는 또는 형식이 나쁜 Gui, Gui Show 또는 GuiControl 옵션.
- 그룹 이름이 비어 있는 GroupAdd. 이전에는 쓰레드가 조용히 종료했습니다.
- Gui 옵션 +LastFoundExist는 다른 옵션과 조합하면 안 됩니다. 왜냐하면 그렇게 하면 +LastFound와 똑같이 행동하기 때문입니다.
어떤 구문 에러는 현재 탐지되지 않지만, AutoHotkey_L에 문제를 일으킵니다:
(
과의 자동-결합(Auto-concat)은 더 선별적이 되었습니다. 그래서12(34)
와 같이 무효한 표현식은 더 이상 작동하지 않습니다.
FileRead
FileRead는 보통의 경우 코드 페이지 사이에 텍스트를 변환합니다. 그러므로 부패한 이진 데이터를 출력할 가능성이 있습니다. 이를 피하려면 *c
옵션을 추가하거나 대신에 FileOpen을 사용하십시오.
변수 이름과 함수 이름
[
, ]
그리고 ?
는 표현식에 사용이 예약되어 있습니다. 그래서 더 이상 변수 이름으로 유효하지 않습니다. 결론적으로, ?
는 (삼진 연산에 사용됨) 더 이상 양쪽에 스페이스가 없어도 됩니다. 객체 구문을 참조하십시오.
에러는 자동으로 탐지될 수도 있고 아닐 수도 있습니다:
- 스크립트가 이런 문자들을 표현식에서 변수 이름에 사용하면, 일반적으로 그 스크립트는 에러 메시지를 보여주지 않고 실행되지만, 문자를 변수의 이름의 일부가 아니라 연산자로 이해하기 때문에 잘못된 행위를 하게 됩니다.
- 이런 문자가 이중 참조(double-deref)에 사용되면 (
Array%n%
과 같이 n에 위의 문자중 하나가 담겨 있으면), 스크립트가 실행되다가, 이중-참조가 평가될 때 에러 메시지가 나타납니다. - 이 문자들이 다른 문맥에 사용되면, 예를 들어 할당의 왼편이나 명령어의 입/출력 변수의 이름 또는 %percent% 사인에 사용되면, 에러 메시지가 나타나고 스크립트는 기동하지 못합니다.
Transform
Transform 하위-명령어 중 일부는 유니코드 버전의 AutoHotkey_L에서 변경되거나 사용할 수 없습니다:
- Transform, Unicode는 사용 불가능합니다. 유니코드 텍스트를 클립보드에 할당하려면, 보통처럼 할당하십시오. 다음 참조: StrPut/StrGet.
- Transform, HTML는 추가 특징을 지원합니다.
기본 스크립트
AutoHotkey_L가 스크립트를 지정하지 않고 기동하면, .ini 파일 대신에 .ahk 파일이 적재됩니다. 이 파일의 이름은 현재 실행파일의 파일이름에 따라 다릅니다. 더 자세한 것은 스크립트에 명령어 줄 매개변수를 건네기를 참조하십시오.
SetFormat, Integer[Fast], H
대문자 H가 사용되면, 십육진수 A-F도 대문자가 됩니다. AutoHotkey Basic은 언제나 소문자를 사용합니다. SetFormat을 참조하십시오.
A_LastError
다음 명령어는 이제 A_LastError를 설정해 디버깅을 돕습니다: FileAppend, FileRead, FileReadLine, FileDelete, FileCopy, FileMove, FileGetAttrib/Time/Size/Version, FileSetAttrib/Time, FileCreateDir, RegRead, RegWrite, RegDelete. 이 명령어를 사용하면 A_LastError의 이전 값이 덮어 씌여집니다.
MsgBox
MsgBox의 똑똑한 쉼표 처리가 다른 모든 명령어와 일관성이 있게 그리고 유연하게 개선되었습니댜. 대부분의 경우, MsgBox는 의도한 대로 잘 작동합니다. 어떤 경우는 스크립트가 예전의 기묘한 행위에 의존하는 경우 행위에 변화가 보일 수 있습니다. 예를 들면:
; 다음은 이제 표현식 (Options) 다음에 텍스트 (Title)로 번역됩니다. ; 여러 부-표현식을 가진 단일 표현식 (Text) 으로 번역되지 않습니다 : MsgBox % x, y ; 반괄호를 추가하면 예전의 번역을 강제할 수 있습니다: MsgBox % (x, y) ; 다음은 이제 텍스트 "0, Title" 대신에 빈 대화상자를 보여줍니다: MsgBox 0, Title ; 다음은 AutoHotkey_L 그리고 AutoHotkey Basic에서 모두 예상대로 행위합니다: MsgBox 0, Title, % "" ; 빈 대화상자를 보여줍니다. MsgBox 0`, Title ; 텍스트 "0, Title"을 보여줍니다. ; 다음은 이제 텍스트 ", Title" 대신에 빈 대화상자를 보여줍니다: MsgBox,, Title
Gui +Owner
+Owner 옵션을 Gui에 적용하면 WS_CHILD 스타일이 제거되고 WS_POPUP 스타일이 설정됩니다. 이 때문에 스타일을 설정한 다음에 +Owner
를 사용하여 Gui의 부모 창을 설정한 스크립트는 깨질 수 있습니다.
DPI 스케일링
DPI 스케일링은 기본적으로 스크립트 GUI에 켜집니다. 이 때문에 DPI 설정이 96 (100%)이 아니면 스크립트에 영향을 미칩니다. 이를 끄려면, Gui -DPIScale
를 사용하십시오.
Windows Vista 이후의 Sound 명령어
SoundSet, SoundGet, SoundSetWaveVolume 그리고 SoundGetWaveVolume Windows Vista 이후에 개선되었습니다. 전형적인 행위의 변화로:
- 스크립트가 그냥 스크립트 자체 대신에 전체 시스템에 영향을 미칩니다 (보통 이것이 의도하는 바입니다).
- 장치는 번호가 다르게 매겨집니다 - 각 출력이나 입력은 별도의 장치로 간주 됩니다.
~틸드와 맞춤 조합 핫키
v1.1.14 부터, 틸드 접두 심볼은 맞춤 조합에 수식 키로 사용될 때 키가 작동하는 방식에 영향을 미칩니다.
맞춤 조합키와 Down/Up 핫키
틸드 접두 심볼이 사용되는 경우를 제외하고, 키-다운과 키-업 핫키가 맞춤 수식 키로 정의되어 있다면, 키를 뗄 때 둘 모두 촉발 됩니다. 예를 들어, x & y::
이면 x를 뗄 때 x::
와 x up::
가 모두 촉발 됩니다. 예전에는 x::
가 촉발 되지 않았습니다.
If var is type
If var is type는 시스템 로케일을 무시합니다. 단, StringCaseSense, Locale이 사용되었다면 예외입니다.
창 그룹
GroupActivate는 활성화 할 창을 발견하지 못하면 ErrorLevel에 1을 설정합니다, 그렇지 않으면 0을 설정합니다. 이전에는 ErrorLevel을 변경하지 않고 그대로 두었습니다.
GroupAdd의 Label 매개변수는 창 그룹에 전체적으로 적용됩니다. 그룹 안의 특정 창 규격 하나에만 적용되지 않습니다. 이 변경에 관한 토론이 포럼에 있습니다. 그렇지만, 이 매개변수를 사용하는 것은 추천 하지 않습니다; 대신에 GroupActivate를 호출한 후에 ErrorLevel을 점검하십시오.
Run / RunWait
AutoHotkey_L은 Run과 RunWait 명령어가 목표(Target) 매개변수를 번역하는 방식이 약간 개선되었습니다. 이 때문에 아주 희귀한 경우이기는 하지만, 예전에는 작동하지 않던 것들이 작동하게 되어 AutoHotkey Basic에서 이미 잘 작동하는 스크립트에 영향을 미칠 수 있습니다. 새로운 행위는 다음과 같습니다:
- Target이 따옴표로 시작하면, 다음 따옴표까지 모든 것을 조치로 취급합니다. 전형적으로 실행 파일로 간주합니다.
- 그렇지 않으면 첫 번째 부문자열이 스페이스로 끝나거나 기존의 파일이거나 또는 .exe, .bat, .com, .cmd 또는 .hta로 끝나면 조치로 간주합니다. 이 때문에 .ahk, .vbs 또는 .lnk 같은 파일 유형은 매개변수를 받을 수 있습니다. 그러면서도 이전의 버전과 같이 절대 경로가 없어도 여전히 wordpad.exe와 같이 "알려진" 실행 파일을 기동할 수 있습니다.
Control-Z
Loop Read 그리고 FileReadLine는 더 이상 문자 Control-Z (0x1A)를 파일 끝 표식으로 이해하지 않습니다. Control-Z는 모두, 파일 맨 끝에 오더라도, 그대로 적재됩니다. FileRead는 이미 이 문자를 무시합니다. 그래서 이 문제에 영향을 받지 않습니다.
호환 모드
스크립트를 실행하는 데 사용된 EXE 파일의 특성에 호환 모드가 Windows 95, 98/ME 또는 NT4로 설정되었다면,
그 스크립트는 올바르게 작동하지 못합니다. 왜냐하면 호환 모드 때문에 특정 버전의 Windows가 어플리케이션에 보고되지만, AutoHotkey_L은 이런 버전을 지원하지 않기 때문입니다. 예를 들어, 호환 모드를 Windows 95 or 98/ME에 설정하면 MsgBox %A_OSVersion%
는 WIN_NT4
라고 보고합니다.
A_IsCompiled
A_IsCompiled는 스크립트가 컴파일되지 않았다면 빈 문자열로 정의됩니다. 이전에는 정의되지 않은 채 그대로 두었습니다. 그 때문에 스크립트가 컴파일되지 않았음에도 A_IsCompiled := 1
와 같은 할당이 유효했었습니다. 이제는 모든 경우에 읽기 전용 내장 변수로 취급됩니다.
공백 문자 피신
`t
와 `
같은 피신 공백문자는 더 이상 각 인자의 앞 뒤에서 제거되지 않습니다. 예를 들어, StringReplace s, s, `t
는 이제 유효하며 모든 탭 문자를 s로부터 제거합니다.
Unicode vs ANSI
텍스트 값은 종종 문자열(string)이라고 부릅니다. 각 텍스트의 값이 문자열의 연속 또는 줄지어(string) 저장되어 있기 때문입니다. 각 문자의 숫치 문자 코드와 크기 (바이트 단위)는 어느 버전의 AutoHotkey를 사용하고 있는가에 달려 있습니다: Unicode 또는 ANSI. 이런 세부 사항은 다음과 같은 일을 하려는 스크립트에 전형적으로 중요합니다:
- DllCall을 통하여 문자열을 외부 함수에 전달할 때.
- PostMessage/SendMessage를 통하여 문자열을 전달 할 때.
- NumPut/NumGet를 통하여 문자열을 조작할 때.
- VarSetCapacity를 사용하여 특정 개수의 문자를 변수에 담을 수 있는지 확인할 때.
한 가지 형식만 염두에 두고 설계된 스크립트는 종종 엉뚱한 버전의 AutoHotkey로 실행할 때 문제에 봉착합니다. 예를 들면, 어떤 스크립트가 AutoHotkey Basic용으로 작성되었다면 ANSI 버전의 AutoHotkey_L에서는 잘 작동하지만 유니코드 버전에서는 실패합니다. 어느 버전을 사용하고 있는지 잘 모르겠다면, 다음 스크립트를 실행해 보십시오:
MsgBox % A_IsUnicode ? "Unicode" : "ANSI"
ANSI: 각 문자는 한 바이트 (8 비트)입니다. 127을 넘는 문자 코드는 시스템의 언어 설정에 따라 달라집니다.
Unicode: 각 문자는 두 바이트 (16 비트)입니다. 문자 코드는 UTF-16 형식으로 정의됩니다.
의미구조 주의: 기술적으로, 어떤 유니코드 문자는 두 개의 16-비트 코드 단위로 표현됩니다. 합쳐서 "대리 쌍(surrogate pair)"라고 부릅니다. 비슷하게, 어떤 ANSI 코드 페이지는 (보통 DBCS(Double Byte Character Sets)라고 부름) 두 바이트 문자를 담고 있습니다. 그렇지만, 실용적인 이유로, 이것들을 거의 언제나 두 개의 개별 단위로 취급합니다 (단순하게 하기 위해 그냥 "문자(characters)"라고 부릅니다).
VarSetCapacity
VarSetCapacity는 변수의 가용 능력을 바이트 단위로 설정합니다. 변수의 가용능력을 문자의 개수에 기반하여 설정하려면, 문자의 크기를 반드시 고려해야 합니다. 예를 들어:
VarSetCapacity(ansi_var, capacity_in_chars) VarSetCapacity(unicode_var, capacity_in_chars * 2) VarSetCapacity(native_var, capacity_in_chars * (A_IsUnicode ? 2 : 1)) VarSetCapacity(native_var, t_size(capacity_in_chars)) ; 아래 참조
다음은 VarSetCapacity의 두 가지 주요 사용법입니다:
- 예측한 개수의 문자를 보유하도록 변수를 확장합니다. 그리하여 점진적 결합을 통해 문자열을 구성할 때 수행성능을 개선할 수 있습니다. 예를 들어,
VarSetCapacity(var, 1000)
는 1000 바이트를 허용합니다. 이것은 유니코드 버전의 AutoHotkey_L에서는 500 문자에 불과합니다. 이렇게 하면 수행성능에 영향을 미칠 수 있지만, 스크립트는 여전히 올바르게 작동합니다. - 변수 크기를 조정해 이진 구조체를 담습니다. 구조체에 직접적으로 텍스트가 담겨 있다면, 그 텍스트의 형식을 반드시 고려해야 합니다. 형식은 구조체에 따라 다릅니다 - 어떤 경우는 유니코드 버전의 AutoHotkey_L에서도 ANSI 텍스트가 사용됩니다. 변수가 너무 작으면, 스크립트는 충돌하거나 아니면 예상하지 못한 행위를 할 수 있습니다 (구조체를 어떻게 사용하는가에 따라).
DllCall
"Str" 유형이 사용될 때, 현재 빌드의 고유 유형의 문자열이라는 뜻입니다. 어떤 함수는 특정한 형태의 문자열을 요구하거나 돌려주기 때문에, 다음의 문자열 유형을 사용할 수 있습니다:
문자 크기 | C / Win32 Types | 인코딩 | |
---|---|---|---|
WStr | 16-비트 | wchar_t*, WCHAR*, LPWSTR, LPCWSTR | UTF-16 |
AStr | 8-비트 | char*, CHAR*, LPSTR, LPCSTR | ANSI (시스템 기본 ANSI 코드 페이지) |
Str | -- | TCHAR*, LPTSTR, LPCTSTR | 유니코드 빌드의 WStr 그리고 ANSI 빌드의 AStr과 동등. |
"Str" 또는 현재 빌드에 대하여 그와 동등한 유형이 매개변수로 사용되면, 그 문자열 또는 변수의 주소가 함수에 건네집니다. 그렇지 않으면 대신에 문자열의 임시 사본이 원하는 포맷으로 생성되고 건네집니다. 일반적으로, "AStr" 그리고 "WStr"은 함수가 그 매개변수에 변수를 쓸 때 사용하면 안 됩니다.
주의: "AStr" 그리고 "WStr"은 매개변수에 대하여 그리고 그 함수의 반환 값에 대하여 똑 같이 유효합니다.
일반적으로, 스크립트가 문자열을 매개변수로 받는 함수를 DllCall를 통하여 호출하면, 다음 접근법 중 하나를 취해야 합니다:
-
함수를 Unicode (W) 버전과 ANSI (A) 버전으로 모두 사용할 수 있으면, 현재 빌드에 대하여 적절한 버전을 호출합니다. 다음 예제에서, "DeleteFile"은 내부적으로 "DeleteFileA" 또는 "DeleteFileW"이라고 부릅니다. "DeleteFile" 자체는 실제로 존재하지 않으므로, DllCall은 자동으로 현재 빌드에 대하여 적절하게 "A" 또는 "W"를 시도합니다:
DllCall("DeleteFile", "Ptr", &filename) DllCall("DeleteFile", "Str", filename)
다음 예제에서,
&filename
은 문자열의 주소를 정확하게 있는 그대로 건넵니다. 그래서 함수는 문자열을 "Str" 유형과 같은 형식이라고 예상해야 합니다. AutoHotkey Basic에서 "UInt"를 "Ptr" 대신에 사용할 수 있습니다. 그러나 결과 코드는 64-비트와 호환되지 않습니다.주의: 함수를 정확하게 지정된 대로 발견할 수 없으면, AutoHotkey_L은 어느 DLL이 지정되어 있는가에 상관 없이 "A" 또는 "W" 접두사를 덧붙입니다. 그렇지만, AutoHotkey Basic은 User32.dll, Kernel32.dll, ComCtl32.dll, 또는 Gdi32.dll에 있는 함수에 대해서만 "A" 접두사를 붙입니다.
- 함수가 오직 특정 유형이 문자열만 입력으로 받는다면, 그 스크립트는 적절한 문자열 유형을 사용할 수 있습니다:
DllCall("DeleteFileA", "AStr", filename) DllCall("DeleteFileW", "WStr", filename)
- 함수가 (비-고유 형식으로) 문자열을 수정해야 한다면, 스크립트는 버퍼를 위에 기술한 대로 할당하고 그의 주소를 함수에 건네야 합니다. 매개변수가 입력을 받는다면, 스크립트는 또한 입력 문자열도 적절한 형식으로 변환해야 합니다; StrPut을 사용하면 변환할 수 있습니다.
NumPut / NumGet
NumPut이나 NumGet이 문자열에 사용될 때, 주어진 유형의 문자열에 대하여 오프셋과 유형이 정확해야 합니다. 다음을 지침으로 삼으십시오:
; 8-bit/ANSI strings: size_of_char=1 type_of_char="Char" ; 16-bit/UTF-16 strings: size_of_char=2 type_of_char="UShort" nth_char := NumGet(var, (n-1)*size_of_char, type_of_char) NumPut(nth_char, var, (n-1)*size_of_char, type_of_char)
var
에 음수 형태의 문자열이 들어 있다면, 적절한 값은 A_IsUnicode
에 기반하여 결정할 수 있습니다:
nth_char := NumGet(var, t_size(n-1), t_char()) NumPut(nth_char, var, t_size(n-1), t_char()) ; 편리성과 명료성을 위해 함수를 정의합니다: t_char() { return A_IsUnicode ? "UShort" : "Char" } t_size(char_count=1) { return A_IsUnicode ? char_count*2 : char_count }
포인터 크기
포인터 크기는 32-비트 빌드에 대하여 4 바이트 (AutoHotkey Basic 포함) 64-비트 빌드에 대하여 8 바이트입니다. 구조체나 DllCall을 사용하는 스크립트는 두 플랫폼에서 모두 올바르게 작동하려면 이 사실을 고려할 필요가 있습니다. 영향을 받는 구체적인 영역은 다음과 같습니다:
크기와 오프셋 계산은 A_PtrSize을 사용하십시오. DllCall, NumPut 그리고 NumGet에는 적절하게 Ptr 유형을 사용하십시오.
필드의 오프셋은 보통 그 앞에 있는 모든 필드의 전체 크기임을 기억하십시오. 또 핸들도 (HWND와 HBITMAP 같은 유형을 포함하여) 본질적으로 포인터-유형임을 명심하십시오.
/* typedef struct _PROCESS_INFORMATION { HANDLE hProcess; // Ptr HANDLE hThread; DWORD dwProcessId; // UInt (4 bytes) DWORD dwThreadId; } PROCESS_INFORMATION, *LPPROCESS_INFORMATION; */ VarSetCapacity(pi, A_PtrSize*2 + 8) ; Ptr + Ptr + UInt + UInt DllCall("CreateProcess", <omitted for brevity>, "Ptr", &pi, <omitted>) hProcess := NumGet(pi, 0) ; Defaults to "Ptr". hThread := NumGet(pi, A_PtrSize) ; dwProcessId := NumGet(pi, A_PtrSize*2, "UInt") dwProcessId := NumGet(pi, A_PtrSize*2 + 4, "UInt")