본문 바로가기

work/delphi

[Delphi] MAC Address 확인 (cmd 명령 리턴값 받기)

// 읽고 쓰기 파이프 핸들
type
  TPipeHandles=record
    hRead, hWrite: DWORD;
  end;


// 실행한 도스 명령어의 결과값을 반환
function GetDosOutput(cmd: String): String;
const BUFFER_SIZE=4096;

 

  // 넘겨받은 핸들을 닫아줌 ____________________________________________________
  procedure ClosePipe(var Pipe: TPipeHandles);
  begin
    with Pipe do begin
      if
hRead<>0 then CloseHandle(hRead);
      if hWrite<>0 then CloseHandle(hWrite);
      hRead:=0;
      hWrite:=0;
    end;
  end;

  // 파이프에서 읽어온 정보를 Result 에 저장 ___________________________________
  procedure ReadPipe(var Pipe: TPipeHandles);
  var
    ReadBuf: array [0..BUFFER_SIZE] of Char;
    BytesRead: DWORD;
  begin
    // 파이프에 읽을 데이터가 있는지 검사
    if PeekNamedPipe(pipe.hRead, nil, 0, nil, @BytesRead, nil) and (BytesRead>0)
    then begin
      ReadFile(pipe.hRead, ReadBuf, BytesRead, BytesRead, nil);
      if BytesRead>0 then begin
        ReadBuf[BytesRead]:=#0;
        Result:=ReadBuf;
      end;
    end;
  end;
  // ___________________________________________________________________________


var
  ProcessInfo: TProcessInformation;
  StartupInfo: TStartupInfo;
  SecAttr: TSecurityAttributes;
  PipeStdOut: TPipeHandles;
  PipeStdErr: TPipeHandles;
  dwExitCode: DWORD;

 

begin
  SecAttr.nLength:=SizeOf(SecAttr);
  SecAttr.lpSecurityDescriptor:=nil;
  SecAttr.bInheritHandle:=True;

 

  // STDOUT 파이프 생성
  with PipeStdOut do // 표준 출력(stdout) 파이프
    if not CreatePipe(hRead, hWrite, @SecAttr, BUFFER_SIZE) then ShowMessage('STDOUT pipe 를 만들 수 없습니다.');

 

  try
    // STDERR 파이프 생성
    with PipeStdErr do // 표준 에러(stderr) 파이프
      if not CreatePipe(hRead, hWrite, @SecAttr, BUFFER_SIZE) then ShowMessage('STDERR pipe 를 만들 수 없습니다.');
  except
    ClosePipe(PipeStdOut);
    raise;
    Exit;
  end;

 

  try
    FillChar(StartupInfo, SizeOf(StartupInfo), 0);
    with StartupInfo do begin
      cb:=SizeOf(StartupInfo);
      dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
      // 표준출력 and 표준에러 스트림에 생성한 파이프를 연결
      hStdOutput:=PipeStdOut.hWrite;
      hStdError:=PipeStdErr.hWrite;
      wShowWindow:=SW_HIDE;
    end;

 

    // 도스 명령어 실행
    if CreateProcess(
      nil, PChar(Cmd), @SecAttr, @SecAttr, True,
      DETACHED_PROCESS or NORMAL_PRIORITY_CLASS,
      nil, nil,
      StartupInfo, ProcessInfo
    )
    then begin
      dwExitCode:=STILL_ACTIVE;
      Screen.Cursor:=crHourglass;
      try
        repeat

          // 실행완료까지 기다림
          WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
          GetExitCodeProcess(ProcessInfo.hProcess, dwExitCode);

 

          Application.ProcessMessages;

 

          // 실행완료후 결과값을 파이프에서 읽어옴
          ReadPipe(PipeStdOut);
          ReadPipe(PipeStdErr);
        until dwExitCode<>STILL_ACTIVE; //  아직 실행중이면 반복

 

        if not GetExitCodeProcess(ProcessInfo.hProcess, dwExitCode) then ShowMessage('Exit Code 를 읽어올 수 없습니다.');

 

        if dwExitCode<>0 then // 정상종료가 아니면
          raise Exception.Create('Exit Code '+IntToStr(dwExitCode));
      finally
        Screen.Cursor:=crDefault;
        if dwExitCode=STILL_ACTIVE then TerminateProcess(ProcessInfo.hProcess, 1);
        CloseHandle(ProcessInfo.hProcess);
        CloseHandle(ProcessInfo.hThread);
        ProcessInfo.hProcess:=0;
      end;
    end
    else
ShowMessage(Cmd+' 명령어 실행을 위한 프로세스 생성 실패');
  finally
    ClosePipe(PipeStdOut);
    ClosePipe(PipeStdErr);
  end;
end;

//=========================================================================================

procedure TForm1.Button1Click(Sender: TObject);
var
  s: String;
  sList, tList: TStringList;
  i: Integer;


begin
  sList:=TStringList.Create;
  tList:=TStringList.Create;
  try

    s:=GetDosOutput('ipconfig /all');

    ExtractStrings([#13],[],PChar(s),sList);

    Memo1.Clear;


    for i:=0 to sList.Count - 1 do begin
      // 맥어드레스는 Physical Address 라는 항목에 있음
      if Pos('Physical Address', sList[i])>0 then begin
        tList.Clear;
        // ':' 로 나눈 뒤에 것이 MAC Address
        ExtractStrings([':'], [], PChar(sList[i]), tList);
        Memo1.Lines.Add(Trim(tList[1]));
      end;
    end;

  finally
    FreeAndNil(tList);
    FreeAndNil(sList);
  end;
end;




출처 : http://bloodguy.tistory.com/entry/Delphi-MAC-Address-%ED%99%95%EC%9D%B8