RAD Studio 2009에서 CreateProcess를 사용할 때 kernel32.dll access violation이 발생하는 개같은 일이 발생.
이전까진 잘 썼었는데.
호출코드는 대략 아래와 같음. (초기화 같은건 생략)
CreateProcess(
nil, 'cmd.exe', @SecAttr, @SecAttr, True, DETACHED_PROCESS or NORMAL_PRIORITY_CLASS,
nil, nil, StartupInfo, ProcessInfo
);
nil, 'cmd.exe', @SecAttr, @SecAttr, True, DETACHED_PROCESS or NORMAL_PRIORITY_CLASS,
nil, nil, StartupInfo, ProcessInfo
);
문제는 2번째 파라메터인 'cmd.exe' 때문이었다.
PChar를 파라메터로 받는건데, 이게 쫌 함정이다.
WideChar를 사용하는 내부함수인 ProcessCreateW 함수에서는 넘어온 변수를 WideString으로 바꾸는 일이 필요하므로,
2번째 파라메터가 const String 일 경우 손댈 수가 없어 access violation이 발생한다.
MSDN 원문은 다음과 같다.
링크: http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
아래처럼 바꾸면 된다.
손댈 수 있는 놈으로 수정하는 것이다...
procedure TForm1.Button1Click(Sender: TObject);
var
SecAttr: TSecurityAttributes;
ProcessInfo: TProcessInformation;
StartupInfo: TStartupInfo;
cmd: array [0..1023] of WideChar;
begin
SecAttr.nLength:=SizeOf(SecAttr);
SecAttr.lpSecurityDescriptor:=nil;
SecAttr.bInheritHandle:=True;
ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
StartupInfo.cb:=SizeOf(StartupInfo);
StartupInfo.dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
StartupInfo.wShowWindow:=SW_SHOW;
ZeroMemory(@cmd, SizeOf(cmd));
cmd:='regedit.exe';
CreateProcess(
nil, cmd, @SecAttr, @SecAttr, True,
DETACHED_PROCESS or NORMAL_PRIORITY_CLASS,
nil, nil,
StartupInfo, ProcessInfo
);
end;
var
SecAttr: TSecurityAttributes;
ProcessInfo: TProcessInformation;
StartupInfo: TStartupInfo;
cmd: array [0..1023] of WideChar;
begin
SecAttr.nLength:=SizeOf(SecAttr);
SecAttr.lpSecurityDescriptor:=nil;
SecAttr.bInheritHandle:=True;
ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
StartupInfo.cb:=SizeOf(StartupInfo);
StartupInfo.dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
StartupInfo.wShowWindow:=SW_SHOW;
ZeroMemory(@cmd, SizeOf(cmd));
cmd:='regedit.exe';
CreateProcess(
nil, cmd, @SecAttr, @SecAttr, True,
DETACHED_PROCESS or NORMAL_PRIORITY_CLASS,
nil, nil,
StartupInfo, ProcessInfo
);
end;
아 병신... ... ...
'Delphi' 카테고리의 다른 글
[Delphi] IdHTTP + 아파치 인증 (0) | 2009.08.31 |
---|---|
[Delphi] TWebBrowser 스크롤바 없애기 (2) | 2009.08.17 |
[Delphi] POST 전송으로 파일전송하기 (2) | 2009.06.21 |
[Delphi] 키보드 누르기 (2) | 2009.06.21 |
[Delphi] 클립보드 이미지 데이터를 JPEG로 저장하기 (0) | 2009.06.21 |