달력

4

« 2024/4 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2009. 5. 27. 17:03

C#에서 Win32 API 사용하기 Programing/Windows Programing2009. 5. 27. 17:03


개요

Win32 API를 불러올 때, 함수의 명칭, 인자, 리턴 값을 가지고 불러오게 되어 있다. 하지만, C#에서 타입들이 모두 객체(Object)의 형식이며, 일반적인 C 의 데이터 형과 상이한 모양을 가진다. 이러한 문제들을 해결할 수 있는 것이 PInvoke 기능이다.

 

PInvoke( Platform Invocation Service)는 관리화 코드에서 비관리화 코드를 호출할 방법을 제공한다. 일반적인 용도는 Win32 API의 호출을 위해 사용한다.

 

namespace PinvokeExample

{

using System;

 

             using System.Runtime.InteropServices; // 반드시 입력해야 한다.

 

             public class Win32

             {

                           [DllImport(user32.dll)]

                           public static extern int FindWindow(string a, string b);

                          

             }

}

 

위 예제는 FindWindow라는 user32.dll C함수를 사용하는 모습을 보여주고 있다. 실제 FindWindow의 선언은 다음과 같다.

 

             HWND FindWindow(LPCSTR swClassName, LPCSTR swTitle);

 

HWND는 윈도우 핸들을 표현하는 32비트 정수 이므로, int형으로 치환되고 LPCSTR 형은 NULL로 끝나는 문자열을 표현한다. 이때 PInvoke string을 자동으로 LPCSTR로 치환해 주는 역할을 하게 된다.

이 문서에서는 이처럼 Win32 API 함수의 여러 유형들을 어떻게 C#에서 사용 할 것인지에 대하여 알아보자.




 

출처 : 데브피아

:
Posted by Lunaness
VS2005를 실행하면 각종 정보들이 시작 페이지에서 나타난다
그중에 이번 Windows7의 애플리케이션 개발시 관련 호환성에 대한 정보를 다음과 같이 나왔다

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

Windows에서 동작하는 소프트웨어를 개발하는 분들이 Windows 7, Windows Server 2008 R2 호환을 고민할 때 볼만한 문서가 있어 나누고자 합니다. 문서 목적은 애플리케이션이 Windows 7 혹은 Windows Server 2008 R2에 문제없이 동작하는데 필요한 호환성 관련 사항을 전달하려는 것입니다. 문서 이름은 “Windows Application Quality Cookbook”입니다. 문서는 http://code.msdn.microsoft.com/Windows7AppQuality에서 내려받을 수 있습니다. 지속적으로 수정될 예정이고, 버전 1.1 문서는 이 포스트에 첨부했습니다. 이 문서에는 Windows XP에서 Windows 7으로 바로 옮겨가는 것은 고려되지 않았습니다. 애플리케이션을 Windows XP에서 Windows Vista 옮기는 것은 http://msdn.microsoft.com/en-us/library/bb757005.aspx를 참조하시기 바랍니다.

 

1. 운영체제 버전

  운영체제 버전이 올라가면 언제나 달라지는 것 중의 하나입니다. GetVersion 함수의 반환 값이 변화되었습니다.

2. Windows Mail 삭제

  이후에 Windows Mail 도구는 지원되지 않을 것을 명시했습니다. CoStartOutlookExpress API는 동작하지 않으며, 다른 메일 API deprecating 정보를 포함했습니다. 앞으로 지원 중단을 선언하지 않은 API는 전과 같이 동작합니다.

3. Internet Explorer 8 – 사용자 에이전트 문자열

  Windows 7에 포함된 Internet Explorer 버전은 8입니다. 웹 개발자가 개발하는 웹 애플리케이션이 사용자 브라우저 버전 혹은 정보에 따라 행동을 달리하는 경우에 사용자 에이전트 문자열 (User Agent String) 값을 다시 검토해야 합니다. 그리고, Internet Explorer 8은 Internet Explorer 7 compatibility view를 지원하기 때문에, 웹 개발자는 필요한 경우 Internet Explorer 7 compatibility view 상태를 판단할 수 있는 메타 정보도 확인해야 합니다.

4. 윈도우 휴대용 장치를 위한 WPDUSB.SYS 삭제

  커널 모드로 Windows Vista USB 드라이버 스택에서 동작한 WPDUSB.SYS WINUSB.SYS 드라이버로 교체되었습니다.

