Previous Entry Share Next Entry
И немного программирования
outsidepro
Да, да, я тут немного ударился в программирование. И начал не как все нормальные люди с Pascal или еще чего проще, а с разновидностей Basic, а именно FreeBasic. По сути, какая-то интересная низкоуровневая и многословная разновидность. Конечно, несовместимость языка с Visual Studio, но тут уж я пока даже и не стремлюсь писать плагины под какую-нибудь Miranda NG!
Почему низкоуровневую и многословную? Могу поставить простейшую задачу:
В Windows 7X64 если открыть Преобразование текста в речь стандартно через панель управления, откроется аплет, который поддерживает только 64-битные синтезаторы. Чтобы отобразить все, необходимо либо раскопать в системе Речь (32 бита), либо запустить аплет sapi.cpl вручную из SysWOW64. Да, да, вы, как настоящий айтишник, напишете BAT-файлик, который будет запускать этот файл либо просто в shell, либо через control.exe. Но мы-то программисты! Нам важно видеть exe-файлик результатом нашей деятельности! =)
Итак, как это реализовать? Следующим кодом:

' Определяем тип приложения как Unicode
#define unicode

' Подключаем Windows API
#INCLUDE "WINDOWS.BI"

' Подключаем библиотеку file для проверки существования файлов
#include "file.bi"

' Объявляем нужные нам переменные:
Dim PRCInfo as PROCESS_INFORMATION ' тип PROCESS_INFORMATION, необходим для создания процесса
Dim STInfo as STARTUPINFO ' тип STARTUPINFO, тоже туда же
Dim WinDir as wstring * 512 ' путь к папке Windows пользователя, его установим ниже функцией GetWindowsDirectory
Dim ProcessIsCreated as bool ' сюда будем писать результат отработки функции CreateProcess
' Здесь пока объявляемые переменные закончились

' Ну и главный самый код программы:
GetWindowsDirectory (@WinDir, MAX_PATH) ' Как раз-таки определяем путь к папке Windows. Думаю, у каждого хватит ума сходить на MSDN ;)
GetStartupInfo (@STInfo) ' Заполняем тип STARTUPINFO

' Для подстраховки проверим есть ли вообще папка SysWOW64 путем проверки наличия на месте control.exe, а то
' FreeBasic пока не умеет компилировать приложения под 64-битные архитектуры специально.
If FileExists (WinDir+"\SysWOW64\control.exe") then
' Собственно, то, для чего и затеивался этот вышенаписанный сыр-бор:
ProcessIsCreated = CreateProcess (NULL, WinDir+"\SysWOW64\control.exe "+WinDir+"\SysWOW64\Speech\SpeechUX\sapi.cpl", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, @STInfo, @PRCInfo)
' Упс, подчистим мусор в хендлах...
CloseHandle (PRCInfo.hThread)

If ProcessIsCreated = 0 then ' Если процесс по воле судьбы не создался

' Сейчас тут будет высший пилотаж. :D Признаюсь, честно скоммуниздил такой способ получения ошибки у человека,
' коий этот FreeBasic любит до беспамятства! :D
' Серега, вай спасибо тебе большое!

' Получим последнюю ошибку из системы
dim as dword errid = GetLastError()
' Объявим переменную, куда запишем текстовый вариант кода ошибки из errid
dim as wstring * 1024 formatString

' Получим текстовый вариант ошибки:
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,errid,0,formatString,1023,0)

messageBox(0,"Control panel opening error! "+formatString,"Error!",MB_ICONERROR or MB_TASKMODAL)

End If
Else
' Нету на месте control.exe, значит пользователь запустил нашу программку не на 64-битной версии Windows!
MessageBox (0, "Your Windows operating system is not 64 bit architecture. This utility isn't needs to be executed. To run the Speech settings dialog, go to Control pannel\Speech.", "Error", MB_OK or MB_ICONERROR)
End If

Ну вот как-то так, весело и со вкусом. Разобраться было несложно - все привязано только к WinAPI, поскольку сам язык не имеет никаких оберток, работающих напрямую с системами.
И вот тут, на мою беду мне попался другой форк бедного бейсика - PureBasic! Код весьма облегчен, куча оберток, мы избавлены от надобности инклюдить все, что надо инклюдить, все уже тут, если, конечно, ты-таки установил нужные библиотеки! ;) Для кого как. Однако, для меня это стало какой-то бедой. Куча примеров, со смутными комментариями, писанные какими-то толи школьниками, толи еще кем... Но спорить не буду, что все задачи решаются на раз два! Хоть я и поломал голову и погугглил изрядно, но оно действительно так!
Опять же, я попытался перенести ту же самую утилиту на PureBasic. Смотрите как все выглядит:

WinDir.s = GetEnvironmentVariable("WINDIR") ; Получаем путь к папке Windows
ProcessIsCreated = RunProgram ("control.exe", WinDir+"\SysWOW64\Speech\SpeechUX\sapi.cpl", "", #PB_Program_Open) ; Собственно, открываем control.exe с параметром пути к аплету и записываем результат в ProcessIsCreated
; Туда запишется, на сколько я помню, PID процесса, но нам побоку что там будет. В любом случае, если 0 - то что-то не так!
If ProcessIsCreated=0 ; Если переменная пустая, значит ничего не создалось!
MessageRequester("SAPI5Opener error", "Couldn't open the control panel aplet.", #MB_OK|#MB_ICONERROR)
EndIf
End ; чистим весь мусор за собой одним прекрасным словом! =)

Вот, собственно и весь код! В паре строк! Но парился с этим я дней пять к ряду! Облазил кучу форумов, перепробовал и через WinAPI, и так, и сяк - без толку! Конечно, здесь пока нет такого прекрасного отлова ошибок из системы, но вся проблема в том, что я пока не могу разобраться как в PureBasic работать с указателями. Вроде все переменные соответствуют необходимым типам, а в итоге результат нулевой. После передачи указателей на них элементарно в WinAPI, они остаются пустыми. Так что ковыряемся далее! Учение и свободное время сделают пурик! :D

?

Log in

No account? Create an account