프로그램의 중복실행을 방지하는 방법으로는 CreateMutex가 많이 쓰이는 것 같습니다.
저는 조금 고전적이지만 이해하기 쉬운 Global Atom Table을 이용한 방법을 소개합니다.
실은 10년전쯤에 컴포넌트로 만든 것을 컴포넌트 설치과정 없이 바로 이용할 수 있도록 단순한 유니트로
바꾼 것입니다. 
이용법은 프로그램 소스 내용 중 상수로 정의된 Author와 RunProgram 값을 올바르게 고친 후 프로젝트가 위치한 
폴더에 복사해 두고, 아래와 같이 프로젝트 소스화일(*.dpr)의 uses절에 제일 먼저 RunOne을 등록만 하면 됩니다. 
  uses RunOne, 
            Forms, . . .  .

그리고 RunOne은 실행하고자 하는 프로그램이 이미 실행중일 경우 최소화 상태이면 원래 크기로, 최상위
윈도우가 아니면 최상위 윈도우로 변경하여 사용자가 이전에 이미 실행 중이었다는 것을 바로 인식할 수 
있도록 해 줍니다.
아래는 RunOne.pas 소스입니다.

unit RunOne;

interface

uses WinTypes, SysUtils, Forms;

const
  Author = 'Silhwan Hyun';  // 저자명 : 실행여부를 검사하기 위한 검색어를 구성함.
  RunProgram = 'TClock';    // 프로그램명 :             "

implementation

var
  AtomText: array[0..63] of Char;
  AtomSaved : boolean = false;

  MyClassName    : array[0..255] of Char;
  FoundPrevInst  : boolean = false;
  PrevInstHandle : HWnd = 0;
  FoundAtom      : TAtom;

  NewAtom : TAtom;
  MyPopup : HWnd;

function LookAtAllWindows(Handle: HWnd; Temp: Longint): BOOL; stdcall;
var
  ClassName : array[0..255] of Char;
begin
  LookAtAllWindows := true;

  if GetClassName(Handle, ClassName, SizeOf(ClassName)) > 0 then
  begin
    if StrComp(ClassName, MyClassName) = 0 then // 동일 window class ?
    begin
    // 중복실행여부를 조사하기 위한 검색어 생성
       StrPCopy(AtomText, Author + RunProgram + IntToStr(Handle));
    // 검색어가 Global Atom Table에 등록되어 있는지 확인
       FoundAtom := GlobalFindAtom(AtomText);
       if FoundAtom <> 0 then  // Global Atom Table에 등록되어 있으면
       begin
          FoundPrevInst  := true;    // 이미 실행 중인 것으로 표시
          PrevInstHandle := Handle;  // 실행 중인 어플리케이션 윈도우 핸들
          LookAtAllWindows := false; // enumeration 함수를 종료시킨다
       end;
    end;
  end;
end;

initialization
 // 프로그램의 클래스명을 알아낸다.   
  GetClassName(Application.Handle, MyClassName, SizeOf(MyClassName));
 // 윈도우를 검색하여 중복실행이 아닌지 확인한다
  EnumWindows(@LookAtAllWindows, 0);
  if FoundPrevInst then   // 이미 실행 중이면
  begin
     MyPopup := GetLastActivePopup(PrevInstHandle);
     BringWindowToTop(PrevInstHandle);
     if IsIconic(MyPopup) then
     begin
        ShowWindow(MyPopup, SW_RESTORE);  // 최소화 상태이면 원래 크기로
     end else
        BringWindowToTop(MyPopup);        // 최상위 윈도우로
     SetForegroundWindow(MyPopup);      // 포커스를 준다.    *** Added ***

     Halt(0);  // 새로 실행한 프로그램은 강제로 종료시킨다
  end else
  begin
   // 실행중이 아니면 검색어를 Global Atom Table에 등록한다
     StrPCopy(AtomText, Author + RunProgram + IntToStr(Application.Handle));
     NewAtom := GlobalAddAtom(AtomText);
     if NewAtom <> 0 then   // Global Atom Table에 등록성공이면
        AtomSaved := true;
  end;

finalization
  // 프로그램 종료시는 Global Atom Table에 등록해 둔 검색어를 해제한다.
  if AtomSaved then
  begin
     FoundAtom := GlobalFindAtom(AtomText);
     if FoundAtom <> 0 then
        GlobalDeleteAtom(FoundAtom);
  end;

end.



댓글 중~ 


단지...
BringWindowToTop 다음에

     SetForegroundWindow(MyPopup);

이것을 추가하는것이 더 편할것 같습니다.
어차피 실행할려고 한것이니 최상위 및 원복 후 포커스를 주는것이 좋을듯 합니다. ^^  



원본 링크 : http://www.delmadang.com/community/bbs_print.asp?bbsNo=3&bbsCat=0&indx=412497

구두점 및 기호

