Форум » GUI » ShellExecute в МиниГуи » Ответить

ShellExecute в МиниГуи

Andrey: С некоторых пор перестало показываться окно при вызове команды ShellExecute. Раньше автоматом было. Т.е. фокус переходил на проводник. Что нужно сделать, чтобы фокус переходил на проводник ? Вот код: [pre2]// Как программно открыть папку и выделить файл? // ShellExecute(Application.Handle, 'OPEN', 'EXPLORER', '/select, ' + path, '', SW_NORMAL) FUNCTION RunExplFile2(cFile) ShellExecute( 0, "open", "explorer.exe", '/select, ' + cFile, , SW_SHOWNORMAL ) //InKeyGui(5000) - это не помогает. RETURN NIL[/pre2]

Ответов - 34, стр: 1 2 All

gfilatov2002: Andrey пишет: Что нужно сделать, чтобы фокус переходил на проводник ? У меня сработал такой вызов: // Using ShellExecute for opening Explorer with selected File ShellExecute( 0, "open", "explorer.exe", "/select," + cFileName, NIL, 1 ) где cFileName := CurDrive() + ":\" + CurDir() + "\MyPicture.png"

Andrey: Да на простом примере может и будет работать, только у меня не работает. Путь вот такой длинный: J:\Abonent4.Город\@Город-Sberbank\Export-2023\0156019111_10202810800190000111_200223.txt У меня на кнопках установлены вызовы других функций через блок кода, примерно так: [pre2] cRunBlock := cRunFun + "( '"+cVal+"' ,'"+aObj[1]+"', '"+aObj[2]+"', '"+cWrtFld+"' )" bBlock := &("{||"+cRunBlock+"}") SetProperty(cForm, aObj[1], "OnLostFocus", bBlock)[/pre2] Причём вызовов несколько. Это как то может повлиять на сбой фокуса ?

gfilatov2002: Andrey пишет: Путь вот такой длинный Для таких случаев используй преобразование пути с помощью функции _GetShortPathName(): cFileName := _GetShortPathName( cFileName )


Andrey: gfilatov2002 пишет: Для таких случаев используй преобразование пути с помощью функции _GetShortPathName(): Не помогает... Убрал русские буквы из пути. Думал что из диска J: подключённый через SUBST, но указание явно - тоже не работает, т.е. НЕ ВЫВОДИТ проводник на передний план рабочего стола компа, предыдущее модальное окно на переднем плане. [pre2]cFile = F:\DISK_J\ABONENT4.City\@City-Sberbank\Export-2023\0156019111_10202810800190000111_200223.txt c2File= F:\DISK_J\ABONENT4.City\@City-Sberbank\Export-2023\0156019111_10202810800190000111_200223.txt[/pre2] Что можно сделать ?

SergKis: Andrey пишет Что можно сделать ? для excel ты делаешь[pre2] hWnd := oExcel:hWnd // хендл окна Excel ShowWindow( hWnd, 6 ) // MINIMIZE windows ShowWindow( hWnd, 3 ) // MAXIMIZE windows BringWindowToTop( hWnd ) // a window on the foreground [/pre2] проделай для explorer.exe, поймав его hWnd через enumwindow() или через pid := ShellExcecuteEx(...) В hmg в примерах или lib был набор ф-й для pid (не могу вспомнить в данный момент) предыдущее модальное окно на переднем плане Сделай Minimaize этому окну, потом сделаешь Restore, возможно в нем Topmost сильно "заморозился"

Andrey: Пример C:\MiniGUI\SAMPLES\Advanced\ShellExec При вызове кнопки видно, что окно Хелпа МиниГуи становится после окна программы МиниГуи !!! Эта же программа лежит собранная где-то в 2019 году - Хелпа МиниГуи на переднем плане.

SergKis: Andrey пишет При вызове кнопки видно, что окно Хелпа МиниГуи становится после окна программы МиниГуи !!! Что не ясно в примере и причем здесь год ? [pre2] DEFINE WINDOW Win_1 ; AT 0,0 WIDTH 450 HEIGHT 300 ; TITLE "ShellExecuteEx() Using Demo" ; MAIN ; TOPMOST ; ON INIT This.Topmost := .F. ; FONT "Tahona" SIZE 14 ; NOMAXIMIZE NOSIZE ... [/pre2] ты в примерах всегда это пишешь (красным)

Andrey: SergKis пишет: Что не ясно в примере и причем здесь год ? Блин, упустил из вида. Спасибо, понял !

