PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » В Notepad++ перестали работать плаги


В Notepad++ перестали работать плаги

Сообщений 1 страница 23 из 23

1

Указываю в плаге прямой путь и он не может открыть библиотеку, выдавая указанную мессагу:

Код:
If Not OpenLibrary(0, "C:\Program Files (x86)\Notepad++\SciLexer.dll")
	MessageRequester("", "Не удалось открыть SciLexer.dll")
EndIf

Пробую открыть отдельным кодом, открывает, даже если Notepad++ запущен.
Есть подозрение, что автор сделал блокирование повторного открытия SciLexer.dll в плаге. Если бы библиотека была зарегистрированной, то открывалась бы одной копией всегда, если она открывается программой, то возможна двойная, а то и тройная загрузка dll в память, не уверен, но не исключаю, и автор  чтобы предотвратить это сделал какую то блокировку. Осталось разгадать как получить дескриптор открытой библиотеки SciLexer.dll, то есть указатель на неё. Есть идеи?

0

2

Какой результат выполнения этого кода

Код:
h = LoadLibrary_("C:\Program Files (x86)\Notepad++\SciLexer.dll")
e = GetLastError_()

MessageRequester("", "Handle "+h+"  Error "+e)

И этого

Код:
h = GetModuleHandle_("C:\Program Files (x86)\Notepad++\SciLexer.dll")
e = GetLastError_()

MessageRequester("", "Handle "+h+"  Error "+e)

0

3

Вот, в той же последовательности:
Handle 0  Error 1114
Handle 0  Error 126

и на всякий случай я запустил повторно второй тест, получил те же 126.

А также я делал попытки перемещения кода в начало, думая что AttachProcess() зарезервированная функция NPP, внутри которой вызов, но не помогло.
Проблема началась с NPP версии 8.0.

Проверил права, скопировав SciLexer.dll в папку C:\D, не помогло. Также dll и NPP одинаковой разрядности x32.

Гугл пишет, что ошибка такая бывает, когда dll не может открыть другую dll, от которой она зависит.
Взял старую версию SciLexer.dll (3.5.6) из NPP 7.x.x, не помогло (текущая версия 4.4.6).

Отредактировано AZJIO (10.07.2021 14:41:50)

0

4

1114 это Произошел сбой в программе инициализации библиотеки динамической компоновки (DLL).

126 - Не найден указанный модуль.

В последнем случае DLL не найдена. Путь правильный? DLL загружена?

AZJIO написал(а):

AttachProcess()

В ней далеко не все возможно сделать. Это ограничение винды. https://docs.microsoft.com/ru-ru/window … -practices

AttachProcess(), DetachProcess(), AttachThread(), DetachThread() вызываются из DllMain.

0

5

Вот в обновлениях NPP

