Обновление ПО "МС2" - с версии 2.1.5.1 до 2.1.5.2

1: Добавлена проверка связи с сервером С-Маркет.
2: Добавлена возможность работы со старыми версиями С-Маркет на старом Interbase без поддержки EXECUTE BLOCK.
3: Исправлена ошибка при файловой загрузке из Домино.
4: Исправлена ошибка возникшая при изменении VIEW_EXPORT при выводе сличительных ведомостей.
5: Добавлен механизм работы с мягкими чеками.

( Читать дальше )

Стив Джобс и компания Next - 1986 год

Интересный короткий документальный фильм о Стиве Джобсе и о его компании Next. Сейчас то уже известно чем всё кончилось.

Получаем программно серийный номер на ТСД Cipher 9300

Публикация в дополнение вот к этой: Программируем лазерный считыватель на терминалах сбора данных Cipher (9300).

У терминалов сбора данных Cipher с Windows CE — есть одна особенность, в отличие от всех других ТСД (во всяком случае Motorola(Symbol) и Datalogic) стандартными способами получить серийный номер не получится. Получить то он получится — но будет на всех устройствах одинаковый, что лично меня не устраивает.

Однако этот глюк можно обойти и получить серийный номер при помощи API с библиотекой SystemApi_Ce_Net.DLL которая поставляется на диске с терминалом.

Ниже маленький примерчик кода — как это сделать:
using Cipherlab.SystemAPI;


int err = 0;

DataType.DataStruct.SYSINFO sysinfo = new DataType.DataStruct.SYSINFO();
            
err = SystemAPI.Function.GetSysInfo(ref sysinfo);

string serial = Encoding.UTF8.GetString(sysinfo.SerialNum,0,sysinfo.SerialNum.Length);

Полагаю комментарии излишни, и так всё достаточно просто и понятно.

Удаление временных таблиц в MSSQL

Иногда возникает необходимость, в ходе работы процедуры, удалить временно созданную таблицу которая может быть либо создана либо нет, тогда не достаточно просто написать например drop table #myTempTable — потому что в случае если таблицы не существует то запрос не выполнится и выдаст ошибку. Пример ниже показывает как правильно удалять временные таблицы в таком случае:
if exists (
	select * from tempdb.dbo.sysobjects o
	where o.xtype in ('U') 

	and o.id = object_id(N'tempdb..#myTempTable')
)
BEGIN
  DROP TABLE #myTempTable; 
END

Примеры процедур, для минимизации кода при работе с БД в Delphi.

Волею судеб вновь столкнулся с разработкой на Delphi, с тех пор когда занимался этим будучи студентом, прошло много времени и в Delphi особо ничего не изменилось, а вот у меня несколько сменились представления о разработке и о том как правильно должен выглядеть код.

Теперь о том, как я делал давным давно и как (к моему удивлению) многие программисты делают до сих пор.

Ох уж эти базы данных, чего может быть проще, кинул на форму DBGrid, Connection, Query или Table, DataSource, связал всё это хозяйство и работает — Красота!.. Только если этих таблиц много и выборки очень разнообразны (даже в случае когда мы всё вынесем на отдельную формочку) получится жуть в которой очень легко запутаться и это только на форме, в то что творится внутри кода и заглядывать страшно — бардак.

Да и в любом случае, надо вам скажем выполнить один единственный запрос в коде, и поехало собирание Query с кучей строчек кода.


( Читать дальше )

Рекурсивная процедура поиска элементов ветки дерева в FireBird и Interbase

Время от времени приходится общаться с СУБД FireBird и Interbase. И вот недавно возникла необходимость поиска и выбора всех вложенных элементов дерева. В моём случае необходимо было удалить все вложенные группы дерева при удалении родительской группы и в дальнейшем организовать поиск всех вложенных элементов.

Удаление можно сделать на триггерах, а вот с поиском так не прокатит. Поэтому используем рекурсивную процедуру выборки. (заранее оговорюсь, рекурсия — это вариант для небольших и не очень нагруженных БД, если база большая и нагрузка на СУБД планируется существенная, то рекурсии лучше избежать, пример того как это можно сделать будет ниже)

Итак, мы имеем таблицу с тремя полями (идентификатор, идентификатор родителя, наименование):
CREATE TABLE TEST_TABLE (
    ID         INTEGER NOT NULL,
    ID_PARENT  INTEGER,
    NAME       VARCHAR(250)
);

Для такой таблицы процедура рекурсивного удаления элемента со всеми вложенными элементами будет выглядеть так:
CREATE PROCEDURE DELETE_NODES (
    ID_NODE INTEGER)
AS
DECLARE VARIABLE ID_KID INTEGER;
begin
  /* Выбираем вложения */
  for select ID from test_table where ID_PARENT = :ID_NODE INTO :ID_KID
    do begin
        /* Запускаем процедуру для всех вложенных групп поочереди (рекурсия) */
        execute procedure delete_nodes(id_kid);
    end
    /* Удаляем группу*/
    delete from test_table where ID = :ID_NODE;

  suspend;
end
Вот и всё, вместо удаления можем делать выборку или изменение данных, всё что угодно.

( Читать дальше )

Фотографии ТСД Symbol MC 9090 Gun - с пистолетной рукояткой.

ТСД Symbol MC 9090 GunНедавно вновь попал в руки терминал сбора данных, фотографий которого на сайте ещё не было. Технически данный терминал практически ни чем не отличается от терминала, о котором я уже писал здесь: http://kbss.ru/blog/promterminals/27.html.Только в том случае была модель с укороченным корпусом (на мой взгляд менее удобная чем с длинным). Сейчас же я представлю экземпляр с пистолетной рукояткой. Устройство попало ко мне для лёгкого (программного — не касающегося технической части) ремонта, терминал перестал по умолчанию читать коды UPC — точнее перестал их приводить к виду EAN, вообщем мелочь.
Данному экземпляру уже около 5-ти лет довольно активной эксплуатации. О техническом состоянии судите сами по фотографиям и на видео в конце публикации.
Это пожалуй самый надёжный терминал из линейки терминалов сбора данных Symbol (Motorola), его поломки от падений и неаккуратного использования практически сведены к нолю.


( Читать дальше )

Позднее связывание, на примере взаимодействия с терминалом сбора данных Cipher 8001L

В данной публикации я продемонстрирую взаимодействие с COM объектом на языке C#. В примере будет использована OLE-компонента для взаимодействия с ТСД Cipher 8001L компании CitySoft. Думаю, всё то что описано можно использовать и для других COM-Объектов.

Для начала поясню в чём суть позднего связывания, и зачем это надо. Позднее связывание необходимо нам тогда, когда тип объекта заранее не известен и мы не можем напрямую обращаться к параметрам, методам и свойствам используемого объекта — вот для этого и используется позднее связывание.

Для вызова метода надо знать его название и список формальных параметров, которые он принимает. Для вызова используем метод InvokeMember().


( Читать дальше )

Microsoft All-In-One Code Framework - бесплатная библиотека примеров топик-ссылка

Наткнулся на интересную коллекцию примеров кода. Примеры кода для разных задач под различные виды разработки на платформе .NET. Публикую ссылочку, может пригодится.