Andrey: Как из PID процесса можно получить хендл окна ? Т.е. при запуске: [pre2] nPid := ShellExecuteEx( 0, "open", "explorer.exe", '/select, ' + cFile, , SW_SHOWNORMAL )[/pre2] Получаю nPid, а как потом получить Хендл окна для изменения его ? [pre2] hWin := ????? nPid cTitle := GetWindowText( hWin ) cTitle += ": " + cFileNoPath(cFile) SetWindowText( hWin, cTitle ) // меняем текст Title [/pre2] Видел это - http://clipper.borda.ru/?1-4-0-00001093-000-0-0-1438070443 Кто нибудь реализовал ?

Haz: Andrey пишет: Видел это - http://clipper.borda.ru/?1-4-0-00001093-000-0-0-1438070443 Кто нибудь реализовал ? Реализовывал лет 5 назад, только обратную задачу по окну найти процесс, все работает. А в чем сложность протестировать ? там не более 10 строк кода будет всего. Учти только что у одного процесса может быть много окон ( кнопки, к примеру, это тоже окна ) https://learn.microsoft.com/en-us/windows/win32/winmsg/about-window-classes

SergKis: Haz пишет А в чем сложность протестировать ? Что есть в hmg примерах - танцует от hWnd, т.е. для explorer.exe [pre2] LOCAL cClass := "CabinetWClass" // класс окна explorer.exe ... nId := ShellExecuteEx( 0, "open", "explorer.exe", '/select, ' + cFile, , SW_SHOWNORMAL ) ... IF !Empty(nId) // запустился и прорисовался aWin := HandlesHbWin( , cClass, .T.) IF ( lRun := Len(aWin) > 0 ) i := 0 h := aWin[1] ? GetWindowThreadProcessId(h, @nThr, @nPid) // вернет Nil ?? i, h, nId, nPid, nThr ^^^ ^^^^ // разные значения [/pre2] Вопрос от Андрея и меня, как получить hWnd от nId ? Ведь из оной или разных программ может быть запущено несколько explorer.exe aWin := HandlesHbWin( , cClass, .T.) даст несколько hWnd. Пример тут https://TransFiles.ru/qyyji - внизу кнопка (1) запускает просмотр запущенного, на ней Reset - обновляет список, Excel запускается, в Reset видно - внизу кнопка (2) запускает explorer.exe с new Title и блокирует 2-ой запуск - внизу кнопка (3) останавливает explorer.exe с new Title - вверху кнопка 1) запускает explorer.exe (запустить можно несколько), тут вопрос и возникает (вверху) PS Мне хватало, на клиентской PC, помечать запущенную прогу, меняя title[pre2] t := GetWindowText( h ) SetWindowText( h, t +": "+cFile ) // меняем текст Title [/pre2] У Андрея RDP есть и такая фишка может не прокатить, или на своем столе он увидит только свой explorer.exe

Haz: SergKis пишет: Вопрос от Андрея и меня, как получить hWnd от nId ? примерно так [pre2] Func Test local hWnd := 0 local aWin := {} local hPid, hProcess hPID := hb_processOpen( "Explorer.exe /select," + cFile,,,,.F., @hProcess) aWin := EnumWindows() for each hWnd in aWin if hPID == GetWindowThreadProcessID(hWnd) // тут и hWnd и hPID и hProcess можно дополнительно указать титл "Проводник" и ClassName окна "Static" ЧТОБ КНОПКИ ОТСЕЧЬ ? hWnd , hPID, hProcess end END return nil [/pre2] НЕ ПРОВЕРЯЛ , позже

Haz: Haz пишет: НЕ ПРОВЕРЯЛ , позже Проверил , EXPLORER так не выловить ! он как то хитро запускается что ID процесса не выдает корректно Любое другое приложение запускаясь ловится отлично

