string strTempPath = Path.GetTempPath();


이거 쓰세요......

돌겠눼.......


.........................................................................................................................

사용자 계정 폴더 하위의 temp에 직접 임시파일을 기록할 일이 있다.

이 폴더는 윈도가 관리하는 폴더라 나중에 디스크 정리 때 같이 정리할 수 있으며,

윈도가 다중 사용자 계정일 상태에는 단일 사용자마다 temp가 따로 주어지므로 보안(?)이나 관리측면에서 용이한 면이 있다.


C#에서는 전역 클래스로 Environment클래스가 제공되며 이 클래스를 통해 실행되는 시스템의 OS관련 정보, 실행 프로그램에 대한 위치 등에 대한 관련 정보, 그리고 윈도가 제공하는 시스템 디렉토리등에 대한 정보들을 제공하는데 


보통 C:\Documents and Settings\{USERNAME}\ApplicationData 경로는 Environment.SpecialFolder의 열거자중에 골라서 리턴받을 수 있으며 다양하게 제공하기도 한다.


하지만  정작 {USERNAME}\Local Settings\Temp 의 경로, 즉 Temp 폴더는 열거자에서 찾아볼 수 없다.

그러나 다른 방법으로 Temp경로를 얻을 수 있는데


바로

Environment.GetEnvironmentVariable("temp");

을 통해 얻을 수 있다.