One button to build them all - build Notepad++ with Scintilla static lib and Boost RegExpr headers. (Implement #9594)

Scintilla static lib

0

6

AZJIO написал(а):

Scintilla static lib

Тогда не нужно загружать dll.
Для какой цели загружается SciLexer.dll?

0

7

Случайно удалил сообщение...

AZJIO написал(а):

GetCurrentScintilla()

Это хендл редактора?
Если да, то можно написать

Код:
*sciptr = SendMessage_(hSciEditor, #SCI_GETDIRECTPOINTER, 0, 0)
Length = ScintillaMsg(*sciptr, #SCI_GETSELTEXT, 0, 0)

0

8

GetCurrentScintilla определяет между правым и левым окном scintilla в NPP

Код:
Procedure GetCurrentScintilla()
	Protected instance_sci
	SendMessage_(NppData\_nppHandle, #NPPM_GETCURRENTSCINTILLA, 0, @instance_sci)
	If instance_sci
    ProcedureReturn NppData\_scintillaSecondHandle
	Else
    ProcedureReturn NppData\_scintillaMainHandle
	EndIf
EndProcedure
Код:
Procedure ScintillaMsg(*point, msg, param1 = 0, param2 = 0)
	If Scintilla And *point
    ProcedureReturn Scintilla(*point, msg, param1, param2)
	Else
    ProcedureReturn 0
	EndIf
EndProcedure

То есть ScintillaMsg() это для простоты, на самом деле ScintillaMsg вызывает Scintilla(), которая была получена из GetFunction

Прочитал, что можно типа так

Код:
Scintilla = SendMessage_(GetCurrentScintilla(), #SCI_GETDIRECTFUNCTION, 0, 0)

Но это пока не работает.

Из версии 1.47 в Windows Scintilla экспортирует функцию, называемую      Scintilla_DirectFunction , который можно использовать так же, как функция, возвращаемая     SCI_GETDIRECTFUNCTION. Это избавит вас от вызова     SCI_GETDIRECTFUNCTION и необходимость вызова Scintilla косвенно с помощью указателя функции.

Отредактировано AZJIO (10.07.2021 18:34:41)

0

9

AZJIO написал(а):

Но это пока не работает.

Так работает.

Код:
Prototype pScintilla(*point, msg, param1 = 0, param2 = 0)

Global Scintilla.pScintilla=0


Procedure ScintillaMsg(hWnd, msg, param1 = 0, param2 = 0)
  Protected *pSciWndData
  
  If Scintilla And hWnd
    *pSciWndData = SendMessage_(hWnd, #SCI_GETDIRECTPOINTER, 0, 0)
    If *pSciWndData
      ProcedureReturn Scintilla(*pSciWndData, msg, param1, param2)
    Else
      ProcedureReturn 0
    EndIf
  Else
    ProcedureReturn 0
  EndIf
EndProcedure


If OpenWindow(0, 0, 0, 330, 90, "ScintillaGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  If InitScintilla()
    ScintillaGadget(0, 10, 10, 320, 70, 0)
    
    hWnd = GadgetID(0)
    
    Scintilla=SendMessage_(hWnd, #SCI_GETDIRECTFUNCTION, 0, 0)
    
    ScintillaMsg(hWnd, #SCI_STYLESETFORE, 0, RGB(255, 0, 0))
    *Text=UTF8("This is a simple ScintillaGadget with text...")
    
    ScintillaMsg(hWnd, #SCI_SETTEXT, 0, *Text)
    
    FreeMemory(*Text) ; The buffer made by UTF8() has to be freed, to avoid memory leak
    
    ; Adding a second line of text with linebreak before
    Text$ = Chr(10) + "Second line"
    *Text=UTF8(Text$)
    
    ScintillaMsg(hWnd, #SCI_APPENDTEXT, Len(Text$), *Text)
    
    FreeMemory(*Text)
  EndIf
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

0

10

Пётр
Функция Scintilla() образуется от Scintilla = GetFunction(0, "Scintilla_DirectFunction")
но GetFunction сработает от OpenLibrary()

то есть

Код:
Prototype ScintillaDirect(sciptr, msg, param1 = 0, param2 = 0)
Global Scintilla.ScintillaDirect=0

это есть, хотя из описания должно быть так

Код:
Scintilla.ScintillaDirect = GetFunction(0, "Scintilla_DirectFunction")

а не так

Код:
Scintilla = GetFunction(0, "Scintilla_DirectFunction")

В данный момент ваш код у меня выдаёт ошибку на строке
ProcedureReturn Scintilla(*pSciWndData, msg, param1, param2)
[16:18:32] [ОШИБКА] Строка: 12
[16:18:32] [ОШИБКА] Invalid memory access. (Read error at address 2051)

Отредактировано AZJIO (10.07.2021 19:19:22)

0

11

AZJIO написал(а):

Функция Scintilla() образуется от Scintilla = GetFunction(0, "Scintilla_DirectFunction")

Ее аналог

Код:
Scintilla=SendMessage_(hWnd, #SCI_GETDIRECTFUNCTION, 0, 0)

То есть достаточно знать хендл любого из экземпляров редактора.

AZJIO написал(а):

В данный момент ваш код у меня выдаёт ошибку на строке
ProcedureReturn Scintilla(*pSciWndData, msg, param1, param2)
[16:18:32] [ОШИБКА] Строка: 12
[16:18:32] [ОШИБКА] Invalid memory access. (Read error at address 2051)

В Scintilla и *pSciWndData правильные значения?

0

12

Пётр
да, правильные, числа не ноль.
Я упростил, сделав запрос CODEPAGE

Код:
  If InitScintilla()
    ScintillaGadget(0, 10, 10, 320, 70, 0)
    
    hWnd = GadgetID(0)
    
    Scintilla = SendMessage_(hWnd, #SCI_GETDIRECTFUNCTION, 0, 0)
    Debug Scintilla
    
    Debug ScintillaMsg(hWnd, #SCI_GETCODEPAGE)
  EndIf

пурик 5.72

Отредактировано AZJIO (10.07.2021 19:34:06)

0

13

Разобрался. Должно быть

Код:
PrototypeC pScintilla(*point, msg, param1 = 0, param2 = 0)

Я тестировал на x64 версии, где нет разницы между Prototype и PrototypeC.

0

14

Пётр
Заработал пример, но не плаг. Пока смотрю подетально, чтобы правильно модифицировать.

0

15

В плагине нужно заменить

Код:
Scintilla.ScintillaDirect = GetFunction(0, "Scintilla_DirectFunction")

На

Код:
Scintilla.ScintillaDirect = SendMessage_(hWnd, #SCI_GETDIRECTFUNCTION, 0, 0)

Где hWnd - хендл любого экземпляра редактора Scintilla.

0

16

Пётр
Заработало и в плаге

Код:
*sciptr = SendMessage_(GetCurrentScintilla(), #SCI_GETDIRECTPOINTER, 0, 0)
Scintilla = SendMessage_(GetCurrentScintilla(), #SCI_GETDIRECTFUNCTION, 0, 0)

а так не работало:
Scintilla = SendMessage_(*sciptr, #SCI_GETDIRECTFUNCTION, 0, 0)
дело в том, что я сначала зеркально использовал

Код:
Scintilla = SendMessage_(hWnd, #SCI_GETDIRECTFUNCTION, 0, 0)

здесь у нас hWnd и в запросе SCI_GETDIRECTFUNCTION и в ScintillaMsg(hWnd, #SCI_GETCODEPAGE), и я сделал аналогично ScintillaMsg(*sciptr, #SCI_GETCODEPAGE), значит *sciptr в запросе, оказалось не так. Ну и все функции ранее переделал.

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

0

17

AZJIO написал(а):

а так не работало:Scintilla = SendMessage_(*sciptr, #SCI_GETDIRECTFUNCTION, 0, 0)

Правильно, потому что нужен хендл, а не результат #SCI_GETDIRECTPOINTER.

AZJIO написал(а):

У меня теперь вопрос SCI_GETDIRECTFUNCTION запрашивается для разных окон, а в описании было написано что её надо получить один раз, это же типа указатель на функцию из библиотеки

Все верно. Нужен любой хендл редактора Scintilla. Вызывается только один раз.
Тоже что с GetFunction(0, "Scintilla_DirectFunction") но получение адреса функции не из dll, а по хендлу.

AZJIO написал(а):

надо теоретически запросить его вообще при старте плага.

Да. Как только будет известен хендл Scintilla, тогда получить адрес функции.

+1

18

Пётр
Да, указал запрос SCI_GETDIRECTFUNCTION сразу после получения дескрипторов Scintilla, и не пришлось указывать в других местах. Обновил плаги NPP_TextA.7z и Highlight.7z

0

19

x86 плагин нормально работает?
Из кода плагина

Код:
Prototype ScintillaDirect(sciptr, msg, param1 = 0, param2 = 0)

Как выяснили, это работает в x64. В x86 будет ошибка В Notepad++ перестали работать плаги

0

20

PrototypeС использую. Не тестировал только плаги x64, некогда было, работа. Проверены x86, работают.

0

21

Пётр
Ещё интересует как выгрузить или заблокировать плагин, если что-то пошло не так. Например в каждом запросе к Scintilla используется проверка

Код:
If Scintilla And *point

логично было бы проверку Scintilla сделать там же где и происходит её однократный вызов. Понятно что ни один запрос далее работать не будет и плаг надо выгружать. Одновременно я понимаю что это не критично, то есть проверить что число не равно 0 это быстрая операция, но хочется сделать правильно. Вызвать DetachProcess(Instance) не могу, так как там параметр Instance, но внутри функции Instance не используется ,можно попробовать любое число. Я попробовал содержимое функции выполнить как операцию выгрузки, но даже по контексту она просто отключает горячие клавиши. Хотелось бы вывести мессагу для пользователя, что плаг имеет проблему и будет выгружен. Также я понимаю что в 99.999% указатель на функцию Scintilla будет получен и выгрузка плага в большинстве лишний код.

Ещё момент код внутри функции AttachProcess() как и код в глобальном пространстве оба выполняются при подключении DLL, т.е. при Attach. Т.е. чтобы написать красиво, весь глобальный код должен быть в AttachProcess(), конечно я понимаю что объявления структур, констант и глобальных переменных должно быть снаружи, а вот логические сравнения, чтения ini-файла и т.д. должно быть в AttachProcess().

На счёт OnErrorCall(@FatalError()) это только для теста? я понимаю что она может помочь в выводе ошибок и пользователь может детально сообщить о проблеме, но как я понимаю это встраивает в логику компилируемого файла связь с номером строки и увеличивает размер файла, а понадобится ли это на практике, когда плаг оттестирован достаточно.

Отредактировано AZJIO (12.07.2021 09:51:49)

0

22

AZJIO написал(а):

Ещё интересует как выгрузить или заблокировать плагин

Просто выгрузить нельзя, т. к. загружал Notepad++. Нужно ему сообщить что плагин не работает.

AZJIO написал(а):

Вызвать DetachProcess(Instance) не могу, так как там параметр Instance

Параметр Instance такой же как в AttachProcess(), но вызов DetachProcess() не выгрузит плагин. Нужно выгружать DLL, но это должен сделать Notepad++, иначе DLL выгрузится, а Notepad++ продолжит вызывать функции плагина что приведет к ошибке.

AZJIO написал(а):

На счёт OnErrorCall(@FatalError()) это только для теста?

Это чтобы понять в какой строке кода произошла ошибка.
Если плагин отлажен и ошибок нет, можно убрать функцию OnErrorCall(), все что связано с ней и снять галочку "Поддержка OnError строк" в настройках компилятора.

AZJIO написал(а):

это встраивает в логику компилируемого файла связь с номером строки и увеличивает размер файла

Верно.

0

23

Пётр написал(а):

Просто выгрузить нельзя, т. к. загружал Notepad++. Нужно ему сообщить что плагин не работает.

Возможно есть какой нибудь флаг, который скажет Notepad++, что плаг надо отключить. Но можно другим путём попробовать: Notepad++ запрашивает указатель на структуру-массив указателей функций. Можно уменьшить размер элементов массива до одного, оставив в ней указатель на функцию с мессагой ошибки. В памяти будет висеть, но уже с напоминанием, что плаг не работает.

Проверил, работает этот код

Код:
If Not Scintilla
	ReDim FuncsArray.FuncItem(1)   ; оставляем 1 пункт с текстом Ошибка
	With FuncsArray(0)
    \_itemName="Ошибка"
    \_pFunc=@ItemError()	; указатель на функцию показывающей сообщение об ошибке
	EndWith
EndIf

Кстати, ранее я не мог сделать хоткей на пункт, поменял _key.u на _key.b (у автора было _key.i), так как догадался, что #VK_F7, то есть константа клавиши в 99% это символ от 0 до 255, то есть число размером в байт, а не как ранее мне казалось двухбайтовая буква юникода. И заработало.

Отредактировано AZJIO (12.07.2021 13:35:55)

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » В Notepad++ перестали работать плаги