SergKis: Haz пишет Проверил , EXPLORER так не выловить ! он как то хитро запускается что ID процесса не выдает корректно Ерунда получается, ты прав.[pre2] nId := ShellExecuteEx( 0, "open", aCmd[1], aCmd[2]+' '+aCmd[3], , SW_SHOWNORMAL ) DO EVENTS ; wApi_Sleep(1000) IF !Empty(nId) //hProc := hb_processOpen( "explorer.exe "+'/select, ' + cFile, , , , .F., @nPID ) hProc := hb_processOpen( cCmd, , , , .F., @nPID ) hb_processClose(hProc) aWin := HandlesHbWin( , cClass, .T.) // снимок ? procName(),cClass,nId,hProc,nPID, aWin FOR EACH hWnd IN aWin GetWindowThreadProcessID(hWnd, @nTread, @nProcID) ? hb_EnumIndex(hWnd), hWnd,nTread, nPID, nProcID NEXT ENDIF результат: 1-ый запуск 1 15729718 CabinetWClass _ShellExecute RUNEXPLORFILE2EX CabinetWClass 1516 912 11968 ARRAY[1] 2-ой запуск 1 15729718 12672 11968 6252 1 16516746 CabinetWClass _ShellExecute 2 15729718 CabinetWClass _ShellExecute RUNEXPLORFILE2EX CabinetWClass 900 1564 3936 ARRAY[2] 1 16516746 12652 3936 4356 2 15729718 12672 3936 6252 [/pre2] Любое другое приложение запускаясь ловится отлично Вернусь к своей схеме, проверена, работает[pre2] ... aPos := HandlesHbWin( cFile, cClass, .T.) // снимок ДО для cFile, проверка 2-го запуска IF Len(aPos) > 0 ; RETURN .F. // уже есть такой ENDIF aOld := HandlesHbWin( , cClass, .T.) // снимок ДО nId := ShellExecuteEx( 0, "open", "explorer.exe", '/select,'+' '+cFile, , SW_SHOWNORMAL ) DO EVENTS ; wApi_Sleep(1000) // ждем прорисовки и форм. Title IF !Empty(nId) // запустилcя ok! aWin := HandlesHbWin( , cClass, .T.) // снимок ПОСЛЕ IF Len(aWin) > 1 FOR EACH hWnd IN aWin nPos := aScan(aOld, hWnd) IF ( lNew := nPos == 0 ) ; EXIT ENDIF NEXT ELSE lNew := .T. hWnd := aWin[1] ENDIF DO EVENTS ; wApi_Sleep(100) IF lNew i := 0 t := GetWindowText( hWnd ) SetWindowText( hWnd, t +": "+cFile ) // меняем текст Title DO EVENTS ; wApi_Sleep(100) WHILE !cFile $ GetWindowText( hWnd ) .and. i++ < 10 // проверяем Title SetWindowText( hWnd, t +": "+cFile ) DO EVENTS ; wApi_Sleep(100) END ENDIF ENDIF ... [/pre2]

Andrey: Haz пишет: Любое другое приложение запускаясь ловится отлично Что-то у меня не получается... Покажи код как ловиться ?

Haz: Andrey пишет: Что-то у меня не получается... Покажи код как ловиться ? [pre2] #include "common.ch" #include "i_winuser.ch" #include "hbthread.ch" Func Main local hWnd := 0 local aWin := {} local hPid, hProcess local nT, nP, cClassName hPID := hb_processOpen( "Notepad.exe",,,,.F., @hProcess) hb_idlesleep(1) aWin := EnumWindows() for each hWnd in aWin cClassName := GetClassName( hWnd ) if cClassName == "Notepad" GetWindowThreadProcessID(hWnd, @nT, @nP) if hProcess == nP ? "Вот оно окно , делай что хочешь hWnd = ", hWnd, cClassName end end END return nil [/pre2]

Haz: Сергей пишет: Ерунда получается, ты прав. При попытке запуска EXPLORER.EXE управление передается SVCHOST и из него дочерним процессом запускается EXPLORER Поэтому hPID и nProcess имеют значения отличные от получаемых в hb_ProcessOpen() Попытка трассировки ProcessID и ParentProcessID ничего не дает и уходит в WinInit Остается только твой вариант - перед запуском снимок окон пользователя с Wnd.ClassName = 'CabinetWClass' и отлов нового после запуска.

Andrey: Haz пишет: if cClassName == "Notepad" GetWindowThreadProcessID(hWnd, @nT, @nP) if hProcess == nP ? "Вот оно окно , делай что хочешь hWnd = ", hWnd, cClassName end end А если запущено уже несколько Notepad пользователем, то что будет ? Т.е. уже есть открытые Notepad и я запускаю свой. Хочу поменять титул окна, чтобы знать что это мой экземпляр и облом с этим действием. Рассматриваю Notepad в качестве примера.

