자유롭게 질의 및 응답을 할 수 있는 게시판입니다. 개발자 여러분의 답변이 큰 도움이 됩니다.
- 제품설치/등록 오류 문의: 설치/등록 Q&A 이용 (제품 구매 고객 한정)
Delphi WINEXEC 관련해서 문의드립니다
2015.05.16 04:32
자꾸 질문드려 죄송 합니다.
( ※ XE7로 Migration 하다보니 기왕의 DELPHI 에 있던 기능들이 변경되어 안되는 것들이 자꾸나오고 또 그런건 어디 '
자세한 설명도 찾기 힘들고요. 또 완전히 없어져서 안되는 것이 아니라 내용이 생각지 못하는 방향으로 바뀌는 것들이라
기존에 생각 못했던 것들이라 그렇네요)
문제의 내용 설명으로 iexplore를 실행시키는 것을 예로 들어 설명 하겠습니다
① WinExec(pansichar(C:\Program Files\Internet Explorer\iexplore.exe http://tech.devgear.co,kr/'),sw_show) 하면 잘 됩니다
②그런데 들어가는 command 나 argumenet 를 변수를 사용하는 경우에는 안됩니다
즉 aa := 'C:\Program Files\Internet Explorer\iexplore.exe http://tech.devgear.co,kr/' 로 하여 WinExec(pansichar(aa),sw_show) 로 한다거나
cmd_line := 'C:\Program Files\Internet Explorer\iexplore.exe', param_data := 'http://tech.devgear.co,kr' 로 하고
WinExec(Pansichar(cmd_line + ' ' + param_data).sw_show) 로 하거나
WinExec(Pansichar('C:\Program Files\Internet Explorer\iexplore.exe' + ' ' + param_data),sw_show)로 하면 안됩니다.
다른 프로그램을 실행 시키면서 parameter를 넘길때도 마찬 가지 입니다/
WinExce(PAnsiChar('TESTPRG' + ' ' + '이순신' + ' ' + '영웅'),0) 하면 잘되지만 param_1 := '이순신', param_2 := '영웅 '으로하여
WinExec(PAnsiChar('TESTPRG' + ' ' + param_1 + ' ' + param_2),0)' 하면 안됩니다.
(실제 업무에서는 parameter 가 변수로 바뀌므로 후자로 사용 될 수 밖에 없습니다. 예 LoginId, 성명 같은 거지요)
어디서 잘못 되었고 어떻게 하면 될지 해결 방안을 가르켜 주시면 고맙겠습니다.
(old version의 DELPHI 4, 5, 6 에서는 후자의 방법으로 많이 잘 사용 해 온 것입니다. 이걸 전환 해야 하니 어떻게 할지 방안이 없네요)
WINEXEC에서 XE6등에서는 PAnsiCharacter로 해야 하는 것(Unicode관련)은 알고 있지만 제대로 알지 못한 건지요.
그런데 위의 예와 같이 constatnt 값을쓰나 동일한 것을 변수에 넣고 쓰나 같은게 일반적인 상식이라 이와 관련된 것을 어디서 찾아 보아야
할지도 사실 알 수 없습니다. (하도 실력이 모자라서)
Ansichar 가 AnsiString 이나 String 이런 것과는 다른 것이라지만 값을 그냥 썼을때와 변수에 넣고 썼을때 왜 차이가 나는 건지 특히
Space 에 대해서 차이가 나는 건지 알수 없네요 (앞에붙은 Space나 뒤꼬리에 붙은 Space 라면 모르겠는데 문자열의 중간에 있는
Space인데 ...)
첨부 : 이를 Test 한 프로그램입니다 (DELPHI XE6 사용)
Source 와 실행 File 입니다 (ZIP으로 묶어 놓았으나 Zip을 풀면 됩니다)
댓글 3
-
Humphery
2015.05.18 18:51
-
jcitec
2015.05.18 23:47
예 고맙습니다.
PansiChar 로 쓰는 것은 AnsiSting 일때는 됩니다. (나도 이것저것 추측해 보고 추측을
테스트 해보고 알아 낸 거였습니다. 즉 Ansistring 값은 PAnsiString 으로 CAST 했을때
정상적으로 STRING 값은 안됩니다. String 은 Unicode String 으로 간주한다는 설명이
delphi 도움말에 있는데 이걸보고 혹시 AnsiString 과 PAnsiChar, WideString PWideChar 로
끼리끼리 만 노는게 아닌가 하는 생각이 들었고 Unicode String (String) 을 WideString 으로
분류해서 끼리끼리 노는데서 (PAnsiChar 에서) 안끼워 주는 거 아닐까 하는 추측을 했고요
그래서 String 값을 ANSISTRING으로 정의 한 변수에다 넣고 PANSICHAR을 했더니 먹혀
들더군요. 완전히 가정만 가지고 추측 했던 것이 먹혀 들었던 것인데 미치 눈먼고기
낚았다는 기분이더군요. (그래서 컨버전에서는 일단 임시 방편으로 그렇게 하고 있음)
왜냐고요 그 이유도 알 수 없고 어쩌다 해 보니 된 거라서요.
그래서 이게 맞는 건지 확인도 해보고 싶고 더 중요한 것은 그 이유 가 알고 싶어 질문을
올렸던 것입니다
( 답변도 string 값을 ANSISTRING 으로 하고 이를 PANSICHAR로 했으니 된 것입니다.)
( 이렇게 답을 받고 보니 내 추측이 어쩌다 잡은 눈먼 고기가 아니었나 보네요)
(그래서 지금 바꾼 WINEXEC 가 임시 방편이 아니라 정상 방법이 되었습니다)
그런데 제가 가장 궁금 했던점은 Unicode String 을 PAnsiChar 로 바로 컨버트 하면 왜 안되
느냐는 것입니다. 말씀 하신 답변은 '일부 문자가 누락 된다"는 말씀 이었습니다.
그러면 그 누락문자가 어떤 것인가가 궁금해 집니다
ACSII Code 에서 Extended 된 부분의 Unicode 중에서의 누락되는게 생긴 다면 어느정도
이해 되지만 다 ASCII Code 내에 있는 것들인데 그런 것들 (즉 ANSISTRING 에서 다
수용 할 수 있는 코드들)까지에서 생략 되는 문자가 있다는 것인 가요 ?
String 으로 선언시Unicode 수용을 위해 Unicode String 으로 받 는 것은 당연 하겠자요.
그런데 String Type을 ANSISTRING, WIDESTRING, UNICODESTRING 으로 구분 하고
있으면서 (즉 ANSI 와 WIDE를 전부 수용 할수 있는 UNICODE String 을 운용하면서 )
Pchar또는 PAnsiChar 로 Cast 할때만 이런 현상이 생긴다는 게 잘 이해도 안되고 그래서
생각도 못 했던 것입니다)
어쨌든 잘못되었든 아니든 제작자가 String 은 바로 PANSICHAR 로 Cast 할 수 없고
string -> AnsiString 으로 한후 ANSISTRING을 가지 PAnsichar 로 Cast 하도록 만들어
놓았다니 그렇게 해야 겠지요.
어쨌든 눈먼 고기 잡은 건줄 알았던 것을 DELPHI 문법이 그렇게 되어 있음을 확인
시켜주어서 감사 합니다.
DELPHI 도움말 에서 String 은 PAnsichar 로 cast 할 수 없고 ANSISTRING 만 가능
하다는 설명은 못 보았습니다 (아니 비록 열심히 찾았지만 못찾았겠지요)
하옇튼 감사 합니다. 참조 Site 까지 알려 주신 것 정말 더 감사하고 있습니다.
만일 가능 하다면 EMBARCADERO의 TECHNICAL DOCUMENT 까지 있었으면
더 고마왔을 텐데요
(UNICODE, Ansistring .. 등에 이렇게 신경 쓰는 이유는 '한글 짤림' Check 문제
때문입니다. 한글 짤림 문제의 심각성때문에 DB에 자료 저장시 한글Data는 반드시
한글짤림 check 를 전체 Program 에서 하고 있습니다.
한글 Data 입력은 KEYBOARD입력뿐 아니라 (예를들면 결제DATA 적요 형성등)
DB자료 + DB 자료를 해서 만드는 FIELD 도 있습니다. 그래서 한글 짤림 발생 Chec
k 및 방지는 반드시 필요 합니다
즉 unicode 환경 하에서의 한글짤림 문제도 생각 해야 하기 때문에 이렇게 신경
쓰고 있습니다
감사 합니다
-
Humphery
2015.05.22 22:35
유니코드에 대해 조금 더 이해할 수 있도록 짧게 문제의 원인을 안내해 드립니다.
위와 같이 string(유니코드)은 ASCII 문자(1바이트 문자)를 사용하는 경우 짝수 byte마다 $00이 들어갑니다.
즉 한글자를 2바이트로 사용해 첫번째바이트는 문자 두번째 바이트는 $00(null byte)으로 채워줍니다.
만약 string을 PAnsiChar로 캐스팅 하는 경우 위의 그림을 예로들면 url 변수의 메모리번지를 전달하게 됩니다.
그러면 해당 문자열을 받은 DLL(또는 윈도우 API)에서 C스타일의 널문자종료 문자열을 사용하는 경우 첫번째 한글자의 영문만 읽어오기 때문에 원하지 않은 결과가 수행됩니다.
사용하시는 WinExec 윈도우 API는 아래와 같이 첫번째 커맨드라인 명령을 안시캐릭터포인터로 받도록 윈도우를 제작한 MS에서 정의해놓았습니다.
윈도우 API도 C스타일의 널문자종료 문자열을 사용합니다.
이런 원리를 이해하신다면 유니코드 사용이 생각하시는 것처럼 어렵지 않습니다.
특히 DB처리하는 부분은 DBMS의 캐릭터셋과 데이터타입만 잘 설정하신다면 안시코드와 유니코드 모두 동일한 코드로 사용할 수 있습니다.
Delphi WINEXEC 관련해서 문의드립니다
2015.05.16 04:32
자꾸 질문드려 죄송 합니다.
( ※ XE7로 Migration 하다보니 기왕의 DELPHI 에 있던 기능들이 변경되어 안되는 것들이 자꾸나오고 또 그런건 어디 '
자세한 설명도 찾기 힘들고요. 또 완전히 없어져서 안되는 것이 아니라 내용이 생각지 못하는 방향으로 바뀌는 것들이라
기존에 생각 못했던 것들이라 그렇네요)
문제의 내용 설명으로 iexplore를 실행시키는 것을 예로 들어 설명 하겠습니다
① WinExec(pansichar(C:\Program Files\Internet Explorer\iexplore.exe http://tech.devgear.co,kr/'),sw_show) 하면 잘 됩니다
②그런데 들어가는 command 나 argumenet 를 변수를 사용하는 경우에는 안됩니다
즉 aa := 'C:\Program Files\Internet Explorer\iexplore.exe http://tech.devgear.co,kr/' 로 하여 WinExec(pansichar(aa),sw_show) 로 한다거나
cmd_line := 'C:\Program Files\Internet Explorer\iexplore.exe', param_data := 'http://tech.devgear.co,kr' 로 하고
WinExec(Pansichar(cmd_line + ' ' + param_data).sw_show) 로 하거나
WinExec(Pansichar('C:\Program Files\Internet Explorer\iexplore.exe' + ' ' + param_data),sw_show)로 하면 안됩니다.
다른 프로그램을 실행 시키면서 parameter를 넘길때도 마찬 가지 입니다/
WinExce(PAnsiChar('TESTPRG' + ' ' + '이순신' + ' ' + '영웅'),0) 하면 잘되지만 param_1 := '이순신', param_2 := '영웅 '으로하여
WinExec(PAnsiChar('TESTPRG' + ' ' + param_1 + ' ' + param_2),0)' 하면 안됩니다.
(실제 업무에서는 parameter 가 변수로 바뀌므로 후자로 사용 될 수 밖에 없습니다. 예 LoginId, 성명 같은 거지요)
어디서 잘못 되었고 어떻게 하면 될지 해결 방안을 가르켜 주시면 고맙겠습니다.
(old version의 DELPHI 4, 5, 6 에서는 후자의 방법으로 많이 잘 사용 해 온 것입니다. 이걸 전환 해야 하니 어떻게 할지 방안이 없네요)
WINEXEC에서 XE6등에서는 PAnsiCharacter로 해야 하는 것(Unicode관련)은 알고 있지만 제대로 알지 못한 건지요.
그런데 위의 예와 같이 constatnt 값을쓰나 동일한 것을 변수에 넣고 쓰나 같은게 일반적인 상식이라 이와 관련된 것을 어디서 찾아 보아야
할지도 사실 알 수 없습니다. (하도 실력이 모자라서)
Ansichar 가 AnsiString 이나 String 이런 것과는 다른 것이라지만 값을 그냥 썼을때와 변수에 넣고 썼을때 왜 차이가 나는 건지 특히
Space 에 대해서 차이가 나는 건지 알수 없네요 (앞에붙은 Space나 뒤꼬리에 붙은 Space 라면 모르겠는데 문자열의 중간에 있는
Space인데 ...)
첨부 : 이를 Test 한 프로그램입니다 (DELPHI XE6 사용)
Source 와 실행 File 입니다 (ZIP으로 묶어 놓았으나 Zip을 풀면 됩니다)
댓글 3
-
Humphery
2015.05.18 18:51
-
jcitec
2015.05.18 23:47
예 고맙습니다.
PansiChar 로 쓰는 것은 AnsiSting 일때는 됩니다. (나도 이것저것 추측해 보고 추측을
테스트 해보고 알아 낸 거였습니다. 즉 Ansistring 값은 PAnsiString 으로 CAST 했을때
정상적으로 STRING 값은 안됩니다. String 은 Unicode String 으로 간주한다는 설명이
delphi 도움말에 있는데 이걸보고 혹시 AnsiString 과 PAnsiChar, WideString PWideChar 로
끼리끼리 만 노는게 아닌가 하는 생각이 들었고 Unicode String (String) 을 WideString 으로
분류해서 끼리끼리 노는데서 (PAnsiChar 에서) 안끼워 주는 거 아닐까 하는 추측을 했고요
그래서 String 값을 ANSISTRING으로 정의 한 변수에다 넣고 PANSICHAR을 했더니 먹혀
들더군요. 완전히 가정만 가지고 추측 했던 것이 먹혀 들었던 것인데 미치 눈먼고기
낚았다는 기분이더군요. (그래서 컨버전에서는 일단 임시 방편으로 그렇게 하고 있음)
왜냐고요 그 이유도 알 수 없고 어쩌다 해 보니 된 거라서요.
그래서 이게 맞는 건지 확인도 해보고 싶고 더 중요한 것은 그 이유 가 알고 싶어 질문을
올렸던 것입니다
( 답변도 string 값을 ANSISTRING 으로 하고 이를 PANSICHAR로 했으니 된 것입니다.)
( 이렇게 답을 받고 보니 내 추측이 어쩌다 잡은 눈먼 고기가 아니었나 보네요)
(그래서 지금 바꾼 WINEXEC 가 임시 방편이 아니라 정상 방법이 되었습니다)
그런데 제가 가장 궁금 했던점은 Unicode String 을 PAnsiChar 로 바로 컨버트 하면 왜 안되
느냐는 것입니다. 말씀 하신 답변은 '일부 문자가 누락 된다"는 말씀 이었습니다.
그러면 그 누락문자가 어떤 것인가가 궁금해 집니다
ACSII Code 에서 Extended 된 부분의 Unicode 중에서의 누락되는게 생긴 다면 어느정도
이해 되지만 다 ASCII Code 내에 있는 것들인데 그런 것들 (즉 ANSISTRING 에서 다
수용 할 수 있는 코드들)까지에서 생략 되는 문자가 있다는 것인 가요 ?
String 으로 선언시Unicode 수용을 위해 Unicode String 으로 받 는 것은 당연 하겠자요.
그런데 String Type을 ANSISTRING, WIDESTRING, UNICODESTRING 으로 구분 하고
있으면서 (즉 ANSI 와 WIDE를 전부 수용 할수 있는 UNICODE String 을 운용하면서 )
Pchar또는 PAnsiChar 로 Cast 할때만 이런 현상이 생긴다는 게 잘 이해도 안되고 그래서
생각도 못 했던 것입니다)
어쨌든 잘못되었든 아니든 제작자가 String 은 바로 PANSICHAR 로 Cast 할 수 없고
string -> AnsiString 으로 한후 ANSISTRING을 가지 PAnsichar 로 Cast 하도록 만들어
놓았다니 그렇게 해야 겠지요.
어쨌든 눈먼 고기 잡은 건줄 알았던 것을 DELPHI 문법이 그렇게 되어 있음을 확인
시켜주어서 감사 합니다.
DELPHI 도움말 에서 String 은 PAnsichar 로 cast 할 수 없고 ANSISTRING 만 가능
하다는 설명은 못 보았습니다 (아니 비록 열심히 찾았지만 못찾았겠지요)
하옇튼 감사 합니다. 참조 Site 까지 알려 주신 것 정말 더 감사하고 있습니다.
만일 가능 하다면 EMBARCADERO의 TECHNICAL DOCUMENT 까지 있었으면
더 고마왔을 텐데요
(UNICODE, Ansistring .. 등에 이렇게 신경 쓰는 이유는 '한글 짤림' Check 문제
때문입니다. 한글 짤림 문제의 심각성때문에 DB에 자료 저장시 한글Data는 반드시
한글짤림 check 를 전체 Program 에서 하고 있습니다.
한글 Data 입력은 KEYBOARD입력뿐 아니라 (예를들면 결제DATA 적요 형성등)
DB자료 + DB 자료를 해서 만드는 FIELD 도 있습니다. 그래서 한글 짤림 발생 Chec
k 및 방지는 반드시 필요 합니다
즉 unicode 환경 하에서의 한글짤림 문제도 생각 해야 하기 때문에 이렇게 신경
쓰고 있습니다
감사 합니다
-
Humphery
2015.05.22 22:35
유니코드에 대해 조금 더 이해할 수 있도록 짧게 문제의 원인을 안내해 드립니다.
위와 같이 string(유니코드)은 ASCII 문자(1바이트 문자)를 사용하는 경우 짝수 byte마다 $00이 들어갑니다.
즉 한글자를 2바이트로 사용해 첫번째바이트는 문자 두번째 바이트는 $00(null byte)으로 채워줍니다.
만약 string을 PAnsiChar로 캐스팅 하는 경우 위의 그림을 예로들면 url 변수의 메모리번지를 전달하게 됩니다.
그러면 해당 문자열을 받은 DLL(또는 윈도우 API)에서 C스타일의 널문자종료 문자열을 사용하는 경우 첫번째 한글자의 영문만 읽어오기 때문에 원하지 않은 결과가 수행됩니다.
사용하시는 WinExec 윈도우 API는 아래와 같이 첫번째 커맨드라인 명령을 안시캐릭터포인터로 받도록 윈도우를 제작한 MS에서 정의해놓았습니다.
윈도우 API도 C스타일의 널문자종료 문자열을 사용합니다.
이런 원리를 이해하신다면 유니코드 사용이 생각하시는 것처럼 어렵지 않습니다.
특히 DB처리하는 부분은 DBMS의 캐릭터셋과 데이터타입만 잘 설정하신다면 안시코드와 유니코드 모두 동일한 코드로 사용할 수 있습니다.
다음과 같은 코드로 진행해 보세요. 유니코드를 PAnsiChar로 바로 컨버팅 시 일부 문자열이 누락될 수 있으니 AnsiChar로 컨버팅 후 PAnsiChar로 처리하시기 바랍니다.
var
Path: string;
begin
Path := 'C:\Program Files\Internet Explorer\iexplore.exe';
WinExec(PAnsiChar(AnsiString(Path)), SW_SHOW);
다음 링크를 참고했습니다.(구글에서 "winexec wide char" 검색)
http://bcbjournal.org/forums/viewtopic.php?f=10&t=1278