Pull to refresh

Mac Maniac. DropCopy под Windows

Reading time8 min
Views1.5K
Помните пост про извлечение дивайсов и носителей как в Маке? Так вот, у той милой иконки Eject появился друг — DropCopy:

Вступление


Когда я работал на маках, я просто наслаждался простотой перекидывания файлов между компьютерами в сети с помощью DropCopy. Кидаешь в чёрную дыру файлы, выбираешь из выпадающего списка куда отправить, и на рабочем столе адресата появляются эти самые файлы. Класс! Но с момента моего увольнения прошло уже 2 года и некоторая ломка по макам осталась (особенно по Final Cut Pro *прослезился*). В комнате рядом сидит брат за своим компом, я за своим, есть ещё ноутбук которым пользуются все по очереди и постоянно возникает проблема, когда надо перекинуть файл с одного компа на другой. Чего только мы не вытворяли:
  • Пересылка по почте
  • По аське
  • Через флешку
  • Через ФТП (это самый логичный способ)

Стоит отметить важный момент — Общие Документы Сети Microsoft возможно и помогли бы в данной ситуации, но они отключены давно и так основательно, что как их включить обратно я уже не знаю\не помню\не хочу, поэтому я начал копать в другую сторону и в итоге получилось (по-моему) гораздо лучше. Так что тем у кого данная вещь функционирует я думаю не имеет смысла читать дальше.

Продукты для приготовления


Для выполнения нам понадобиться:
  • утилитка ftp.exe (стандартный компонент Windows)
  • IIS (нужно устанавливать через компоненты Windows)
  • Вместо IIS можно (и даже лучше) использовать сторонний ФТП сервер по вкусу
  • Иконка DropCopy (нагло стырена из самого же дропкопи под Мак)
  • AutoHotKey для изобретателей или просто exe файл для пользователей

Подготовка машин



IIS


Дальнейшая работа уныла и однообразна: На всех машинах надо поставить FTP сервер. Учитывая, что я не люблю ставить много дополнительных программ, я решил покопаться в Windows и нашёл IIS. Он имеет дыры (не знаю как новые версии, но старые имели), но так как мою мини сеть охраняет Роутер, то я сплю спокойно, да и параноей «кто-то хочет меня взломать» не обладаю, кому я нафиг нужен? Поэтому сначала пройдёмся по этому пути:
Панель управления\Установка и удаления программ\Компоненты Windows

Cтавим галочку напротив IIS и нажимаем Details

Логично, что нам нужен FTP из этого списка. Дальше последует установка и первая проблема — возможно он потребует, чтобы вы вставили в дисковод диск, откуда инсталировали свой Windows. Так как я ставил 2 года назад свой Windows — я уже забыл где он лежит, но всё-таки нашёл диск, Но думаю если порыться в интернете, то можно найти ссылку на скачивание данного компонента без этих приключений. Мысленно перенесёмся в будущее, где у вас всё-таки получилось его поставить. Дальше идём
Пуск\Администрирование\Internet Information Services (что? у вас нету пункта Администрирование? Ужос! Да простят меня ИТ-гуру, что я возлагаю на себя труд Капитана Очевидности: Правой кнопкой по меню Пуск\Свойства\Меню Пуск\Настроить\Дополнительно\Администрирование — Отображать в меню «Все программы» и «пуск»)
Я отвлёкся. Дальше выбираем:

и правой кнопкой по нашему FTP узлу по умолчанию\Свойства.

Вот это самая небезопасная часть, потому-что не рекомендуется использовать
анонимные подключения, но мне нечего бояться, как я уже говорил. Можно конечно создать пользователя с паролем вместо анонимуса, но я не осилил и мне это не надо, ибо у меня на компе только один пользователь — админ и без пароля, а IIS без пароля ругается.

Здесь самый главный момент — путь домашней директории. Нужно указать Рабочий стол. Я не знаю, будет ли работать это с убранной галочкой Чтение, поэтому на всякий случай оставил.