검색 시 아래의 문장 부호가 지원되지만 검색에 문장 부호를 포함한다고 해서 반드시 검색결과가 향상되는 것은 아닙니다. 구두점을 포함해도 결과가 향상되지 않는다고 판단되는 경우 구두점을 없애고 검색한 제안 결과가 표시될 수 있습니다.

기호사용 방법
+

Google+ 페이지 또는 혈액형 검색
예: +Chrome 또는  AB+

@소셜 태그 검색
예: @agoogler
$가격 검색
예: nikon $400
#

최신 주제의 인기 해시태그 검색
예: #throwbackthursday

-단어 또는 사이트 앞에 대시를 사용하는 경우 검색결과에서 해당 정보가 포함된 사이트가 제외됩니다. 자동차 브랜드 Jaguar와 동물 재규어처럼 여러 의미를 가진 단어를 검색할 때 유용합니다.
예: 재규어 속도 -자동차 또는 팬더 -site:wikipedia.org
"인용부호 안에 한 단어 또는 구를 넣으면 순서까지 정확하게 일치하는 단어/구가 포함된 페이지만 결과에 표시됩니다. 정확한 단어 또는 구를 검색하는 경우에만 이 방법을 사용하세요. 그렇지 않으면 유용한 많은 결과를 실수로 제외하게 됩니다.
예: "나보기가 역겨워 가실 때에는"
*별표는 알 수 없는 용어 또는 '와일드 카드' 용어에 대한 자리표시자 역할을 합니다.
예: "* 도둑이 * 도둑 된다"
..숫자 사이에 공백 없이 마침표 두 개를 넣으면 주어진 범위 내의 숫자를 포함하는 검색결과가 표시됩니다.
예: 카메라 $50..$100

검색 연산자

검색 연산자는 검색에 추가하여 결과를 좁히는 데 사용할 수 있는 단어입니다. 하지만 모든 검색 연산자를 기억할 필요는 없습니다. 고급검색 페이지로도 검색결과를 좁힐 수 있습니다.

연산자사용 방법
site:특정 사이트 또는 도메인의 검색결과를 표시합니다.
예: 올림픽 site:nbc.com 및 olympics site:.gov
link:특정 페이지로 연결되는 페이지를 찾습니다.
예: link:youtube.com
related:이미 알고 있는 URL과 유사한 사이트를 찾습니다.
예: related:time.com
OR여러 단어 중 하나를 포함하는 페이지를 찾습니다.
예: 마라톤 OR 경주
info:페이지의 저장된 버전, 유사한 페이지, 사이트로 연결되는 페이지 등 웹 주소 관련 정보를 표시합니다.
예: info:google.com
cache:Google이 마지막으로 사이트를 방문했을 당시의 페이지 모습을 표시합니다.
예: cache:washington.edu

참고: 연산자 또는 문장 부호를 사용하여 검색하는 경우 연산자와 검색어 사이에 공백이 있어서는 안 됩니다. 즉,site:nytimes.com을 입력하면 검색결과가 표시되지만 site: nytimes.com을 입력하면 결과가 제대로 표시되지 않습니다.



원본 링크 : https://support.google.com/websearch/answer/2466433

시작 프로그램이란?


시작 프로그램이란 윈도우가 시작될 때 자동으로 실행되는 프로그램 입니다. 즉, 윈도우가 시작될 때마다 매번 자동으로 시작되는 프로그램들의 집합을 의미하는 것이죠. 시작 프로그램은 시작프로그램 폴더, 또는 관련 레지스트리에 원하는 프로그램(바로 가기, 실행 파일, 배치 파일 등)을 등록하는 것으로 지정할 수 있습니다.


참고로 이러한 시작 프로그램은 사용자 계정별로 따로 적용되는 개별 사용자용 시작 프로그램과 모든 사용자에게 공통으로 적용되는 전체 사용자용 시작 프로그램 두 가지 종류로 나누어집니다.

개별 사용자용 시작 프로그램 - 해당 사용자 계정으로 로그온될 때만 실행됨.
전체 사용자용 시작 프로그램 - 모든 사용자 계정에서 공통으로 실행됨.


또한 시작 프로그램은 윈도우 시작시마다 항상 실행되는 지속용 시작 프로그램과, 다음 번 로그온 때 한 번만 실행되고 이후 제거되는 일회용 시작 프로그램으로 다시 나누어지죠.

지속용 시작 프로그램 - 매번 윈도우의 지정한 사용자 계정으로 로그온될 때마다 자동으로 실행됨.
일회용 시작 프로그램 - 다음번 윈도우의 지정한 사용자 계정으로 로그온될 때 한 번만 실행되고 이후 제거됨.



즉, 시작 프로그램에는 개별-지속, 개별-일회, 전체-지속, 전체-일회의 총 네 가지 형태의 유형이 존재한다고 생각하시면 됩니다. 그리고 마지막으로 윈도우에서 시작 프로그램을 등록하는 방법은 크게 아래의 두 가지 방법이 있습니다.

1. 시작 프로그램 폴더에 등록.
2. 레지스트리의 Run 과 RunOnce 에 등록.








시작프로그램 폴더


