Кислотно-щелочной баланс или сбор информации об окруженииТема нашей последней лекции - кислотно-щелочной баланс, или среда в которой мы живем. Согласитесь иногда полезно знать то, что нас окружает, точнее не нас, а разработанные нами конфигурации, внешние отчеты и обработки. Да и заодно вывернуть пятки, типа круты мы не по-детски и в рот нам килограмм печенья. А помогать выворачивать пятки и кушать печенье буду я, Guk, mszsuz, Ковычки. Если кого не упомянул, не обессудьте. Склероз под старость совсем извел. ;)) | | Автор статьи: skunk | Редакторы: Волшебник Последняя редакция №6 от 23.01.06 | История URL: http://kb.mista.ru/article.php?id=66 | |
Что за имя у меня?
Пожалуй, самая трудная часть нашего фокуса. Начнем, наверное, с него. Будем определять имя стартовой программы 1С. Ибо в имени этом много вкусного. Но ребятишки из всеми любимой нами фирмы забыли воткнуть в язык один Си данную функцию. И если с определением пути, откуда стартанула система траблов нет, то с именем возникает лажа. Сейчас я вам покажу, как устранить эту лажу в 1С.
Сперва я, как последний Левка Баранов, определял имя программы путем поиска первого файла, удовлетворяющего маске «1Cv7*.exe». Что было не очень гуд, так как, тот же Левка, мог записать в рабочую папку 1С два разных файла 1Cv7s.exe и 1Cv7l.exe, просто от не фих делать. И мы получали грабли. Найденный файл мог оказаться совсем не тем, который был нужен нам. Конечно ситуация довольно редкая, я в реале столкнулся только когда готовил данный материал. Но кто знает, где оно летает. Не правда ли? И тут на помощь пришел человек, единственное, что о нем знаю, так это его никнэйм Ковычки. Он показал, как получить PID процесса запущенного 1С, но и заодно имя программы, породившее данный процесс. PID в данном случае нам не нужен. А вот определять имя будем его способом, и только в крайнем случае, тылкнемя к поиску по маске. Вот весь код функции:
//*******************************************
function vlFileName()
Answer = createobject("valuelist");
strPathFile = upper(bindir());
Answer.AddValue(strPathFile, "Path");
oleWSH = createobject("WScript.Shell");
objExec = oleWSH.Exec("rundll32.exe kernel32,SleepEx");
oleLocator = createobject("WbemScripting.SWbemLocator");
objService = oleLocator.ConnectServer();
strProcID = objService.Get("Win32_Process.Handle=" + objExec.ProcessID).ParentProcessID;
objExec.Terminate();
strNameFile = upper(objService.Get("Win32_Process.Handle=" + strProcID).ExecutablePath);
strNameFile = strreplace(strNameFile, strPathFile, "");
Answer.AddValue(strNameFile, "Name");
return Answer;
endfunction
Данная функция вернет список значений, состоящий из двух значений. У которого с представлением «Name» будет значение имени файла 1С. Ну, а под представлением «Path», будет находиться значение пути до данного файла.
Что в имени моем тебе надо?
Имя самой стартовой программы нам нужно, что бы знать за проперти. А для чего они нам нужны. Ясно для чего, чтобы что-то килишить. Один раз я это заюзал в троянчике, впаривая его лоху сказал, что данная обработка сосет патчи с обновлениями для эсины. Так же свойства имею для определения имени OLE сервера 1С. Ну а версию или релиз надо проверять, если используете в обработке какие-нибудь не документированные фичи. Короче глядим на проперти:
//*******************************************
function vlProperty(File = "", Path = "")
Answer = createobject("valuelist");
if fs.ExistFile(Path + File) = 0 then
Answer.AddValue("хорошо подумал... свойства чего ты хочешь получить", "error");
else
oleShell = createobject("Shell.Application");
objFolder = oleShell.NameSpace(Path);
objFile = objFolder.ParseName(File);
strPlatform = objFolder.GetDetailsOf(objFile, 31);
if find(strPlatform, "for SQL") > 0 then
Answer.AddValue("for SQL", "Platform");
Answer.AddValue("V77S.Application", "NameOLEServer");
elsif find(strPlatform, "multi-user") > 0 then
Answer.AddValue("многопользовательская", "Platform");
Answer.AddValue("V77.Application", "NameOLEServer");
elsif find(strPlatform, "single-user") > 0 then
Answer.AddValue("однопользовательская", "Platform");
Answer.AddValue("V77L.Application", "NameOLEServer");
else
Answer.AddValue("какой то странный файл", "error");
endif;
strVersion = objFolder.GetDetailsOf(objFile, 32);
if strcountoccur(strVersion, ".") = 3 then
strVersion = strreplace(strVersion, ".", ",");
vlTMP = createobject("valuelist");
vlTMP.FromSeparatedString(strVersion);
Answer.AddValue(string(vlTMP.GetValue(1)) + "." + string(vlTMP.GetValue(2)), "Version");
Answer.AddValue(string(vlTMP.GetValue(4)), "Release");
else
Answer.AddValue(strVersion, "Version");
endif;
endif;
return Answer;
endfunction
Как видно из примера данная функция тоже возвращает список значений. Правда вот только количество значений в ней плавает. Все зависит от той или иной ситуации. Если есть значение с представлением «error», то во время попытки определения пропертей возникли траблы. Если для вас это будет не критично, то продолжайте работу, нет валить клозетом обработку на фих. Если все гуд, то функция вернет четыре значения: «Platform» - тип платформы 1С, «NameOLEServer» - имя сервера автоматизации 1С, «Version» - версию исполняемого файла и «Release» - его релиз.
Компоненты.
Итак дошли до компонентов 1С. Все знают, что это такое. Правда, не все знают, с чем их едят. Я, например, не знаю, зачем определять их присутствие. Но кое-кто попросил, пришлось сделать. Может и вам на что-нибудь сгодиться. Смотрим код:
//*******************************************
function vlGetComponent()
Answer = createobject("valuelist");
Path = bindir();
oleShell = createobject("Shell.Application");
objFolder = oleShell.NameSpace(Path);
if fs.ExistFile(Path + "Account.dll") > 0 then
objFile = objFolder.ParseName("Account.dll");
if find(lower(objFolder.GetDetailsOf(objFile, 31)), "accounting") > 0 then
Answer.AddValue(1, "Account");
endif;
endif;
if fs.ExistFile(Path + "DistrDB.dll") > 0 then
objFile = objFolder.ParseName("DistrDB.dll");
if find(lower(objFolder.GetDetailsOf(objFile, 31)), "distrdbd") > 0 then
Answer.AddValue(1, "DistrDB");
endif;
endif;
if fs.ExistFile(Path + "Salary.dll") > 0 then
objFile = objFolder.ParseName("Salary.dll");
if find(lower(objFolder.GetDetailsOf(objFile, 31)), "salary") > 0 then
Answer.AddValue(1, "Salary");
endif;
endif;
if fs.ExistFile(Path + "Trade.dll") > 0 then
objFile = objFolder.ParseName("Trade.dll");
if find(lower(objFolder.GetDetailsOf(objFile, 31)), "trade") > 0 then
Answer.AddValue(1, "Trade");
endif;
endif;
return Answer;
endfunction
Опять получаем список из неизвестного числа значений. Смотрим, если есть представление «Account» - значиться есть бух учет, есть «DistrDB» - имеем УРИБ, есть «Salary» - работает зарплата, ну и если есть «Trade» - можно работать с регистрами.
Что у нас за «база»?
Эта фича в наглую закоммуниздина мною, у Gukа. Функция просто возвращает строку, в которой указан тип информационной базы. Короче смотрим, все по-русски:
//*******************************************
function strTypeIB()
if fs.ExistFile(ibdir() + "1Cv7.dd") > 0 then
Answer = "DBF";
else
Answer = "SQL";
endif;
return Answer;
endfunction
Что у нас еще имеется?
Иногда, бывает полезным знать какие базы еще зарегистрированны в компьютере. Например, при работе с OLE. Для этого мы воспользуемся функцией, которую любезно обнародовал всеми уважаемый mszsuz. Я просто взял на себя немного труда и внес небольшие изменения. Изменив код так, что он теперь возвращает список значений, где в качестве представления выступает представление информационной базы на компьютере, а в качестве значения – путь до базы.
//*******************************************
function vlGetListBase()
try
oleShell = createobject("MSScriptControl.ScriptControl");
oleShell.Language = "VBScript";
lstCode =
"function strGetListBase()
| const RootKey = &H80000001
| set Reg = GetObject(""winmgmts:{impersonationLevel=impersonate}!\\."" &_
| ""\root\default:StdRegProv"")
| PathKey = ""Software\1C\1Cv7\7.7\Titles""
| Reg.EnumValues RootKey, PathKey, Arr
| Answer = ""{""""СписокЗначений"""",{""
| for x = LBound(Arr) to UBound(Arr)
| call Reg.GetStringValue(RootKey, PathKey, Arr(x), Value)
| Answer = Answer & ""{{""""Строка"""","""""" &_
| Arr(x) & """"""},"""""" & replace(Value, """""""", """""""""""") &_
| """""",""""0""""}""
| if x <> UBound(Arr) then Answer = Answer & "",""
| next
| Answer = Answer & ""}}""
| strGetListBase = Answer
|end function";
oleShell.AddCode(lstCode);
Answer = valuefromstring(oleShell.Run("strGetListBase"));
Answer.SortByPresent();
except
Answer = createobject("valuelist");
Answer.AddValue("что-то не получилось", "error");
endtry;
return Answer;
endfunction
Десерт.
Ну и на закуску. Небольшая фича основанная на проверке файла <ПутьДоБазы\UsrDEF\Users.USR>. Его наличие дает нам все основания предполагать, что для подключения к данной базе требуется авторизация. Для Львов Барановых, чтобы начать работать с данной базой, требуется ввести логин и пассворд. Сама функция проста, как ежик под новогодней елкой:
//*******************************************
function intCheckBase(strPathBase)
return fs.ExistFile(strPathBase + "\UsrDEF\Users.USR");
endfunction
Передаете ей путь до нужной базы и получаете, либо 1 – есть авторизация, либо 0 – админ жжот. На следующих уроках я расскажу вам еще один трюк с этим файлом. Будем пускать робота для работы с базой.
Как прочитать параметры подключения 1с к SQLАвтор способа вроде бы Docent...
Function XOR(Val ParA, Val ParB)
Res = 0;
Koef = 1;
For BitNumber = 1 To 8 Do
BitA = ParA % 2;
BitB = ParB % 2;
ParA = Int(ParA / 2);
ParB = Int(ParB / 2);
BitC = (BitA + BitB) % 2;
Res = Res + BitC * Koef;
Koef = Koef * 2;
EndDo;
Return Res;
EndFunction
//*******************************************
// индексы значений с списке
// server = 2, db = 4, uid = 6, pwd = 8, checksum = 10
Function ConnectionString() export
Var SQLKeyCode[36], ConnectCode[200];
ConnectFile = IBDir() + "1Cv7.DBA";
If FS.ExistFile(ConnectFile) = 0 Then
Message("Это не SQL - база!", "!");
Return (0);
EndIF;
FSO = CreateObject("Scripting.FileSystemObject");
F = FSO.OpenTextFile(ConnectFile, 1);
ConnectLen = 0;
While F.AtEndOfStream = 0 Do
ConnectLen = ConnectLen + 1;
ConnectCode[ConnectLen] = Asc(F.Read(1));
EndDo;
F.Close();
FSO = 0;
SQLKey = "19465912879oiuxc ensdfaiuo3i73798kjl";
For i = 1 To 36 Do
SQLKeyCode[i] = Asc(Сред(SQLKey, i, 1));
EndDo;
Connect = "";
For i = 1 To ConnectLen Do
Connect = Connect + Chr(XOR(ConnectCode[i], SQLKeyCode[(i - 1) % 36 + 1]));
EndDo;
vl=createobject("ValueList");
Connect=StrReplace(Connect,"{","");
Connect=StrReplace(Connect,"}","");
vl.fromSeparatedString(Connect);
return (vl);
EndFunction
Вызов производится так:
if ExclusiveMode()=0 then
if FS.ExistFile(IbDir()+"1cv7.dds")=1 then
constr=ConnectionString();
if ConStr<>0 then
server=constr.getValue(2);database=constr.getValue(4);uid=constr.getValue(6); pwd=constr.getValue(8);
На сегодня все. Всем пока. Да чуть не забыл. Это наш последний урок в этом году. Так что разрешите всех заздравить и конечно поздравить. Достойно проводите старый, и пусть в новом у вас будем в жизни немного меньше дерьма, чем в прошлом. Ну, все-таки пусть его немного останется, ведь без него жизнь становится скучной. Всего-всего, что сами себе желаете. Короче удачи, счастья и т.п. Пух … ой Скунк ;))
Санкт-Петербург, Декабрь 2005 года.
skunk
Файлы:
http://www.kb.mista.ru/files/System.zip |