(이걸 그대로 출력하면 C:\Document~1\ ~~" 이런식으로 Dos에서의 출력처럼 8.3자 제한에 짤려서 출력이 된다(시샵 Console용으로 출력시. 그래서 아래를 참고)


위 메소드를 통해 

"C:\Documents and Settings\{USERNAME}\Local Settings\Temp"까지 얻을 수 있고 이걸 그대로 사용하면 파일로 인식되는 모호성이 발생하기 때문에 나는  


Path.GetFullPath(Environment.GetEnvironmentVariable("temp") + "\\");


로 static선언을 통해 리턴받아 사용한다.


그렇게 되면 정확하게 

"C:\Documents and Settings\{USERNAME}\Local Settings\Temp\"

이 출력되며, 그 뒤에 파일이나 하위 디렉토리를 추가하여 다른 작업을 할 수 있다.


Temp 의미상 임시로 즉각적인 임시파일의 기록이나 폴더를 사용하기 위한 용도로만 사용해야 맞는것이며 부팅하거나 다른 작업시 운영체제가 임의로 정리 가능한 권리를 가지는 폴더이기 때문에 파일의 일정기간의 저장을 위한 용도로는 사용하지 않는것이 좋다.


특정 프로그램에서 일정 기간의 저장, 예로 config.xml같은 실행시에만 초기에 프로그램의 환경설정 변수를 잡아주는 용도로 사용하는 파일을 저장할때는 C:\Documents and Settings\{USERNAME}\ApplicationData 같은 ApplicationData의 하위폴더에 대표하위폴더를 생성해서 그 안에서 작업하는것이 일반적이다.


한글 MSDN : http://msdn.microsoft.com/ko-kr/library/system.environment(v=vs.80).aspx (System.Environment 클래스) (.net v2.0)



요즘 좀 프로젝트 말미라 빡시게 돌아간다.


하면서 개인 스터디를 하고 있는데, 하면서 알게된 기초적인 프로그래밍 문법





다들 if문과 switch문이 비슷한 용도로 쓰이는것을 알것이다.

물른 다르지만 비슷하다.


즉 조건식으로 분기를 하기위해 사용되는데 개발자에 따라, 회사간의 정책에 따라 사용하는 방법은 다 다르겠지

Whatever!


나는 vs2005를 사용(.Net 2.0)


if문과 switch문에서 int a = 10을 주고

if( a == 0) ~

else if (a == 1) ~

else if (a == 2) ~

else if (a == 3) ~

~~~


이렇게 흘러가는데 만약 조건에 맞는 식이 저 밑에 있다고 치면 if문을 위에서부터 하나씩 전부 검사하고 내려온다.

이것을 어셈블리어로 확인할 수 있다.


if문에 진입하기 직전에 BreakPoint를 걸고 실행하면 if문앞에서 걸리면서 소스가 나올것이고,

소스화면에서 마우스 오른쪽 -> Go to Disassembly를 통해 확인할 수 있다.


대충 보면(나도 어셈블리어는 모른다 갸초보라 ㅠㅠ) jmp가 그 주소로 이동한다는  소리인데,

if문은 각 else if 문이 끝나는 지점에서 다음 else if 문의 주소로 jmp를 한다.(왜 jmp명령어를 사용하는지는 어셈블리어를 몰라서 모름. return 도 아닌데..)

if문은 이런식이고.....


switch문도 BreakPoint를 직전에 걸고 실행한 후 Disassembly를 통해 보면 switch인 조건식 검사 구문에서 다음 첫 case를 넘어가기 전까지 여기서 조건을 검사한 후 바로 해당 case로 넘어간다. case가 없으면 default가 지정되어 있으면 거기로 넘어가고  아니면 switch문 밖으로 jmp해버린다.


이것이 바로 if문과 switch문의 차이이기 때문에 실제 실행 속도면에서도 조건식이 많을경우 switch문이 빠른것을 알 수 있다.


현재 구상해둔 부분에 대해 기획만 하고 전혀 프로그래밍을 하지않고 있다...


구상은 많다.

다른사람들이 생각이 많은 것처럼 나도 생각해둔 부분이 많고, 기획해둔 부분이 많다.

그래서 어느정도 도식화 시킨것도 있긴 하지만, 이걸 다 할수는 없을것 같고(내 기술이 딸려서 그런것도 있고, 시간도 부족하다),

뭔가 우선순위를 두고 시작은 해봐야 할것 같다.


회사에서 C#으로 새로운 프로젝트를 하나 시작하려 하는것 같은데, 그에 대한 공부와, 프로젝트가 시작되면 거기에 완전 집중해야 하기 때문에 따로 시간을 내기는 어려울 것이다.

제발 뭔가라도 해야하는데....


저번에 시작했었던 후킹 프로그램은 또 귀찮아서 안하고 있따 ㅠㅠ

뭔가 체계적으로 만들어 진 것도 아니고 C#으로 만들다 보니 닷넷과의 연결이 불확실한 xp에서는 작동이 제대로 되지 않는것도 있는것 같아 조금 불안하다.


어쩃든 시작합시다!!! ㅋ


무슨 키가 입력되는지
몇번 입력됐는지
마우스의 유효픽셀 이동거리는 얼마인지
-> 이거슨, 문제가 있는게, 1920x1680모니터에서 화면 끝으로 마우스를 한번에 빨리 움직이면 1680픽셀이 다 인식이 되는것이 아님. 하지만 천천히 움직이면 다 인식됨

 c#으로 만들었고,
윈도xp에서는 트레이로 축소시키면 몇초간의 딜레이가 있음
윈도7 에서는 딜레이 없이 작동 잘 되는듯


차후예상 추가기능 
마우스 클릭 세기
키보드의 키중 제일 많이 입력된 키 랭크 매기기
마우스 픽셀 이동거리 통한 모니터 크기를 받아서 실제 이동거리를 구하기(하루에 몇 m를 갔니 이런거)
 

ClicknTouch.exe

이 글은 C++기초플러스(5판)에서 발췌한 글입니다. 
 
실전 프로그래밍 : 조건 표현식의 연산자와 버그 예방법

'같다' 연산자(==)를 사용할 곳에 대입 연산자(=)를 입력하는 실수를 없애기 위하여,
많은 프로그래머들이 더 직관적인 표현인 'variable == value' 를 'value == variable'로 뒤집어 사용하고 있다.
예를 들면, 조건을 다음과 같이 입력하면

 if (3 == nCount)

바르게 동작한다. 그러나 실수로 다음과 같이 입력하면

if (3 = nCount)

리터럴에 어떤 값을 대입하여는 시도로 간주되어 컴파일러가 에러 메시지를 내보낼 것이다.
(3은 언제까지나 3일 뿐이며, 다른값을 대입할 수 없다.) 
그러나 'variable == value'형식을 사용하면서 다음과 같이 == 대신 = 를 입력하는 실수를 범했을 때에는 

if (nCount  = 3)

컴파일러가 nCount에 무작정 값 3을 대입할 것이고, 이 조건은 참이되어 if의 true 블록을 실행할 것이다.
이것은 매우 흔하게 발생하는 에러이지만 찾아내기가 무척 어렵다.
일반적으로, 컴파일러가 에러를 쉽게 찾을 수 있도록 프로그램을 작성하는 것이 찾기 어려운 에러를 만들어 놓고 이를 고치느라 애를 먹는것보다 훨씬 낫다. 

=======================

요약할께요.
if문 쓸때 'if ( nCount == 3)' 이렇게 쓰는것보다 'if (3 == nCount)로 쓰는버릇을 들이는게 좋다 입니다. 

if (nCount = 3) 으로 하면 문법적으로 문제가 없기 때문에 에러검출이 되지 않습니다.
학생분들이야 코드 몇줄 안되지만, 실무로 가면 이걸 일일히 찾아서 수정하기는 어려운 일입니다. 
 
예로 (출력부분에서 예가 잘못되었지만 조건식을 중점으로 든 예이므로 이해 부탁드립니다)

int MyAge = 20;
if (MyAge = 28)

    cout << "내 나이는 28 이다" << endl;

else
{
    cout << "내 나이는 20 이다." << endl;
}

이렇게 하면
"내 나이는 28이다" 가 출력되어 버립니다. 의도에 맞지 않는거죠.
if문에서 '='을 두번 넣는걸 실수로 한번 넣어서 생긴 오류입니다. 하지만 문법적으로 문제는 없죠.
컴파일러가 에러를 잡아주지 않기 때문에 뭐가 문제지? 하면서 오랜시간 디버깅을 해야할수도 있고, 재수좋아서 한방에 끝낼수도있습니다만, 애초에 에러를 안내기 위해서는

int MyAge = 20;
if ( 28 == MyAge)

    cout << "내 나이는 28 이다" << endl;

else
{
    cout << "내 나이는 20 이다." << endl;
}

로 하면  if문의 조건식에서 false를 리턴하기 때문에 if문 안으로 들어가지 않습니다. 그래서 "내 나이는 20 이다"가 출력되는게 정상이죠.

즉, 변경할수 없는 값, 상수값을 앞에 둬야 실수로 '='으로 입력했더라도 컴파일러 수준에서 에러를 검출해 줄수 있습니다. 

ps. 언어마다 다릅니다. java같은 경우는 c와 다른 조건식의 경우를 가집니다.
java는 if문의 조건식에서 대입을 할수 없는것으로 알고있습니다.
이 글은 c와 c++의 경우로 한정하고 있습니다.(제가 아는 범위 한정입니다. 제가 틀렸을경우 신속한 지적 부탁드립니다
삽질하다 결국 ㅈㅈ 쳤는데 알고보니 다 왔었다 참나 ㅋㅋㅋㅋ

솔루션 하나를 만들고, MFC용 프로젝트와 DLL을 만들 DLL프로젝트를 만든다.
그리고 MFC에 DLL과의 연결 속성들을 알아서 정해준다. (뭐 그런것들... Projects Dependencies...zz)
그런것들은 알아서 정해주고 이제 각 DLL을 구성하는 헤더들에 같은 선언들을 해준다.

//Component.h
#ifdef DLLCOMPONENT
#define CCOMPONENT __declspec(dllexport)
#else
#define CCOMPONENT __declspec(dllimport)
#endif

class CCOMPONENT CComponent{ ~~~~~~~};
 
//Component.cpp
#define CCOMPONENT //이건 해주는지 안해주는지 까먹었다. 알아서 하셈
#include <iostream> 
~~~~ 

이런식으로 선언을 모든 DLL구성 파일들에게 해줘야 한다. "똑같이"
즉, DLL로 만들 클래스들을 저런식으로 똑같이 선언해주면 된다는 거다.

젠장.....
난 클래스마다 다르게 했더만 아니라네? ㅠㅠ
클래스 이름이 달라서 다르게 구분지어 줬더만 똑같이하라니 이런 된장 ㅠㅠㅠㅠㅠ 

추가. 이거 삽질한다고 각종 리크에러들 다 나왔음 ㅠㅠ 
출처 : http://nicejinux.net/bbs/zboard.php?id=lecture&no=66
-- 감사합니다

using System;        
using System.Diagnostics;        
using System.Windows.Forms;        
using System.Runtime.InteropServices;        

class InterceptKeys        
{        
        private const int WH_KEYBOARD_LL = 13; 
        private const int WM_KEYDOWN = 0x0100; 
        private static LowLevelKeyboardProc _proc = HookCallback;        
        private static IntPtr _hookID = IntPtr.Zero; 

        public static void Main()        
        {        
                _hookID = SetHook(_proc);        
                Application.Run(); 
                UnhookWindowsHookEx(_hookID);        
        }        

        private static IntPtr SetHook(LowLevelKeyboardProc proc) 
        {        
                using (Process curProcess = Process.GetCurrentProcess()) 
                using (ProcessModule curModule = curProcess.MainModule)        
                {
                        return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); 
                }        
        }        
        
        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);        
        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
        {        
                if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
                {        
                        int vkCode = Marshal.ReadInt32(lParam);        
                        Console.WriteLine((Keys)vkCode); 
                }        
        
                return CallNextHookEx(_hookID, nCode, wParam, lParam); 
        }
        
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);   
        
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
        [return: MarshalAs(UnmanagedType.Bool)] 
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);   
        
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); 
        
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
        private static extern IntPtr GetModuleHandle(string lpModuleName);  
}