5. Microsoft Message Queuing (MSMQ) – SHA-2 사용

Windows 7에 포함된 MSMQ는 보안 강화를 목적으로 메시지를 보낼 때, SHA-2를 기본으로 이용합니다. 다른 설정에 변화가 없다면 Windows 7 MSMQ에서 만들어진 메시지는 하위 버전에서 받아볼 수 없습니다. 반대도 마찬가지입니다.

6. 바이너리 간의 기능 이동

이후의 기능 효율성과 구조 향상을 위해 Windows 핵심 바이너리 사이에 기능 이동을 했습니다. 예를 들어, kernel32.dll advapi32.dll에서 동작하던 기능을 kernelbase.dll로 옮긴 것입니다. 백신/백업 소프트웨어 같이 하층의 API를 직접 다루는 개발자 분들은 주의 깊게 보실 필요가 있습니다.

7. (Windows Server 2008 R2에만 적용) Microsoft Message Queuing (MSMQ) – Windows 2000 클라이언트 지원 삭제

Windows 2003, 2008 도메인에서 Windows 2000 클라이언트 지원은 선택 사항이지만, Windows 7 도메인에서는 Windows 2000 클라이언트를 지원하지 않습니다.

8. (Windows Server 2008 R2에만 적용) 64-bit 지원

Windows Server 2008 R2 64-bit 제품만 지원합니다. 32-bit 드라이버, 32-bit 플러그-, 16 bit 실행 바이너리만 지원하는 제품을 개발하시는 분들은 미리 준비를 하셔야 합니다. WoW64, x86 emulator가 있기는 하지만, 모든 32 bit 애플리케이션이 동작하는 것은 아니므로 개발자 분들은 세부적인 요건을 조사해서 어떻게 대처할지를 결정해야 합니다.

9. (Windows Server 2008 R2에만 적용) Server Core에서 Wow64 지원은 선택 사항

Windows Server 2008 R2에서 Server Core를 설치하는 경우 Wow64는 디폴트에 포함되지 않습니다.

 

[새로운 기능과 개선 사항]

1. 파일 라이브러리

  라이브러리는 여러 군데로 흩어져 있는 폴더를 묶어 하나로 보일 수 있도록 하고, 인덱싱을 통한 빠른 검색과 원격 접속 방법을 제공합니다. Windows 7에서 달라진 것은 파일 다이얼로그에서 열기, 저장하기를 수행할 때 디폴트로 나타나는 곳이 문서 폴더에서 문서 라이브러리로 바뀐 점입니다. 그리고 라이브러리의 성질은 폴더가 아니라 파일이기 때문에, IFiledialog를 이용하는 경우 GetFolder, GetFilename을 이용하는 대신에 GetResult를 사용해야 합니다. 애플리케이션 개발자는 IShellLibrary 인터페이스를 이용해 필요에 따라 특정 폴더를 라이브러리에 추가할 수 있습니다.

2. 사용자 인터페이스 높은 DPI 인식

 목적은 텍스트와 이미지 크기를 변경하고자 화면 해상도 (screen resolution)을 이용하는 것보다 DPI를 사용하는 것을 권장하려는 것입니다. 추가된 기능은 사용자 단위의 DPI 설정과 로그-온만으로 변경된 DPI를 적용하는 것입니다. 사용자 인터페이스 측면에서 글자, 폰트, 이미지를 다루어야 하는 경우에 유심해 볼 필요가 있습니다.

3. Internet Explorer 8 – Data Execution Protection/NX

  이 기능 변화는 Windows 7만이 아니라 Internet Explorer 8이 설치되는 모든 곳에 공통으로 적용되는 것입니다. Internet Explorer에 추가 기능으로 설치되는 모듈 중에 금융권에서 사용하고 있는 ActiveX처럼 하단의 운영체제를 직접 다루는 ActiveX와 같은 것을 개발하는 분들이 반드시 확인하셔야 할 사항입니다. 기본 개념은 Internet Explorer 8의 추가 기능으로 설치된 모듈이 메모리에 올라가서 실행될 때, 운영체제가 판단해서 heap, stack과 같은 영역에서 코드가 수행되는 것은 디폴트로 막겠다는 것입니다. 목적은 buffer overflow와 같은 보안 침해를 예방하는 것입니다. 일반 개발자 분들은 이런 코드가 있는 지도 갸우뚱하실 것입니다. 생각할 수 있는 대처 방안은 Internet Explorer 추가 기능 모듈을 DEP/NX 호환 ATL 프레임워크 같은 것을 이용해서 재작성하거나, Internet Explorer를 관리자 권한에서 실행해서 DEP/NX를 동작하지 않게 하는 것입니다.

