[C#] Dokan 소스 (Ndrive) - 1

개발 노트/C#  2012.10.11 18:20



안녕하세요. 개발자 명월입니다.

이번 포스팅에서는 Dokan 소스에 대해서 알아보도록 하겠습니다. 저도 아직은 100% 이해하는 상태는 아니지만 소개가 제대로 될지 의문입니다. ^^;

어쨋든 이 소스를 공유해서 다 같이 연구해보는 걸로 하고 간략하게 소개하겠습니다.

 

Dokan은 흔히 우리가 자주 사용하는 Ndrive 에서 사용하는 시스템과 같습니다.

즉 FTP 를 마치 네트워크 드라이브 처럼 사용하는 시스템을 말합니다.

 

Dokan은 일본의 Hiroki Asakawa 개발자가 개발한 것입니다. 우리가 사용하는 Directory System 은 커널 개발영역이므로 C#으로는 개발하기 어렵습니다. ( 프레임워크의 영역을 벗어나기 때문입니다.)

그리고 window 커널은 공개적이지 않기 때문에 C++로 개발한다고 해도 애로사항이 많은게 현실입니다.

그러나 Dokan은 이 커널 을 모듈로 만들어 놨기 때문에 우리는 사용하면 되곘습니다.

 

Dokan 홈페이지 들어가서 확인 해보겠습니다.

바로가기 - Dokan 홈페이지 (위로 가면 English 버전이 있습니다.)

 

 

Dokan 예제 소스 - CodeProject 바로가기

 

 

Dokan 설치파일 - dokaninstall_053.exe

Dokan 예제소스 - Dokan.Mem_src.zip

 

여기까지 소개가 끝나고 소스 설명하겠습니다.

여기서 소스는 크게 두 부분으로 나뉩니다.

 

먼저 Main 과 메시지같은 부분인 Operation 부분으로 나뉩니다.

 

Main

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Text;
  4 using System.Windows.Forms;
  5 using System.ComponentModel;
  6 using System.IO;
  7 using System.Linq;
  8 using Dokan;
  9
10 namespace DokanTest_20121011_1
11 {
12     class Program : IDisposable
13     {
14         [STAThread()]
15         static void Main(string[] args)
16         {
17             new Program();
18             Application.Run();
19         }
20         BackgroundWorker _dokanWorker;
21         readonly static char _driveLetter = UtilityMethods.GetFirstAvailableDriveLetter();
22         public Program() {
23             _dokanWorker = new BackgroundWorker();
24             _dokanWorker.DoWork += new DoWorkEventHandler(_dockanWorker_DoWork);
25             _dokanWorker.RunWorkerAsync();
26         }
27         void _dockanWorker_DoWork(object sender, DoWorkEventArgs e)
28         {
29             DokanOptions option = new DokanOptions
30             {
31                 DriveLetter = _driveLetter,
32                 DebugMode = false,
33                 UseStdErr = true,
34                 NetworkDrive = false,
35                 Removable = false,
36                 UseKeepAlive = true,
37                 ThreadCount = (ushort)(System.Diagnostics.Debugger.IsAttached ? 1 : 0),
38                 VolumeLabel = "Myung"
39             };
40             DokanNet.DokanMain(option, new DokanOperation());
41         }
42         public void Dispose() {
43             _dokanWorker.Dispose();
44         }
45     }
46     internal static class UtilityMethods
47     {
48         internal static bool Exists(this string item)
49         {
50             return item != null;
51         }
52         internal static string GetPathPart(this string sourcePath)
53         {
54             return sourcePath.Substring(0, sourcePath.LastIndexOf('\\'));
55         }
56         internal static string GetFilenamePart(this string sourcePath)
57         {
58             return sourcePath.Substring(sourcePath.LastIndexOf('\\') + 1);
59         }
60         internal static char GetFirstAvailableDriveLetter()
61         {
62             var usedDriveLetters = from drive in DriveInfo.GetDrives() select drive.Name.ToUpperInvariant()[0];
63             string allDrives = string.Empty;
64             for (char c = 'D'; c < 'Z'; c++) allDrives += c.ToString();
65             var availableDriveLetters = allDrives.Except(usedDriveLetters);
66             if (availableDriveLetters.Count() == 0) throw new DriveNotFoundException("No drives available!");
67
68             return availableDriveLetters.First();
69         }
70     }
71 }
72

 

Operation

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using Dokan;
  6 using System.IO;
  7
  8 namespace DokanTest_20121011_1
  9 {
10     class DokanOperation : DokanOperations
11     {
12         const String ROOT_FOLDER = "\\";
13
14         public int Cleanup(string filename, DokanFileInfo info)
15         {
16             return DokanNet.DOKAN_SUCCESS;
17         }
18         public int CloseFile(string filename, DokanFileInfo info)
19         {
20             return DokanNet.DOKAN_SUCCESS;
21         }
22         public int CreateDirectory(string filename, DokanFileInfo info)
23         {
24             return DokanNet.DOKAN_SUCCESS;
25         }
26         public int CreateFile(string filename, FileAccess access, FileShare share, FileMode mode, FileOptions options, DokanFileInfo info)
27         {
28             return DokanNet.DOKAN_ERROR;
29         }
30         public int DeleteDirectory(string filename, DokanFileInfo info)
31         {
32             return DokanNet.DOKAN_SUCCESS;
33         }
34         public int DeleteFile(string filename, DokanFileInfo info)
35         {
36             return DokanNet.DOKAN_SUCCESS;
37         }
38         public int FlushFileBuffers(string filename, DokanFileInfo info)
39         {
40
41             return DokanNet.DOKAN_SUCCESS;
42         }
43         public int FindFiles(string filename, System.Collections.ArrayList files, DokanFileInfo info)
44         {
45             DirectoryInfo DI = new DirectoryInfo("D:\\Test");
46             FileInfo[] _fi = DI.GetFiles();
47             foreach (FileInfo item in _fi) {
48                 FileInformation fileinfo = new FileInformation();
49                 fileinfo.FileName = item.Name;
50                 fileinfo.Attributes = item.Attributes;
51                 fileinfo.LastAccessTime = item.LastAccessTime;
52                 fileinfo.LastWriteTime = item.LastWriteTime;
53                 fileinfo.CreationTime = item.CreationTime;
54                 fileinfo.Length = item.Length;
55                 files.Add(fileinfo);
56             }
57             return DokanNet.DOKAN_SUCCESS;
58         }
59         public int GetFileInformation(string filename, FileInformation fileinfo, DokanFileInfo info)
60         {
61             return DokanNet.DOKAN_SUCCESS;
62         }
63         public int LockFile(string filename, long offset, long length, DokanFileInfo info)
64         {
65             return DokanNet.DOKAN_SUCCESS;
66         }
67         public int MoveFile(string filename, string newname, bool replace, DokanFileInfo info)
68         {
69             return DokanNet.DOKAN_SUCCESS;
70         }
71         public int OpenDirectory(string filename, DokanFileInfo info)
72         {
73             return DokanNet.DOKAN_SUCCESS;
74         }
75         public int ReadFile(string filename, byte[] buffer, ref uint readBytes, long offset, DokanFileInfo info)
76         {
77             return DokanNet.DOKAN_SUCCESS;
78         }
79         public int WriteFile(string filename, byte[] buffer, ref uint writtenBytes,long offset, DokanFileInfo info)
80         {
81             return DokanNet.DOKAN_SUCCESS;
82         }
83         public int SetEndOfFile(string filename, long length, DokanFileInfo info)
84         {
85             return DokanNet.DOKAN_SUCCESS;
86         }
87         public int SetAllocationSize(string filename, long length, DokanFileInfo info)
88         {
89             return DokanNet.DOKAN_SUCCESS;
90         }
91         public int SetFileAttributes(string filename, FileAttributes attr, DokanFileInfo info)
92         {
93             return -DokanNet.DOKAN_ERROR;
94         }
95         public int SetFileTime(string filename, DateTime ctime, DateTime atime, DateTime mtime, DokanFileInfo info)
96         {
97             return -DokanNet.DOKAN_ERROR;
98         }
99         public int UnlockFile(string filename, long offset, long length, DokanFileInfo info)
100         {
101             return DokanNet.DOKAN_SUCCESS;
102         }
103         public int Unmount(DokanFileInfo info)
104         {
105             return DokanNet.DOKAN_SUCCESS;
106         }
107         public int GetDiskFreeSpace(ref ulong freeBytesAvailable, ref ulong totalBytes, ref ulong totalFreeBytes, DokanFileInfo info)
108         {
109             totalBytes = 20 * 1024 * 1024;
110             freeBytesAvailable = totalBytes - 0;
111             totalFreeBytes = int.MaxValue;
112             return DokanNet.DOKAN_SUCCESS;
113         }
114     }
115 }
116

 

여기서 주의 깊게 볼 부분은 getDiskFreeSpace 함수는 처음 데이터 크기를 결정하는 부분입니다. 그리고 처음 탐색기가 열릴때 사용하는 부분이 FindFiles 함수 입니다.

 

 

 

FindFiles 함수입니다.

 

 

 

제가 작성해 놓은 예제 소스입니다.

 

DokanTest_20121011_1.zip

 

(※ Dokan은 프레임워크 3.5 이상에서 작동합니다.)

 

여기까지 제가 알아본 내용입니다. 혹시 Dokan 에 대해 잘 아시는 분 있으면 가르침을 부탁드립니다. ㅜㅜ

 

그리고 요즘 개인 프로젝트가 너무 많아서 포스팅이 하나하나 밀리기 시작하네요.

Puzzle 게임도 하고 있고 Dokan, 스니퍼, 아직 포스팅은 하지 않았지만 웹서버 시스템 등등..

회사 일도 있고 개인 프로젝트도 하고 너무 정신이 없네요. (하나하나 마무리 짓고 가야 하는데...ㅜㅜ)

 

빠른 시일내로 정리해서 올려보도록 하겠습니다.

 

'개발 노트 > C#' 카테고리의 다른 글

[C#] 확장형 브라우져 AxWebBrowser Extended Browser(확장형 webbrowser)  (5) 2012.10.22
[C#] 퍼즐 게임 - 5  (5) 2012.10.19
[C#] 퍼즐 게임 - 4  (0) 2012.10.16
[C#] 웹서버 개발하기  (0) 2012.10.15
[C#] Dokan 소스 (Ndrive) - 1  (9) 2012.10.11
[C#] 퍼즐 게임 - 3  (0) 2012.10.10
[C#] 스니퍼  (2) 2012.10.09
[C#] 비프음  (0) 2012.10.06
[C#] 퍼즐게임 - 2  (0) 2012.10.05

댓글 9개가 달렸습니다.
댓글쓰기
  1. conrg
    2012.10.16 23:47 신고 |  수정/삭제  댓글쓰기

    저도 요새 dokan라이브러리로 개발을 하고 있는데요. 콜백함수를 어떤식으로 작성해야하는지 감이 안잡혀 너무 어렵습니다. 혹시 관련된 자료 얻을 수 있을까요?

    • 明月 v명월v
      2012.10.17 14:33 신고 |  수정/삭제

      안녕하세요... 저도 dokan 함수에 관심이 많이 있지만 네이버에도 보면 관련자료가 적어서 애를 먹고 있네요..ㅜㅜ
      일단 제가 만든것은 Callback 개념이 아닌 C#으로 이벤트 개념으로 접근하여 만든 것입니다. 아무래도 Callback 개념을 찾는 것을 보니 C언어로 작성하는 건 지요??
      저도 Dokan에 대해 안지 몇일 안되어 아는 정보가 적네요.
      이것 저것 연구 해 보다가 알게되면 포스팅을 해도록 하겠습니다. 감사합니다.

  2. 아차차
    2012.10.18 13:16 신고 |  수정/삭제  댓글쓰기

    안녕하세요.
    저도 요즘 N드라이브같은 가상 네트워크 드라이브 개발을 위해 소스를 뒤지다가 Dokan에 대해 알게되었고, 그 덕분에(?) 님의 블러그에도 와서 도움을 받았는데요..
    올려주신 DokanTest_20121011_1 소스 다운받아서 빌드후 실행해보니 오류가 나서 염치불구하고 이렇게 질문을 드립니다. ^^;;;; (제가 잘 몰라서 헤메고 있습니다.....)

    OS는 win7입니다 32bit
    1. DokanTest_20121011_1\bin\Debug\DokanTest_20121011_1.exe 파일 실행시
    ### Create 0014
    CreateDisposition 1
    CreateFile status = -1
    Create got unknown error code 1
    요런 오류가 반복적으로 14번 뜹니다.

    CreateFile 에서 오류가 나는것 같아 Return값을 DokanNet.DOKAN_SUCCESS 로 변경해 주어도 오류가 납니다. (GetFileinfo부분에서..)

    왜 그럴까요?


    2. 위의 오류가 발생해도 Myung(F:) 네트웤 드라이브는 생성됩니다.
    그런데... F: 를 클릭시 ...
    "위치를 사용할 수 없습니다. F:\를 액세스할 수 없습니다. 매개변수가 틀립니다"라는 오류가
    발생합니다.

    3. DokanNet.dll 버젼을 확인해보니 1.0.0.0 이던데
    제가 인터넷에서 찾은 것들은 0.6.0.0 이었습니다.
    혹시 1.0.0.0 소스를 가지고 계시면 공유좀 부탁드려도 될까요?

    4. 마지막으로 제가 웹쪽 프로그래밍만 하다가 이번일을 하게되었는데요
    아는게 너무 없어 삽질의 연속입니다.
    혹시 도움이 될만한 자료(인터넷 URL이나, 책 등등) 알고 계시면 추천좀 부탁드립니다.

    많이 바쁘신것 같은데 이런 장황한 글을 올려놓아 죄송하구
    미리 감사합니다.

    • 明月 v명월v
      2012.10.18 15:19 신고 |  수정/삭제

      아 추가적으로 그리고 윗 부분에 Dokan을 설치 해 주셔야 되요..
      C#은 직접적으로 커널 개발이 불가능 하니 그걸 연결해 주는 sys, driver 가 필요해요..

      즉 Naver ndrive처럼 Dokan을 프로그램에 녹일려고 하시면 C#이 아닌 C로 개발을 해야 맞습니다.

    • 明月 v명월v
      2012.10.18 15:22 신고 |  수정/삭제

      안녕하세요. 먼저 블로그 방문 감사드리구요...
      댓글 남기신건 염치가 아니고 너무 감사드려요. ^^*

      1.먼저 생성은 되나 클릭시 에러가 나는건 저도 상황이 어떤지 정확하게 몰라서 설명 드리기 뭐하나 DokanOperation.cs 의 FildFiles 의 디렉토리 설정은 제대로 되어 있는지 궁금합니다.

      현재 제 환경이 window 7이 아니라 제대로된 답변이 될지는 모르겠으나 디렉토리 권한 설정도 확인 부탁드립니다.

      2. 1번이 해결되면 2번도 해결 될 것 같습니다.
      3. 제가 만든 것은 CodeProject 에서 누가 만든것을 초기화 설정만 조금 바꾸어 놓은 정도 입니다. 블로그 상단에 원 소스도 첨부해 놓았습니다.

      4. Window와 시스템 개발을 생각하시는 것인지..
      가장 빠른 시간에 배울 수 있는 것은 역시 C# 이구요 우리가 사용하는 OS가 MS 이니 JAVA 스윙 보다는 MS 개열이 호환성이 가장 높아요.
      물론 안드로이드 공부하실려면 Java 개열이니 Java 쪽으로 가는게 맞구요.
      C#은 C# PROGRAMMING BIBLE WITH NET FRAMEWORK 3.0 을 추천합니다. 개인적으로 본 책중에 가장 정리가 잘 되어있어요.
      C 로 하신다고 하면 기본적인 C를 익히시고 바로 CAPI 책을 추천합니다. (MFC는 요즘 쓰지도 않을 뿐 더러 MFC로는 깊숙하게 들어가기 힘듭니다.)

      저도 아직 Dokan 은 개인적으로 많이 분석하고 있으나 쉽지가 않네요.
      아싸리 C++로 짜면 쉬울 것 같은데 C++로 하자니 시간이 없네요 ㅜㅜ

      어쨋든 방문 감사하구요.. 앞으로도 많은 방문 부탁드려요 ^^

  3. conrg
    2012.11.18 19:19 신고 |  수정/삭제  댓글쓰기

    안녕하세요. 제가 글쓴 날짜가 10월16일이네요. ㄷㄷㄷ

    4학년 졸업프로젝트하느라 독칸을 알게되었고, 지금은 완성을 했습니다 ㅎㅎ

    저도 외국인이 독칸으로 만든 Ram-Disk프로젝트를 분석해서 제 주제에 맞는 프로그램을 완성했어요. 그 외국인이 정말 잘 만들어 놨더라구요. 역시 양키.. 참고해보세요!!

    참고로 지금 상품화도 생각하고 있어서 코드공유는 힘들 것같습니다.ㅠㅠ

    궁금한 것이 있으면 conrg@네이버 메일로 주세요.ㅎ

    • 明月 v명월v
      2012.11.19 18:15 신고 |  수정/삭제

      잘 되셨으니 다행이네요...
      저도 따로 공부를 해야 하는데 개인적인 일정이 너무 빡빡해서 지금 블로그 포스팅 조차 못하고 있네요..
      어쨋든 관심 감사드리고요.. 앞으로도 많은 방문, 가르침 부탁드리겠습니다.

  4. 프로미
    2013.05.03 15:39 신고 |  수정/삭제  댓글쓰기

    윗 분 질문중에

    2. 위의 오류가 발생해도 Myung(F:) 네트웤 드라이브는 생성됩니다.
    그런데... F: 를 클릭시 ...
    "위치를 사용할 수 없습니다. F:\를 액세스할 수 없습니다. 매개변수가 틀립니다"라는 오류가
    발생합니다.

    이런 내용이 있습니다..
    저도 위와 같은 오류로 볼륨드라이브가 생성은 되지만 사용을 할 수 없는 상태입니다.
    도칸라이브러리 설치는 한 상태입니다..

    좋은 해결방법이 없을까요??

    • 明月 v명월v
      2013.05.11 11:09 신고 |  수정/삭제

      안녕하세요 블로그 방문 감사합니다.
      위 예제는 실제 가상(?) 드라이브까지 생성된 상태입니다.
      실제로 Ftp 라던가, 다른 위치 드라이브를 연결되지 않은 상태여서 엑세스에 실패한 현상이 나오는 것 입니다.
      그 부분의 소스를 수정하게 되면 사용하게 되겠습니다.