시작프로그램 폴더에 등록된 시작 프로그램들의 모습



특정 프로그램, 바로 가기, 배치 파일 등을 시작프로그램 폴더에 위치시키면 매번 윈도우로 로그온될 때마다 시작프로그램 폴더에 위치한 프로그램들이 자동으로 실행되게 됩니다. 즉, 시작프로그램 폴더는 지속형 시작 프로그램들을 위치시키는 공간이라고 할 수 있습니다. 이러한 시작프로그램 폴더는 개별 사용자용과 전체 사용자용, 두 가지 폴더(경로)로 나누어져 있고, 용도에 맞춰 두 폴더 중 원하는 곳에 프로그램(바로 가기, 실행 파일, 배치 파일)을 위치시키면 됩니다.


먼저 사용자 계정별로 달리 적용할 수 있는 개별 사용자용 시작 프로그램 폴더의 경로는 아래와 같습니다.

%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup





다음으로 모든 사용자 계정에 함께 적용되는 전체 사용자용 시작 프로그램 폴더의 경로는 아래와 같습니다.

%ProgramData%\Microsoft\Windows\Start Menu\Programs\Startup




윈도우 7 이하 사용자들은 경로는 물론 스크린 샷과 같은 방법으로 간단하게 시작프로그램 폴더에 접근할 수 있으며, 윈도우 8 사용자들도 비슷하게 시작 타일에서 접근할 수 있지만 그냥 경로를 긁어 파일 탐색기를 통해 접근하는 게 더 편하실 겁니다.






시작 프로그램 레지스트리


레지스트리에 등록된 시작 프로그램들의 모습 [개별-지속]



먼저 시작 프로그램에 해당하는 레지스트리 키는 총 네 개로 이루어져 있으며 이들은 아래와 같습니다.

개별 사용자 지속용 : HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run 
개별 사용자 일회용 : HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce

전체 사용자 지속용 : HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run
전체 사용자 일회용 : HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce


* 전체 사용자 - HKEY_LOCAL_MACHINE, 개별 사용자 - HKEY_CURRENT_USER
* 일반 - Run, 일회성 - RunOnce



이러한 레지스트리는 Regedit 를 통해 편집할 수 있습니다. 레지스트리를 통해 시작 프로그램을 등록하는 방법은 원하는 키로 이동한 후 하위에 문자열 값(REG_SZ) 을 생성하고 해당 문자열의 값 데이터로 원하는 프로그램(기능)의 실행 명령을 등록하면 됩니다. 참고로 값 이름은 적절히 자신이 원하는대로 알아먹을 수 있게만 지정하면 됩니다. [레지스트리 편집에 관해선 자세하게 설명하지 않겠습니다.]

해당 키에 원하는 프로그램의 실행 명령을 문자열 값(REG_SZ)으로 등록.



만약에 이것을 명령형 유틸인 Reg 명령을 통해 작업한다면 명령 프롬프트에서 아래와 같은 식으로 작업할 수 있습니다. 해당 명령은 위의 스크린 샷과 동일한 작업을 담고 있으니 옵션들의 뜻은 알아서 유추하실 수 있을거라 믿습니다.

reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /v "Test" /t REG_SZ /d "F:\Temp\Test.cmd" /f








시작 프로그램에 배치 파일을 등록할 때 팁


시작 프로그램에 배치 파일을 등록하면 윈도우를 시작하고 사용자 계정으로 로그온된 후 순간적이지만 명령 프롬프트 창이 떴다가 사라지게 됩니다. 또는 배치 파일의 작업이 오래 걸리는 것이라면 배치 파일이 모두 완료될 때까지 명령 프롬프트가 노출되죠. 이렇게 배치 파일 창이 노출되는 것이 마음에 들지 않는 사용자도 있으리라 생각합니다.

그럴 땐 시작 프로그램에 배치 파일을 직접 등록하는 것이 아닌, 배치 파일을 실행하되 실행되는 명령 프롬프트 창을 숨겨주는 VB 스크립트를 만들고, 해당 VB 스크립트를 시작 프로그램에 등록하는 방법을 사용하면 됩니다. 즉, 아래와 같은 VB 스크립트를 만들어 시작 프로그램으로 등록하면 되는 것이죠. 이 때 빨간색으로 표시한 부분에 원하는 배치 파일을 넣으시면 됩니다.

Example.vbs
Set WinScriptHost = CreateObject( "WScript.shell" )
WinScriptHost.Run Chr(34) & "D:\VARS\Config\Change.cmd" & Chr(34), 0 
Set WinScriptHost = Nothing



원래 윈도우 7 을 기준으로 포스팅한 내용이지만 다른 윈도우들도 이와 다르지 않기 때문에 전체 윈도우용 설명으로 수정한 후 재포스팅합니다. 시작 프로그램에 대해서는 크게 더 이야기할 게 없네요. 이쯤에서 줄이도록 하겠습니다. ^^

 


원본링크 : http://cappleblog.co.kr/289

+ Recent posts