콘솔어플리케이션으로 만들고 system.window.form하나 추가해주고 
프로젝트 만들때 MFC_Test라는 이름으로 만들었다면 MFC_TestDlg.cpp파일에서 #include 부분 바로 다음에 이걸 추가하시고
#ifdef _DEBUG
#pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console")
#endif
다음에 본인이 필요한 부분에
printf("인덱스 값은 %d" , m_nIndex); 
를 추가해서 컴파일 하면 어플리케이션 창과 콘솔창이 동시에 뜨는것을 확인할수 있을것이고,
입력이나 수정, 삭제시마다 실시간으로 확인이 가능합니다.


ps. 음하하하하 한문장으로 다 썼다 ㅋㅋㅋ
먼저 VS2003으로 작성.
기본적인 MFC 어플리케이션 프로젝트로 생성 후 
Edit Control을 두개 넣고 이름 지정(IDC_EDIT1,2로 지정)해주고,
확인으로 지정해줄 버튼을 생성 후 두번 클릭하면 자동으로 OnBnClickedButton1()이 생성된다. (IDC_BUTTON1)


그리고 그것에서

GetDlgItemText(IDC_EDIT1, m_str1); 
GetDlgItemText(IDC_EDIT2, m_str2);  

MessageBox(""아이디는 : " + m_str1 + "\n" + "비밀번호는 : " + m_str2, "입력한 값", MB_OK);

으로 입력한 후 실행하면 됨.

ps. m_str1, m_str2는 CString으로 미리 선언해뒀음 
int main()
{
CComponent* pComponent = new CComponent("My Component");
  
        //1. 객체로 인자를 넘길때(1번을 한다면 2번을 주석처리하세요)
        pComponent->AddParameter(CParameter("Test1"));
pComponent->AddParameter(CParameter("Test2"));
pComponent->AddParameter(CParameter("Test3"));
pComponent->AddParameter(CParameter("Test4"));
pComponent->AddParameter(CParameter("Test5"));
pComponent->AddParameter(CParameter("Test6"));
pComponent->AddParameter(CParameter("Test7"));
//////// 

 
       //2. 포인터로 인자를 넘길때(2번을 한다면 1번을 주석처리하세요)
for (int i = 0; i < 6; i++)
{
pComponent->AddParameter(CParameter("Test"));
}
//////// 
int nSize = pComponent -> GetParameterSize();
        for (int i = 0; i < nSize; i++) //객체로 넘길때입니다. 포인터로 넘길시에 "GetParameterAt(i)->"로 변경.
        //아래의 포문도 동일
{
cout << i+1 << " " << pComponent->GetParameterAt(i).GetName() << endl;
}
cout << endl;

cout << "3번째 객체를 삭제합니다" << endl;

pComponent->DeleteParameterAt(3);
cout << endl;
nSize = pComponent -> GetParameterSize();
for (int i = 0; i < nSize; i++)
{
cout << i+1 << " " << pComponent->GetParameterAt(i).GetName() << endl;

}
cout << endl;

delete pComponent;

return 0;
}


헤더파일 분리
Component.h , Parameter.h, BaseEntity.h 로 분리후 Parameter클래스는 BaseEntity클래스를 상속받음.
BaseEntity클래스는 "Test1", "Test2" 같은 문자를 입력받습니다.(멤버변수가 'char* 변수명'임) 
Component클래스는 Parameter객체들을 배열형태로 관리 합니다.

구현해보시고 제가 만든거하고 비교해보세요 

+ Recent posts