SergKis: Andrey пишет Хочу поменять титул окна, чтобы знать что это мой экземпляр и облом с этим действием. Облома нет, все работает по схеме, как для explorer.exe выше, т.е. титул окна меняется [pre2] FUNCTION StartNotepad(cFile, cCapt) LOCAL nId, aWin, hWnd, lNew, nPos, aPos, aOld, i, t LOCAL cClass := "Notepad" // класс окна DEFAULT cFile := ".\demo2.prg" DEFAULT cCapt := cFile aPos := HandlesHbWin( cCapt, cClass, .T.) // снимок ДО для cFile, проверка 2-го запуска IF Len(aPos) > 0 ; RETURN .F. // уже есть такой ENDIF aOld := HandlesHbWin( , cClass, .T.) // снимок ДО nId := ShellExecuteEx( 0, "open", "notepad.exe", cFile, , SW_SHOWNORMAL ) DO EVENTS ; wApi_Sleep(500) // ждем прорисовки и форм. Title IF !Empty(nId) // запустился ok! aWin := HandlesHbWin( , cClass, .T.) // снимок ПОСЛЕ IF Len(aWin) > 1 FOR EACH hWnd IN aWin nPos := aScan(aOld, hWnd) IF ( lNew := nPos == 0 ) ; EXIT ENDIF NEXT ELSE lNew := .T. hWnd := aWin[1] ENDIF DO EVENTS ; wApi_Sleep(100) IF lNew i := 0 t := GetWindowText( hWnd ) SetWindowText( hWnd, t + cCapt ) // меняем текст Title DO EVENTS ; wApi_Sleep(100) WHILE !cFile $ GetWindowText( hWnd ) .and. i++ < 10 // проверяем Title SetWindowText( hWnd, t + cCapt ) DO EVENTS ; wApi_Sleep(100) END ENDIF ENDIF RETURN .T. Вызов, например, такой StartNotepad(".\demo2.hbp", " - my start !") [/pre2]

Andrey: SergKis пишет: Облома нет, все работает по схеме, как для explorer.exe выше, т.е. титул окна меняется Только что попробовал, вот результат - титул окна НЕ МЕНЯЕТСЯ : [pre2] 1 526190 Notepad _a.txt – Блокнот 2 395100 Notepad _a4.txt – Блокнот 1 526190 Notepad _a.txt – Блокнот 2 395100 Notepad _a4.txt – Блокнот 1 329742 Notepad Demo2.hbp – Блокнот 2 526190 Notepad _a.txt – Блокнот 3 395100 Notepad _a4.txt – Блокнот ----- Вызов из: TEST_3(711) -> demo2.prg hProcessHandleShellExecuteEx= NIL [/pre2]

SergKis: Andrey пишет Только что попробовал, вот результат - титул окна НЕ МЕНЯЕТСЯ : Смотри на окне Notepad запущенного + смотри в списке процессов на кнопке (1), нажимая кнопку "Reset", можешь задать текст справа внизу в GETBOX "note" и нажать кнопку "Reset". Для фильтра процессов. А то что ты смотришь в логе - так там делать надо, там ничего нет Пример тут https://TransFiles.ru/o72ak Кнопка 4) ... - запуск Notepad.exe PS Текст в GETBOX тебе надо задавать на рус. "блок" Класс для notepad.exe у тебя ? У меня "Notepad" PS2 добавил вывод в log[pre2] FUNCTION StartNotepad(cFile, cCapt) ... IF lNew ... END ? procname(), GetWindowText( hWnd ) ENDIF результат 1 29820426 Notepad Demo2.hbp - Notepad STARTNOTEPAD Demo2.hbp - Notepad - my start ! ----- Вызов из: TEST_3(665) -> demo2.prg hProcessHandleShellExecuteEx= NIL [/pre2]

Haz: Andrey пишет: А если запущено уже несколько Notepad пользователем, то что будет ? а что будет результатом такой проверки ? [pre2] GetWindowThreadProcessID(hWnd, @nT, @nP) if hProcess == nP ? "Вот оно окно , делай что хочешь hWnd = ", hWnd, cClassName end [/pre2]

SergKis: Haz пишет if hProcess == nP ? "Вот оно окно , делай что хочешь hWnd = ", hWnd, cClassName end Что бы делать, что хочешь, надо, как правило, подождать, дать сформироваться окну и его Title Например у Explorer.exe проскакивают 2-а Title (что я поймал), если не ждать wApi_Sleep(1000), и сразу ставить свой, то не получится контролировать 2-ой свой запуск. Т.е. возврат от ShellExecuteEx() говорит лишь о том, что запуск произошел или нет. Это ремарка

Haz: все просто , на передний план, но без hWhd И соответственно без операций с окном ( титлы, размер и пр ) [pre2] SetForegroundWindow(GetDesktopWindow()) hPID := hb_processOpen( "explorer.exe /select," + cFile,,,,.F., @hProcess) // откроет explorer на переднем плане окон // Дальше по тексту // [/pre2]