Главная проблема, что Рабочий стол защищён рутом, а пользователь IUSR_USRERNAME не обладает привилегиями на эту папку, поэтому надо провернуть вещь, за которую меня распнут суровые бородатые админы — нужно переместить пользователя IUSR_USRERNAME в группу администраторов. Поэтому: Пуск\Администрирование\Управление Компьютером\


Это должно работать, на ваш страх и риск ) Но это путь экстремала, далее лёгкий и безопасный путь

Quick`n`Easy FTP Server


У меня на главном компьютере стоит данная программка. Может конечно она не особо функциональна, но мне хватает того, что она предлагает. У меня она уже давно и я даже не помню откуда её нашёл. Ссылка. Тут я просто создал нового пользователя Tr с незамысловатым паролем и указал его Домашнюю Директорию как Рабочий стол. Галочки ставить по вкусу, но так, чтобы всё работало)

И это впринципе всё, что надо сделать в этой программе. Имеет смысл кинуть её ярлык в автозагрузку (загружается она быстро и бесшумно). Теперь собственно главная часть:

Реализация


Для начала проверьте свои фаерволы и позвольте этому потоку литься без преград. Ну теперь дружно пишем код на языке AutoHotKey (я надеюсь что с моими пояснениями вы сможете не хуже написать его на любом другом языке, а если без моих пояснений, то даже лучше :-) Сначала программка была очень простой, маленькой и могла пересылать только несколько штук файлов, с именами не содержащими пробелов (один входной путь, содержащий два пробела, превращал это в 3 входящих параметра, не имеющих смысла). Но потом программка начала обрастать функциональностью, научилась перекидывать папки, пробелы ей нипочём, и теперь у неё даже появился прогрессбар хода выполнения.

Как и предыдущий пост, на рабочем столе лежит ярлык на эту програмку, и когда мы перекидываем на неё файлы, она просыпается, считывает из config.ini список компьютеров и показывает менюшку:

Наша программа не будет вникать в тонкости сокетов и прочих заморочек. она всё будет доверять FTP.exe. Логика с FTP.exe в нашем случае проста. мы пишем файл сценария на основе переданных файлов и в конце просто вызываем ftp.exe с такими параметрами:
ftp.exe -s:«C:\Файл сценария.txt» >«C:\ЛогФайл»
файл сценария примерно выглядит так:
open 172.31.0.3
anonymous
slau.andre@gmail.com
binary
mkdir "ftp"
cd "ftp"
put "C:\DOCUME~1\Kefir\0016~1\ftp\1.png"
put "C:\DOCUME~1\Kefir\0016~1\ftp\2.png"
put "C:\DOCUME~1\Kefir\0016~1\ftp\9.jpg"
put "C:\DOCUME~1\Kefir\0016~1\ftp\PrScr.jpg"
mkdir "прога"
cd "прога"
put "C:\DOCUME~1\Kefir\0016~1\ftp\прога\config.ini"
put "C:\DOCUME~1\Kefir\0016~1\ftp\прога\DropFile.ahk"
put "C:\DOCUME~1\Kefir\0016~1\ftp\прога\DropFile.exe"
put "C:\DOCUME~1\Kefir\0016~1\ftp\прога\Quick'n Easy FTP Server v2.7.1 setup.exe"
cd ..
cd ..
quit


Config.ini такой:
(.ini это просто чтобы порядок был в папке программы, хотя сам файл ничего общего с .ini не имеет)
Borw|172.31.0.3|Username|MyPassword
Nout|172.31.0.4|anonymous|slau.andre@gmail.com

Стоит отметить, что пароли со знаком | обречены на провал ;-)

Чтож, приступим:

; точка с запятой на этом языке - комментарий. У программеров Си\Джава взорван мозг
#NoTrayIcon
#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%

curr=%1%                                  ;без параметров, программа не запустится
if curr=
   ExitApp

FTPCommandFile = %A_ScriptDir%\FTPCommands.txt   ;имя файла сценария
FTPLogFile = %A_ScriptDir%\FTPLog.txt            ;имя логфайла
countf:=0
TSize:=0
FileDelete %FTPCommandFile%                      ;удаляем старые файлы 
FileDelete %FTPLogFile%                          ;на всякий случай
FileRead, conf, %A_ScriptDir%\config.ini         ;считываем настройки в файл conf