4. 사용자 인터페이스 – UAC (User Account Control) 다이얼로그

  UAC (User Account Control) 기초 구조는 변경되지 않았습니다. 크게 달라진 점은 UAC 다이얼로그 상자에서 선택할 수 있는 선택이 “Yes”, “No”로 줄어든 것과 같은 단순화입니다좀 더 세부적인 설명은 Windows 7 engineering blog 또는 Koalra 추천합니다.

5. ChooseFont() win32 공통 다이얼로그

  영향도가 크지는 않습니다. 애플리케이션에서 폰트를 선택하는 다이얼로그에서 WYSIWYG 개념에 따라 폰트 특성을 볼 수 있도록 바뀐 것과 Windows 지역 설정에 따라 필요 없다고 추정되는 폰트는 보이지 않도록 한 것입니다.

6. 애플리케이션 매니페스트 호환성

Windows 7에서는 애플리케이션 매니페스트에 “CompatiblityInfo.”을 넣었습니다. Windows 7에서 실행되지만 동작 방식을 Windows XP 혹은 Windows Vista처럼 하게 하는 것입니다. 모든 동작을 이전 환경으로 하는 것은 아니고 아래와 같은 컴포넌트가 대상입니다.

Desktop Windows Manager: Fail/Lock bit blitting

RPC exception handling

API: ReadFileEx

RPC: Thread pool management

:
Posted by Lunaness

다이얼로그 기반 프로그램에서 DoModal 호출로 윈도우가 보이게 된다

ShowWindow(SW_HIDE)를 써도 안먹히기는 마찬가지....

OnInitDialog()에 아래와 같이 ShowWindowEx() 메소드를 넣어주면 된다

    ShowWindowEx(SW_HIDE);

그리고 윈도우 메시지 헨들러 중 WM_WINDOWPOSCHANGING을 추가하여 넣어주면 된다

아래는 원문...

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

아래와 같이 WM_WINDOWPOSCHANGING 메시지 핸들러에서 들어오는 구조체의 플래그를 설정하면 DoModal()로 설정하더라도

윈도우가 보이는 것을 방지할 수 있다.

일단 m_bShowFlag 값에 따라서 변경하면 되고... m_bShowFlag 값은 ShowWindowEx() 함수를 다시 만들어서 그안에서 설정하도록 하면 됩니다. ShowWindow() 함수가 가상함수가 아니라서 어쩔 수 없이 새로 정의한 함수를 사용해야 합니다.

void CHidDlgDlg::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) 
{
CDialog::OnWindowPosChanging(lpwndpos);

// TODO: Add your message handler code here
if(m_bShowFlag)
lpwndpos->flags |= SWP_SHOWWINDOW;
else
lpwndpos->flags &= ~SWP_SHOWWINDOW;

}

BOOL CHidDlgDlg::ShowWindowEx(int nCmdShow)
{
m_bShowFlag = (nCmdShow == SW_SHOW);
return (GetSafeHwnd()) ? ShowWindow(nCmdShow) : TRUE;
}
출처: http://www.gosu.net/GosuWeb/Article-detail.aspx?ArticleCode=473
출처: 데브피아
그럼 이만...
:
Posted by Lunaness

제목은 거창합니다만....