SergKis: Haz пишет все просто , на передний план, но без hWhd И соответственно без операций с окном ( титлы, размер и пр ) Ни разу не нужно было запускать explorer.exe или notepad.exe, как в примерах. А вот с DosBox и консольными старыми clipper программами под ним + vwt подпрограммы - это сколько угодно, даже размеры и позиции окон приходилось ставить. И SetForegroundWindow(GetDesktopWindow()) не на всех 10-ках срабатывал, приходилось minimaize, restore еще делать до того.

Haz: SergKis пишет: приходилось minimaize, restore еще делать до того. не вопрос , тогда так ( вместо SetForgeroundWindow() - любые действия с хендлом ) [pre2] Func Main local hWnd := 0 local aWin := {} local hPid, hProcess local cFile := "C:\HmG_PROJECT\Z.CMD" // Здесь свой файл указать local aArray := hb_Atokens( cFile , "\" ) local cText := aArray[Len(aArray)-1] hPID := hb_processOpen( "explorer.exe /select," + cFile,,,,.F., @hProcess) hb_idlesleep(1) aWin := EnumWindows() for each hWnd in aWin if UPPER(GetWindowText(hWnd)) == UPPER( cText ) SetWindowText( hWnd, aArray[Len(aArray)]) // или свой текст SetForegroundWindow(hWnd) // или minimaize, restore end END return nil [/pre2]

SergKis: Haz пишет не вопрос , тогда так ( вместо SetForgeroundWindow() - любые действия с хендлом ) Вопросы остаются. cFile := "C:\HmG_PROJECT\Z.CMD". Запуск "explorer.exe /select," + cFile даст в title имя каталога HmG_PROJECT cFile := "C:\HmG_PROJECT\demo.hbp". Запуск "explorer.exe /select," + cFile даст в title имя каталога HmG_PROJECT тоже повторные запуски будут с аналогичным результатом и т.д. Для notepad.exe то же самое, т.е. управления нет и надо добавлять. В примере выше это и показано, есть запуски многократные, есть контролируемые. Т.е. у меня вопросы по GetWindowThreadProcessId(h, @nThr, @nPid) сняты. Спасибо

Andrey: А как можно узнать по хендлу полный путь запущенной программы ? Поискал в примерах, но там что-то непонятно как это делается...

Haz: Andrey пишет: как можно узнать по хендлу полный путь запущенной программы По хендлу чего ? Окна ? Процесса ? Если процесса, самый простой путь через wmi Select * from win32_process . Если хендлу окна, то сначала ищем процесс (как выше писали ) , а потом пять wmi

Andrey: Haz пишет: По хендлу чего ? Окна ? Процесса ? Если процесса, самый простой путь через wmi По хендлу окна. Вроде нашёл - GetFullFileNameByHandle (aWin , @cFullFileName) Правильно ли я делаю ?[pre2] LOCAL oTsb := oHmgData() LOCAL cSuperHd := oWnd:Cargo:cTitle LOCAL cTitle, aWin, hWnd, nThr, nPid, cClass, cFullFileName, aProcess aProcess := {} aWin := EnumWindows() For each hWnd in aWin cClass := GetClassName( hWnd ) cTitle := GetWindowText( hWnd ) GetWindowThreadProcessID(hWnd, @nThr, @nPid) GetFullFileNameByHandle (hWnd, @cFullFileName) AADD( aProcess, { hWnd, nThr, nPid, cClass, cTitle, cFullFileName } ) Next ? "aProcess=",aProcess ; ?v aProcess ; ?[/pre2] Получается непонятка у меня: В проводнике по другому, ну это понятно... А почему строка 'Процессы в памяти: hWnd, nTread, nPID, nProcID' непонятно кому принадлежит ?

SergKis: Andrey пишет А почему строка 'Процессы в памяти: hWnd, nTread, nPID, nProcID' непонятно кому принадлежит ? Почему не понятно принадлежность указанного, не знаю , но кнопку добавлял ты сам ручками [pre2] @ nY, nX BUTTONEX Btn_5 WIDTH nWBtn HEIGHT nHBtn ; CAPTION '(5)' ACTION _wPost(5, , This.Name) ; TOOLTIP 'Процессы в памяти: hWnd, nTread, nPID, nProcID' [/pre2]

Andrey: Т.е. нажатая кнопка на форме тоже отображается в процессах ? Другие кнопки не показываются. Фигня какая то получается. А почему стандартный проводник этого не отображает ?

Haz: Andrey пишет: проводнике по другому, ну это понятно. в диспетчере задач не тот хендл указан , нуля не хватает

Andrey: Haz пишет: нуля не хватает Проглядел...



полная версия страницы