n:=0
Loop, parse, conf,`n                             ;разбираем в цикле по строкам conf
{
     i:=0
     Loop, Parse, A_LoopField, |                 ;парсим по знаку |
     {                                           ;и заносим в двумерный массив всё
         con%n%%i% = %A_LoopField%               ;что там было
         i++
     }
     name:=con%n%0                               ;добавляем в цикле пункты меню. 
     Menu, PopUp, Add, %name%, Who               ;Who - процедура обработки выбора
     n++                                         ;меню
}
i:=0
n:=0

Menu, PopUp, Show                            ;и только теперь показываем меню.
                                             ;конечно не очень удобно что меню
                                             ;показывается не сразу, но по другому
                                             ;я не знаю как это сделать
return

Who:
{
  item:=A_THISMENUITEMPOS-1
  addr:=con%item%1
  login:=con%item%2
  pass:=con%item%3
  FileAppend, open %addr%`n, %FTPCommandFile%      ;пишем в файл сценария параметры
                                                   ;соединения на основе выбранного
  FileAppend, %login%`n, %FTPCommandFile%          ;меню
  FileAppend, %pass%`n, %FTPCommandFile%

  GoSub, Go                                        ;идём к основной процедуре
return
}

go:                                              ;эта процедура составляет запросы
{                                                ;в сценарии на передачу файлов
  FileAppend, binary`n, %FTPCommandFile%         ;двоичный режим передачи 
  prev=
  ToolTip Составляю список...
  Loop                                       ;этот цикл также отлавливает
  {                                             ;во входящих параметрах
                                                 ;нелогичные запросы и
                                                 ;догадывается что в пути 
                                                 ;файла были пробелы, поэтому
                                                 ;склеивает всё обратно
       curr:=%A_Index%             	                                        
       if not prev                          
       {                                        
           prev=%curr%
           continue
       }
       if(!InStr(curr, ":\") and (curr!="")) 
       {                                          ;во входящих параметрах нету ":\"?
           prev=%prev%%A_Space%%curr%             ;склеиваем
           continue
       }       
       FileGetAttrib, Attributes, %prev%
       IfInString, Attributes, D       ;если это папка, то идём в 
                                                   ;рекурсивную функцию
       GenFold(prev,FTPCommandFile,countf,TSize)        
       else
       {                                         ;если нет, то записываем файл
                                                  ;в сценарий
            FileAppend, put "%prev%"`n, %FTPCommandFile%
            FileGetSize, dsize, %prev%
            TSize += %dsize%        ;добавляем размер файла к общему
                                                  ;размеру всех файлов
            countf++                        ;увеличиваем счётчик файлов
       }    	   
        if curr =
		   break
        prev=%curr%
  }     
	
  FileAppend, quit, %FTPCommandFile%         ;добавляем в конец комманду выхода 
  SetFormat, float, 6.1
  TSize:=TSize/(1024*1024)
  ToolTIp Запускаю ftp.exe...                      
        	                                                ;запускаем ftp.exe
  Run %comspec% /c ftp.exe -s:"%FTPCommandFile%" >"%FTPLogFile%", ,Hide
  ToolTip
  ;если вы доверяете ftp и вам не нужен прогрессбар, то дальше можно не писать
  ;========================================================;создаём прогресбар
     CustomColor = 666666
     Gui, -Resize +LastFound +ToolWindow -Caption +AlwaysOnTop
     Gui, Color, %CustomColor%
                                  ;cFF9966 - меняйте цвет на какой хотите
     Gui, Add, Progress, x0 y0 w132 h15 cFF9966 Background666666 vMyProgLoadi
     GuiControl, , MyProgLoadi, 0
     Gui, Font, S7 c111111, Tahoma
     Gui, Add, Text, vMyMemLoadi BackGroundTrans x2 y2 w100 h15, 0/%Tsize%
     Gui, Show, h15 w132, MyProgLoadi	 ;===========================================================================
  countf2:=0
  TSize2:=0
  maybeexit:=0
  Loop     ;ожидаем пока запустится ftp.exe, если вдруг он ещё не запустился
  {
      Process, Exist, ftp.exe
      if(ErrorLevel = 0)
      {
         maybeexit++
         if(maybeexit>10)         ;наш порог терпения 5 секунд
         {
            MsgBox Чего-то ftp.exe долго не запускается`nЯ пожалуй завершусь.
            ExitApp
         }
         Sleep 500
         continue
      }
      break
  }
  Loop            ;этот цикл сканирует лог файл каждые 250 милисекунд и считывает
  {               ;сколько файлов уже передалось
      Process, Exist, ftp.exe     
      if((ErrorLevel = 0) or (countf2 >= countf))   ;выходим из цикла когда
      {                                      ;всё передалось или ftp.exe завершился
         Gui, Destroy
         FileRead, mfile, %FTPLogFile%
         IfNotInString,mfile,logged in  ;ftp.exe мог завершиться из-за
         {                                        ;того, что не смог присоедениться
             MsgBox, 36, Алярма, Не могу присоединиться.`nОткрыть Логфайл?
             IfMsgBox, Yes
                 Run, "%FTPLogFile%"
             break
         }
         SetFormat, float, 6.1
         ToolTIp Файлов: %countf%`nРазмер: %TSize% мб ;ToolTip о результатах
                                ;чтобы жёстко контролировать, вместо Tooltip
                                ;поставть MsgBox
         Sleep 2000
         ToolTip
         break
      }
      countf2:=0
      TSize2:=0
      FileRead, mfile, %FTPLogFile%
      Loop, Parse, mfile,`n            ;проверяем склько файлов уже передано
      {                                ;благодаря лог файлу
         If(InStr(A_LoopField, "ftp: "))
         {
            countf2++
            dsize2:=SubStr(A_LoopField, 6, InStr(A_LoopField," ", 0, 6)-1)
            TSize2 += %dsize2%
         }
      }
      GuiControl, 1: , MyProgLoadi, % (countf2*100)/countf ;двигаем прогрессбар
      SetFormat, float, 6.1
      TSize2:=TSize2/(1024*1024)
      GuiControl,Text , MyMemLoadi, %TSize2%/%TSize% мб
      Sleep 250
    }
    ExitApp
    return
}