알고보면 간단한거라는 -ㅂ-ㅋ

 

   1: void CFileSearch::GetFileList( CString strFolder)
   2: {
   3:  
   4:   // 파일 탐색 필터 정의 - Ini에서 확인 - 변경할 것
   5:     CString strMusicFilter = ".MP3.OGG.WMA.WAV";
   6:     CString strMovieFilter = ".AVI.WMV.MKV.MPEG.MPG";
   7:     CString strImageFilter = ".JPEG.JPG.BMP.PNG.GIF";
   8:     CString strDocumentFilter = ".TXT";
   9:  
  10:     CFileFind file;
  11:     BOOL b = file.FindFile(strFolder + "\\*.*");
  12:     CString strFolderItem, strFileExt, strTempString;
  13:  
  14:     CString strTempPath;
  15:     strTempPath = GetSpecialFolderPath(CSIDL_HISTORY);
  16:     strTempPath = strTempPath.Left(strTempPath.ReverseFind('\\')) + "\\Temp";
  17:  
  18:     while(b)
  19:     {
  20:         b = file.FindNextFile();
  21:  
  22:         if(file.IsDirectory() && !file.IsDots())
  23:         {
  24:  
  25:             strFolderItem = file.GetFilePath();
  26:  
  27:             // 사용하지 않는 시스템 폴더들은 탐색에서 제외한다
  28:              if (
  29:                  strFolderItem.Find(GetSpecialFolderPath(CSIDL_WINDOWS))                > -1            ||
  30:                  strFolderItem.Find(GetSpecialFolderPath(CSIDL_INTERNET_CACHE))        > -1        ||
  31:                  strFolderItem.Find(GetSpecialFolderPath(CSIDL_HISTORY))                > -1            ||
  32:                 strFolderItem.Find(GetSpecialFolderPath(CSIDL_COOKIES))                > -1             ||
  33:  
  34:                  strFolderItem.Find(GetSpecialFolderPath(CSIDL_COMMON_APPDATA))        > -1           ||
  35:                 strFolderItem.Find(GetSpecialFolderPath(CSIDL_APPDATA))                > -1   ||
  36:                  strFolderItem.Find(GetSpecialFolderPath(CSIDL_LOCAL_APPDATA))        > -1         ||
  37:  
  38:                  strFolderItem.Find(GetSpecialFolderPath(CSIDL_PROGRAM_FILES))        > -1        ||
  39:                 
  40:                 strFolderItem.Find(strTempPath)                                        > -1    )
  41:              {
  42:                 
  43:                 TRACE("제외 : %s\n", strFolderItem);
  44:                 continue;
  45:              }    
  46:  
  47:             //하위폴더를 검색하는 조건이면 재귀호출 발생
  48:             if (m_bSearchSubFolder)
  49:                 GetFileList(strFolderItem);
  50:         }
  51:  
  52:         strFolderItem = file.GetFilePath();
  53:         strFileExt = strFolderItem.Mid(strFolderItem.ReverseFind('.'));
  54:         strFileExt.MakeUpper();
  55:         
  56:         // 파일 탐색 필터 정의에따라 해당 StringList에 추가
  57:         if (strMusicFilter.Find( strFileExt , 0) > -1 && !file.IsDots())
  58:         {
  59:             m_strlistMusic.AddTail(strFolderItem);
  60:         }
  61:         else if (strMovieFilter.Find( strFileExt , 0) > -1 && !file.IsDots())
  62:         {
  63:             m_strlistMovie.AddTail(strFolderItem);
  64:         }
  65:         else if (strImageFilter.Find( strFileExt , 0) > -1 && !file.IsDots())
  66:         {
  67:             m_strlistImage.AddTail(strFolderItem);
  68:         }
  69:         else if (strDocumentFilter.Find( strFileExt , 0) > -1 && !file.IsDots())
  70:         {
  71:             m_strlistDocument.AddTail(strFolderItem);
  72:         }
  73:     }
  74: }

 

프로그램을 진행하다 보니 특정 파일들을 검색하는 일이 생겼는데..

CFileFind를 이용하면 무척이나 편하다 'ㅂ'b

:
Posted by Lunaness
유니코드에서 한 문자가 Little-Endian또는 Big-Endian으로 정의 되는 것을 볼 수 있다
이는 시스템상의 사용하는 문제로 가끔 변환해 줄 필요가 있는데....

네트워크 관련 API가 있지만, 해더 파일을 넣어줘야 한다는 이유 하나만으로 쓰기가 싫어졌다 -ㅂ-ㅋ

void Trans_Endian(WCHAR *uni)
{
    int nSize = WideCharToMultiByte(CP_UTF8, 0, uni, -1, NULL, 0, NULL, NULL);

    for (int n = 0; n<nSize; n++)
     {
        // UTF-16 little Endian -> Big Endian
        WCHAR high_bit = 0x0000, low_bit = 0x0000;
        high_bit = (*(uni+n) & 0xFF00) >> 8;
        low_bit = (*(uni+n) & 0x00FF)  << 8;

        WCHAR p = low_bit | high_bit;
            
        if (p == 0x00cd) break;
        *(uni+n) = _T(p);
            
     }

}

이것으로 간단하게 해결~!



:
Posted by Lunaness