아쉽게도 VisualStudio2012버전 부터는 Macro IDE기능을 사용할 수 없게 됐다.

개인적으로 Doxygen용 자동주석 매크로기능을 위해 활용하고 있었는데

VS2012부터 보이지 않아 어디에 숨겼는지 한참을 찾았다.

결국 구글링을 해보니 MS에서 의도적으로 뺀거라고 한다. 전체 VS유저중 사용률이 1%미만 이라나.

Macro외에도 tool 전체의 Performance향상을 위해 몇몇 IDE기능을 줄였다고 한다.

http://social.msdn.microsoft.com/Forums/vstudio/en-US/d8410838-085b-4647-8c42-e31b669c9f11/macros-in-visual-studio-11-developer-preview

 

암튼 자동 주석같은 매크로 기능은 플러그인 프로젝트를 통해 계속 이용할 수 있다. :)

 

1. Visual Studio 추가기능 프로젝트 생성

적당한 이름으로 생성해 준다.

2. 확장 기능을 개발할 언어를 선택해준다. (난 C# 으로)

3. 메뉴에 확장기능 항목이 추가되도록 한다. (우리가 만든 확장기능은 도구 메뉴에서 확인가능하다.)

이후에는 계속 다음을 눌러 프로젝트가 생성되도록 한다.

 

4. Connect.cs파일에서 Exec함수를 찾고 아래 내용을 추가한다.

Exec라는 함수이름 대로 우리가 개발한 확장기능을 나중에 VS에서 사용할때 호출되는 함수다. (사진 클릭해서 원본으로 보기)

 

5. 컴파일이 성공하면 종료 후 다시 실행한다.

적당한 프로젝트 하나를 연 후 소스코드의 적당한 위치에 커서를 위치 시키고 "도구" 메뉴에 우리가 추가한 플러그인을 실행한다.

Doxygen 주석이 추가된걸 확인할 수 있다.

 

6. 매번 메뉴를 클릭하는건 귀찮으니 우리가 개발한 확장기능에 단축키를 할당할 수 도 있다.

도구 - 옵션 - 키보드 선택 후 comment(프로젝트 이름)로 검색하면 개발한 확장기능이 검색된다.

선택 후 "바로 가기 키 누르기"에서 적당한 단측키를 할당해준다.(Ctrl + `은 개인적으로 사용하지 않는 키라서 이걸로 정했음)

확인을 누르고 닫은 후 앞으로는 메뉴 대신 위에서 할당한 단축키를 사용하면 된다.

 

7. 확장기능 배포

내가 만든 확장기능은 dll형태로 일반 프로젝트와 동일하게 프로젝트 폴더(Debug나 Release)에 생성된다.

VS에 설치되는 폴더는 C:\Users\jung\Documents\Visual Studio 2012\Addins 이며 FunctionComment - For Testing.AddIn

이라는 파일명으로 위자드가 자동 생성해준 것을 볼수 있다.

파일을 메모장으로 열어보면 <Assembly> 항목에 우리가 만든 dll위치가 들어가 있는것을 볼수 있는데

원하는 위치에 dll을 설치하고 이 경로만 바꿔주면 된다.

 

 

 

 추가한 소스

public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
  {
   handled = false;
   if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
   {
    if(commandName == "Doxgen2012.Connect.Doxgen2012")
    {
                    EnvDTE.TextSelection textSelection = (EnvDTE.TextSelection)_applicationObject.ActiveWindow.Selection;
                    textSelection.Insert("//-----------------------------------------------------------------------------------//");
                    textSelection.NewLine();
                    textSelection.Insert("//");
                    textSelection.NewLine();
                    textSelection.Insert("// @brief     :  ");
                    textSelection.NewLine();
                    textSelection.Insert("// @param     :  ");
                    textSelection.NewLine();
                    textSelection.Insert("// @return    :  ");
                    textSelection.NewLine();
                    textSelection.Insert("// @author    :  ");
                    textSelection.Insert(System.Environment.UserName);
                    textSelection.NewLine();
                    textSelection.Insert("// @date      :  ");
                    textSelection.Insert(System.DateTime.Now.ToLongDateString());
                    textSelection.Insert("  ");
                    textSelection.Insert(System.DateTime.Now.ToLongTimeString());
                    textSelection.NewLine();
                    textSelection.Insert("//");
                    textSelection.NewLine();
                    textSelection.Insert("//-----------------------------------------------------------------------------------//");

     handled = true;
     return;
    }
   }
  }
  private DTE2 _applicationObject;
  private AddIn _addInInstance;
 } 

 

 

 

 참고 : http://www.dzone.com/articles/missing-macros-visual-studio

 

출처 : http://ccami.tistory.com/19

 

DDNS 설정하는 방법이에요.

ipTIME 공유기를 기준으로 설명하는 것이니, 참고하세요~



ipTIME에서는 기본적으로 DDNS를 제공하고 있어요.

DDNS란? 1) 유동IP를 사용하는 컴퓨터들의 경우에도 쉽게 DNS를 사용 할 수 있도록 해주는 것이에요.

2) IP를 외우기 힘드니까 쉽게 주소로 해서 외우기 쉽게 하려는 목적이에요.


쉽게말해, 공유기도 하나의 컴퓨터인데 외부에서 공유기를 찾아오는 주소를 설정해 주는 거에요.


예를들어, 네이버 홈페이지를 들어갈때 www.naver.com 으로 주소창에 치면 이동을 하는데

네이버 홈페이지의 IP인 220.95.233.171 를 주소창에 쳐도 네이버에 접속이 가능하게 되어 있는데 이게 DNS의 역할이에요. 저 IP를 일일히 외워서 사용하기엔 외울 숫자가 너무 많잖아요?


이와같이, 공유기에도 IP가 들어가는데 그 IP에 주소를 할당해서 외부에서 접속하기 쉽게 해주기 위한 목적이에요.

네이버같이 큰 업체는 고정 IP를 사용하지만, 일반 가정집에서는 유동 IP를 사용하기 때문에

자꾸 바뀌는 IP를 위해 DDNS (Dynamic DNS)를 설정해 주는 거구요.






외부에서 공유기에 접속을 하려면 일단 포트를 열어 줘야 하는데,


먼저 공유기 설정창 (기본설정 : 192.168.0.1)으로 가서 환경설정을 열어요.



고급설정 - 보안기능 - 공유기 접속관리로 가서 원격 관리 포트 사용에서 포트를 설정해 주어요.

저 숫자는 아무 숫자나 상관이 없고 여기선 1233으로 하도록 하겠습니다.

간혹 인터넷 업체에서 특정 범위의 포트를 막아놓는 경우도 있으므로 주의해 주세요.





고급설정 - 특수기능 - DDNS 설정 으로 가서 이제 등록을 합니다.

설명에 나와있듯이 호스트이름은 접속할 주소를 설정하는 곳이에요.

설정할 주소.iptime.org 이런 식으로 설정 해줘야 하구요.

한번 설정하면 바꾸려면 ipTIME에다가 문의 해야하니까 신중하게 결정하도록 해요.

사용자 계정(이메일 주소)과 암호는 본인이 설정해 주세요.




추가를 하면 등록중이라고 나오다가 곧 정상 등록이 되었다고 나와요.

혹시 다른 사람과 주소가 중복이 된다 하면 삭제하고 다시 등록해 보세요.


한 주소당 메일주소는 하나씩 되더라구요.

나중에 주소를 바꾸고 싶을때는 ipTIME 고객센터에 전화해서 메일주소를 알려주고 주소를 삭제해달라 해야해요. 안그러면 새 주소가 등록이 안되요.



이렇게 하면 DDNS 등록은 끝 ! 쉽죠...?


 





이제 접속을 해볼 차례에요.


자신의 컴퓨터에서 공유기 환경설정에 들어갈 때 192.168.0.1로 해서 들어간 것을

외부에서도 그대로 들어갈 수 있는데요.


내부 네트워크에서는 설정한 주소.iptime.org만 해도 접속이 가능한데

외부 네트워크에서는 포트번호도 같이 쳐줘야 해요.

설정한 주소.iptime.org:1233 이런식으로요.


많은 포트(길) 중에 1233번이라는 포트(길)만 열어준 거기 때문에 그 길을 통해서 공유기로 들어가야 하거든요.



이제 아무데서나 인터넷만 연결이 되 있으면 집에있는 공유기에 접속을 할 수 있어요 !



출처 : http://ccami.tistory.com/tag/iptime공유기설정

 

WOL이란? 

Wake On Lan의 약자로 랜 케이블을 통해 컴퓨터를 키는 방법이에요.


데스크탑에는 항상 LAN케이블이 꼽혀 있으니까 컴퓨터는 대기를 하게 되고, 

랜 케이블로 컴퓨터를 키라는 신호를 보내게 되면 컴퓨터가 켜지는 방식~!


요즘 나오는 컴퓨터는 왠만하면 메인보드에서 다 지원을 해주고요~


공유기를 사용한다는 전제 하에, 

그리고 IPTIME 공유기를 기준으로 작성됩니다.



시작하기전에, CMOS로 들어가 봅니다.

메인보드마다 CMOS모양은 다르기 때문에...

LAN관련된 메뉴로 가서, 랜이 항상 Enable되 있도록 설정을 해 주고,

전원 관련된 곳이 있으면, 절전 관련 항목은 꺼 주시는 것이 좋습니다.

(절전 관련 항목이 켜있으면, 랜이 대기상태가 되지를 않아서 랜을 통한 신호를 받지 못해요)



윈도우로 들어온 후,

제어판 - 하드웨어 및 소리 - 장치관리자 - 네트워크 어댑터 - 속성

까지 갑니다.






제 네트워크 카드(랜카드)는 메인보드에 내장 되어 있는 것으로

흔한 Realtek PCIe GBE Family Controller 이고요, 드라이버는 윈도우 설치될 시 자동으로 설치되었습니다.





위에 CMOS설정에서 말했던 것 처럼 절전 관련 항목은 모두 비활성화 해야 합니다.


- Energy Efficient Ethernet : 사용안함

- Gigabit 자동 비활성화 (절전) : 사용안함

- Wake on Magic Packet : 사용

- Wake on pattern match : 사용

- 웨이크 온 랜 종료 : 사용

- 절전형 이더넷 : 사용안함


으로 설정을 해줍니다.

그냥, 전원관련 부분은 전부 비활성화 해주고, 

WOL 관련 항목은 모두 사용으로 해준다 생각하시면 되겠습니다.



이제 공유기 설정을 해야 겠죠?


인터넷익스플로러 (크롬 등) 을 킵니다.

공유기 환경설정으로 들어갑니다.

(기본주소 : 192.168.0.1)


관리도구 로 들어갑니다.



메뉴를 보면

고급설정 - 특수기능 - WOL 기능으로 들어가면

'위에 현재 접속된 PC의 MAC 주소로 설정' 이라는 항목이 있어요.

자동으로 접속한 컴퓨터의 MAC 주소를 검색하여 추가를 해주는 아주 편리한 기능!

눌러 주시면 자동으로 뜨고, PC설명을 넣어줍니다.

추가하면 아래 목록에 추가가 되고요~



이제

컴퓨터를 끕니다.



같은 네트워크에 있는 다른 컴퓨터에 가서 공유기 환경설정 페이지로 접속해요.

무선이건, 유선이건 상관 없어요.

스마트폰으로 무선랜을 연결해서 접속해도 상관 없어요.

(기본주소 : 192.168.0.1)


같은 페이지로 가서 (고급설정 - 특수기능 - WOL 기능) 

아까 설정한 컴퓨터 체크박스에 체크를 하고, 위에 PC켜기 버튼을 클릭하면 

아까 설정한 컴퓨터가 켜지는 것을 볼 수 있을거에요~





주의할 점은 컴퓨터가 비 정상적으로 종료 되었을 시

(전원버튼을 눌러 강제로 종료 했거나 전원 코드를 뽑았다거나)

하면 WOL이 작동을 안하구요,

컴퓨터, 공유기는 항상 전원이 연결 되어 있어야 겠죠!?




그러나, 같은 네트워크 에서만 가능하다면 WOL이 의미가 없겠죠...?

WOL을 활용 하려면, 집 밖에서 스마트폰 혹은 인터넷이 연결된 외부의 컴퓨터에서

집에있는 내 컴퓨터를 켜서 원격 데스크톱을 이용해 내 컴퓨터에 접속하여

어디서나 내 컴퓨터를 사용할 수 있는 환경!!!

을 만들고자 하는게 목적입니다.


외부에서 접속을 하려면 DDNS라는 것을 설정해 주어야 하는데요,

역시 IPTIME에서는 지원을 해주고 있습니다.

DDNS에 관해서는 Part 3. 외부에서 WOL을 이용하여 컴퓨터를 키는 방법

에서 언급 하도록 하겠습니다~




 

출처 : http://ccami.tistory.com/13 폭파당할지도 몰라서 일단 긁어오기...

 

윈도우7에서 원격 데스크톱 설정하는 방법 입니다 !!


원격 데스크톱은 어디서든 인터넷만 된다면 

1) 어디서든 본인의 컴퓨터에 접속을 할 수 있다는 장점이 있습니다. 

2) 접속하는 컴퓨터의 성능에 상관없이 본인의 컴퓨터의 성능을 사용할 수 있습니다.



설정하는 과정은 

1. 접속할 컴퓨터에 대한 설정

2. 공유기를 사용할 시 공유기 설정

3. 외부에서 WOL(Wake On Lan)을 사용하여 컴퓨터를 키는 방법

4. 외부에서 컴퓨터를 끄는 방법

으로 진행할거구요.


여기는 Part 1. 접속할 컴퓨터에 대한 설정 입니다.


설정해 주기 전에, 다른 컴퓨터에서 본인의 컴퓨터로 들어오려면 본인 확인이 필요하겠죠?

ID와 비밀번호를 먼저 설정해 줄게요.


실행을 켭니다.

(단축키 : 윈도우키 + R)

.

.

control userpasswords2 라고 입력 후 확인

.

.

.

.

추가 클릭

.

.

.

.

ID생성

.

.

.

.

비밀번호 설정

.

.

.

.

권한 설정

.

.

마치면 본인이 설정한 ID가 목록에 있을거에요.

.

.

.

그리고 시스템으로 갑니다.

(단축키 : 윈도우키 + Pause Break)

.

.

원격 설정 클릭

.

.

.

.

사용자 선택

.

.

.

.

추가

.

.

.

.

아까 생성한 ID를 넣어주고 확인을 누르면 완료됩니다.


이 과정까지가 원격 데스크톱을 연결하기 위해 연결될 컴퓨터에서 설정해야할 부분 입니다.



여기까지 설정을 하면 

공유기를 사용할 경우 : 내부 네트워크 에서는 다른 컴퓨터에서 본인컴퓨터로 접속이 가능해요!

공유기를 사용하지 않을 경우 : 외부에서도 접속이 가능해요!





내부 네트워크에서 접속방법


먼저 본인 컴퓨터의 IP를 확인해야 합니다.

실행 - cmd 입력

(단축키 : 윈도우 + R)

.

.

명령어 ipconfig 입력

.
.

.

.

IP주소 라고 떠있는 것이 본인 컴퓨터의 IP에요.

(여기서는 192.168.1.13)

--------------------------------------------------------------------------------

192.168.x.x로 시작하면 공유기를 사용하고 있는 경우이고 가상IP를 사용하는 중 이구요,

이 외의 다른 숫자 (14.32.xxx.xxx) 이런식으로 되어 있으면 공유기가 없는 경우에요.


가상IP를 사용하는 경우에는 외부 IP와 연결을 해서 외부에서 접속할 수 있도록 공유기에서 설정을 해 줘야 하구요, 그것은 Part 2에서 설명하도록 하겠습니다^^

--------------------------------------------------------------------------------


이 주소를 기억하시고

다른 컴퓨터에 가서

시작-모든 프로그램-보조프로그램-원격데스크톱 연결

(접속할 컴퓨터에서는 윈도우가 xp이건 7이건 상관이 없어요)



여기에 아까 본인 컴퓨터의 IP주소를 입력하면

아까 설정한 ID와 비밀번호를 넣는 창이 나올거에요.

입력 후 연결하면 짠 ! 하고 본인 컴퓨터가 화면에 나올거에요.

이때 당연히, 접속할 컴퓨터는 켜져있어야 하구요!



외부 네트워크에서 접속하려면 그냥 본인 컴퓨터 IP만 알면 외부에서 접속이 가능해요. 이때도 물론 컴퓨터가 켜져 있어야 겠지요!?






다음은 Part 2. 공유기를 사용할 시 공유기 설정 입니다.

공유기는 IPTIME 공유기를 기준으로 설명 할거구요.

죄송하지만 다른 공유기는... 모르겠지만 비슷 할 거에요.

See you at next Part !



예전 모 회사 프로그래머가 신의 한수를 알려주겠다고 memcpy를 한번 짜보라고 하시더군요..

그래서 그냥 생각나는데요 조금 노멀하게...

 

void MyMemcpy(void *dest, void *src, size_t len){

char *dest8 = (char*)&dest;

char *src8 = (char*)&src;

 

while(--len){

*dest8++ = *src8++;

}

}

 

했는데, 이거 봐서 님의 경력은 얼마 안되네요 ㅋㅋ 하시더군요

ㅡ_ㅡ...

 

그래서 조금 고친것이

dest메모리 영역과 src메모리 영역이 겹치는지 확인하는 코드를 넣었습니다.

bool MyMemCpy(void *dest, void *src, size_t len)
{
    char *dest8 = (char*)dest;
    char *src8 = (char*)src;

    /////////////////////////////////
    //dest ■■■■■              //1.dest 메모리 영역안에 src가 있거나
    //        src □□□□□
    //            dest ■■■■■  //2.src 메모리 영역안에 dest가 있으면 안됨
    /////////////////////////////////

    if((dest8 <= src8 //1검사
       && src8 <= dest8+len)
    ||(src8 <= dest8 //2검사
       && dest8 <= src8+len))
    {
        return false;
    }

    while(len--){
        *dest8++ = *src8++;
    }

    return true;
}

 

뭐 여기까지 하면 그래도 안전하지 않냐라는 생각이 들었습니다만...

 

최근 boost 라이브러리(mpl 프로그래밍)쪽을 공부하면서 이런 방법이 나오더군요..

#include <typeinfo>
#include <algorithm>
#include <iterator>
#include <memory>

#include <boost/test/included/prg_exec_monitor.hpp>
#include <boost/timer.hpp>
#include <boost/type_traits.hpp>

 

//기존의 copy와 차별화를 위한 네임스페이스
namespace opt{
    namespace detail{
        //이건 직접 대입시켜서 복사하는 방식
        template<typename l1, typename l2, bool b>
        l2 copy_imp(l1 first, l1 last, l2 out, const boost::integral_constant<bool, b>&)
        {
           while(first != last){
                *out = *first;
                ++out;
                ++first;
            }
            return out;
        }

 

       //memcpy를 이용하는 방식
       template<typename T>
       T* copy_imp(const T *first, const T *last, const boost::true_type&)
       {
            memcpy(out, first, (last-first)*sizeof(T));
            return out+(last-first);
        }
    }

 

    //실제 copy명령어
    template <typename l1, typename l2>
    inline l2 copy(l1 first, l1 last, l2 out)
    {
          //복사하는것의 타입을 알아내서
          typedef typename std::iterator_traits<l1>::value_type value_type;

 

    //l1에대해서 "C& C::operator=(const C&);" 와 같은 정의가 없다면
    //trivial_assignment operator 를 가지게 됨. 

    //하지만 컴파일러 능력상 이걸 알아내는건 제각각임;;;
    return detail::copy_imp(first, last, out, boost::has_trivial_assign<value_type>());

    }

}

 

/////////////////////////////////////////////////////////////////////////////////////////////////////

// 이 밑은 위의 소스를 테스트 하는 소스

const int array_size = 1000;
int   i_array_[array_size] = {0,};
const int ci_array_[array_size] = {0,};
char  c_array_[array_size] = {0,};
const char cc_array_[array_size] = {0,};

int *i_array   = i_array_;
const int *ci_array  = ci_array_;
char *c_array   = c_array_;
const char *cc_array = cc_array_;

const int iter_count = 1000000;

 

using namespace std;

int cpp_main(int argc, char* argv[])
{
    boost::timer t;
    double result;
 
    cout << "Measuring times in micro-seconds per "<< array_size << " elements processed" << endl;
    cout << "Testing copy... " << endl;
    cout << "  [some standard liberay version may already perform this optimisation.]" << endl;
  
    //////////////////////////////////////////////////////////////////////////
    //cache load
    opt::copy(ci_array, ci_array + array_size, i_array);

    //time optimised verstion
    t.restart();
    for(int i=0; i< iter_count; ++i){
        opt::copy(ci_array, ci_array + array_size, i_array);
    }
    result = t.elapsed();
    cout << "opt::copy<const int*, int*> : " << result << endl;

 

    //////////////////////////////////////////////////////////////////////////
    //cache load;
    std::copy(ci_array, ci_array + array_size, i_array);

    //time standard version
    t.restart();
    for(int i=0; i< iter_count; ++i){
        std::copy(ci_array, ci_array + array_size, i_array);
    }
    result = t.elapsed();
    cout << "std::copy<const int*, int*> : " << result << endl;

  

    //////////////////////////////////////////////////////////////////////////
    //cache load
    opt::copy(cc_array, cc_array + array_size, c_array);

    //time optimised verstion
    t.restart();
    for(int i=0; i< iter_count; ++i){
        opt::copy(cc_array, cc_array + array_size, c_array);
     }
     result = t.elapsed();
     cout << "opt::copy<const char*, char*> : " << result << endl;

 

     //////////////////////////////////////////////////////////////////////////
     //cache load;
     std::copy(cc_array, cc_array + array_size, c_array);

     //time standard version
     t.restart();
     for(int i=0; i< iter_count; ++i){
         std::copy(cc_array, cc_array + array_size, c_array);
     }
     result = t.elapsed();
     cout << "std::copy<const char*, char*> : " << result << endl;

  

     return 0;
}

 

메타프로그래밍은 프로그램 소스를 프로그래밍 하는 개념인데...

위의 메모리 복사 예제 처럼 C++의 템플릿을 가지고, 컴파일러가 타입에 따라 가장 적절한 알고리즘을 선택 할 수 있게 하거나

미리 상수 같은걸 프로그램 실행 시점에서 결정하지 않고 컴파일 시점에서 결정하게 하여

더 빠른 프로그램 속도를 갖게 하는 비법? 꼼수? 학문? 인거 같습니다.

 

진정한 신의 한수... orz....

 

문제는 내가 아직 이걸 프로젝트에 써먹으면서 머리로 이해 + 손으로 익어야 하는데.......

이 개념 자체가 난해하고 어려워서 자료도 그다지 많이 없고

그나마 boost로 익히는 메타프로그래밍 이라는 책을 사서 봤지만....

 

미국 책 스타일... orz...

그냥 개념만 쫙 ~~~ 설명됬고... 제가 멍청해서 그런지 개념 잡기가 너무 난해 하네요..

영어로 표현하면 보는 내내 so what? 이라는 느낌밖에 안왔습니다. ㅠㅠ

 

어쨋든.. 요즘 boost 쪽... 꽤 유용하고 재미있는 프로그래밍 방법론이라 생각하네요..

 

+ Recent posts