GenFold(path,FTPCommandFile,ByRef countf,ByRef TSize) 
{                                         ;функция составления сценария для папок
    fold:=SubStr(path,InStr(path,"\",0,0)+1)
                                        ;создаём на удалённой машине папку с
                                        ;таким же названием и заходим в неё
                                        ;проходимся по всем файлам в этой папке
                                        ;папка - тоже файл (привет Юниксу)

    FileAppend, mkdir "%fold%"`n, %FTPCommandFile%
    FileAppend, cd "%fold%"`n, %FTPCommandFile%
    Loop, %path%\*, 1, 0
    {                                               
        FileGetAttrib, Attributes, %A_LOOPFILEFULLPATH%
        IfInString, Attributes, D                ;привет, мистер Рекурсия
            GenFold(A_LOOPFILEFULLPATH,FTPCommandFile,countf,TSize)
        else
        {
            FileAppend, put "%A_LOOPFILEFULLPATH%"`n, %FTPCommandFile%
            TSize += %A_LoopFileSize%
            countf++
        }
    }
    FileAppend, cd ..`n, %FTPCommandFile%
    return
}


Стоит отметить, что если в пути файла присутствуют два пробела один за другим, то тут программа бессильна.

Код, exe, Иконка тута

Вывод


Чтож, получилось даже больше чем надо, потому-что можно перекидывать файлы между компами не только в одной локальной сети но и между удалёнными компьютерами с прямым IP адресом.
p.s.: если кому-то приглянулись обоины, то тут я их выкладывал ;-)
p.p.s.: за диктанты по русскому языку у меня всегда было стабильное 2, поэтому не ругайте сильно за ошибки
Tags:
Hubs:
Total votes 46: ↑42 and ↓4+38
Comments95

Articles