#NoTrayIcon
#Include <WindowsConstants.au3>
Opt('MustDeclareVars', 1)
Opt('WinTitleMatchMode', 3)
Opt('WinWaitDelay', 0)
Global Const $GUI_NAME = 'MoveUp#ZdwRqp10'
Global $aList[1] = [0], $aTemp, $tCOPYDATA, $tData, $hWnd
$hWnd = WinGetHandle($GUI_NAME)
If $CmdLine[0] Then
If $CmdLine[1] = '/startup' Then
If $hWnd Then
Exit
EndIf
Else
If $hWnd Then
$tCOPYDATA = DllStructCreate('ulong_ptr;dword;ptr')
$tData = DllStructCreate('wchar[' & StringLen($CmdLine[1]) + 1 & ']')
DllStructSetData($tData, 1, $CmdLine[1])
DllStructSetData($tCOPYDATA, 2, DllStructGetSize($tData))
DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tData))
DllCall('user32.dll', 'lresult', 'SendMessage', 'hwnd', $hWnd, 'uint', $WM_COPYDATA, 'ptr', 0, 'ptr', DllStructGetPtr($tCOPYDATA))
; If @error Then
;
; EndIf
EndIf
Exit
EndIf
Else
Exit
EndIf
Opt('TrayIconHide', 0)
$hWnd = GUICreate($GUI_NAME)
GUIRegisterMsg($WM_COPYDATA, 'WM_COPYDATA')
While 1
Sleep(100)
If $aList[0] Then
$aTemp = $aList
$aList[0] = 0
For $i = 1 To $aTemp[0]
MsgBox(0, '', $aTemp[$i])
; Здесь копируем очередной файл $aTemp[$i] на уровень выше!
Next
EndIf
WEnd
Func WM_COPYDATA($hWnd, $iMsg, $wParam, $lParam)
Local $tCOPYDATA = DllStructCreate('ulong_ptr;dword;ptr', $lParam)
$aList[0] += 1
ReDim $aList[$aList[0] + 1]
$aList[$aList[0]] = DllStructGetData(DllStructCreate('wchar[' & DllStructGetData($tCOPYDATA, 2) & ']', DllStructGetData($tCOPYDATA, 3)), 1)
Return 1
EndFunc ;==>WM_COPYDATA
@for %%f in (%*) do @move /-Y %%f "%%~dpf..\"
кто-нибудь из форумчан поможет
Наврядли получится, скрипт должен будет висеть в процессах и ждать вызова г.клавиши.скрипт запускался бы только на какую-то секунду и только тогда, когда это бы требовалось.
Ну ты же написал, что там оно не нужно:почему тогда вот в этом случае скрипту не нужно висеть в процессах?
по горячей клавише почти всегда всё проще (к слову, я их себе понастраивал не один десяток), но не в этот раз
$hExplorer = WinGetHandle("[CLASS:ExplorerWClass]")
If @error Then $hExplorer = WinGetHandle("[CLASS:CabinetWClass]")
$aSelected_Files = _ExplorerGetSelectedItems($hExplorer)
If @error Then
MsgBox(48, "Error", "It seems that there is no selected files, but also it can be an internal function error.")
Exit
EndIf
$sExistingFiles = ""
$sParentPath = StringRegExpReplace($aSelected_Files[1][2], "\\[^\\]*\\[^\\]*$", "")
For $i = 1 To $aSelected_Files[0][0]
$sFileName = StringRegExpReplace($aSelected_Files[$i][2], "^.*\\", "")
If FileExists($sParentPath & "\" & $sFileName) Then
$sExistingFiles &= $sFileName & @CRLF
ContinueLoop
EndIf
If $aSelected_Files[$i][1] = 1 Then
DirMove($aSelected_Files[$i][2], $sParentPath)
Else
FileMove($aSelected_Files[$i][2], $sParentPath)
EndIf
Next
If $sExistingFiles <> "" Then
MsgBox(48, "Attention", StringFormat("The following objects already exists in the parent folder\n[%s]\nMoving was not performed:\n\n%s", $sParentPath, $sExistingFiles))
EndIf
;[0][0] = Total items count
;[N][0] = Selected element Index
;[N][1] = Selected element is Directory
;[N][2] = Selected element string (full path to the file/dir)
Func _ExplorerGetSelectedItems($hWnd="[CLASS:CabinetWClass]")
Local $aRetInfo[1][1]
Local $aIndexes, $iIndex, $iCount, $sSelected, $sSelected_Path
Local $hSearch, $sCurrentFile
If Not IsHWnd($hWnd) Then
$hWnd = WinGetHandle($hWnd)
EndIf
$sSelected_Path = _GetWindowsExplorerPath($hWnd)
$sSelected_Path = StringRegExpReplace($sSelected_Path, "\\+$", "")
$aIndexes = StringSplit(ControlListView($hWnd, "", "SysListView321", "GetSelected", 1), "|")
If $aIndexes[1] = "" Then
Return SetError(1, 0, 0)
EndIf
Dim $aRetInfo[$aIndexes[0]+1][3]
For $i = 1 To $aIndexes[0]
$sSelected = ControlListView($hWnd, "", "SysListView321", "GetText", $aIndexes[$i])
$sCurrentFile = $sSelected_Path & "\" & $sSelected
If Not FileExists($sCurrentFile) Then ;Search the extension for file...
$hSearch = FileFindFirstFile($sCurrentFile & ".*")
If $hSearch <> -1 Then
$sCurrentFile = $sSelected_Path & "\" & FileFindNextFile($hSearch)
FileClose($hSearch)
EndIf
EndIf
$aRetInfo[0][0] += 1
$aRetInfo[$aRetInfo[0][0]][0] = $aIndexes[$i] ;Index
$aRetInfo[$aRetInfo[0][0]][1] = Number(StringInStr(FileGetAttrib($sCurrentFile), "D") > 0) ;Is Directory
$aRetInfo[$aRetInfo[0][0]][2] = $sCurrentFile ;Selected file / dir
Next
If $aRetInfo[0][0] = 0 Then
Return SetError(2, 0, 0)
EndIf
ReDim $aRetInfo[$aRetInfo[0][0]+1][3]
Return $aRetInfo
EndFunc
; ==================================================================================================
; Func _GetWindowsExplorerPath($hWnd)
;
; Function to get the path currently being explored by a Windows Explorer window
;
; $hWnd = Handle to the Windows Explorer window
;
; Returns:
; Success: String - Path being explored by this window
; Failure: "" empty string, with @error set:
; @error = 1 = This is not a valid explorer window
; @error = 2 = DLL call error, use _WinAPI_GetLastError()
;
; Author: WideBoyDixon
; ==================================================================================================
Func _GetWindowsExplorerPath($hWnd)
Local $pv, $pidl, $return = "", $ret, $hMem, $pid, $folderPath = DllStructCreate("char[260]"), $className
Local $bPIDL = False
Local Const $CWM_GETPATH = 0x400 + 12;
; Check the classname of the window first
$className = DllCall("user32.dll", "int", "GetClassName", "hwnd", $hWnd, "str", "", "int", 4096)
If @error Then Return SetError(2, 0, "")
If ($className[2] <> "ExploreWClass" And $className[2] <> "CabinetWClass") Then Return SetError(1, 0, "")
; Retrieve the process ID for our process
$pid = DllCall("kernel32.dll", "int", "GetCurrentProcessId")
If @error Then Return SetError(2, 0, "")
; Send the CWM_GETPATH message to the window
$hMem = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hWnd, "int", $CWM_GETPATH, "wparam", $pid[0], "lparam", 0)
If @error Then Return SetError(2, 0, "")
If $hMem[0] = 0 Then Return SetError(1, 0, "")
; Lock the shared memory
$pv = DllCall("shell32.dll", "ptr", "SHLockShared", "uint", $hMem[0], "uint", $pid[0])
If @error Then Return SetError(2, 0, "")
If $pv[0] Then
$pidl = DllCall("shell32.dll", "ptr", "ILClone", "uint", $pv[0]) ; Clone the PIDL
If @error Then Return SetError(2, 0, "")
$bPIDL = True
DllCall("shell32.dll", "int", "SHUnlockShared", "uint", $pv) ; Unlock the shared memory
EndIf
DllCall("shell32.dll", "int", "SHFreeShared", "uint", $hMem, "uint", $pid) ; Free the shared memory
If $bPIDL Then
; Retrieve the path from the PIDL
$ret = DllCall("shell32.dll", "int", "SHGetPathFromIDList", "ptr", $pidl[0], "ptr", DllStructGetPtr($folderPath))
If (@error = 0) And ($ret[0] <> 0) Then $return = DllStructGetData($folderPath, 1) ; Retrieve the value
DllCall("shell32.dll", "none", "ILFree", "ptr", $pidl[0]) ; Free up the PIDL that we cloned
Return SetError(0, 0, $return) ; Success
EndIf
Return SetError(2, 0, "") ; Failed a WinAPI call
EndFunc
Впринципе достаточно убрать последний параметр у функций Dir/FileCopy.нужно, чтобы в случае, если в целевой папке объекты с аналогичными названиями ужé существуют, никаких перемещений не происходило
Тогда нужна проверка, поправил.отображалось окно с надписью
Это нужно уточнять сразу, в первом сообщений.если у каких-то файлов названия совпадают, а у других - нет, то те, у которых названия не совпадают, перемещаются
Тогда нужно сначала проверять файлы...если совпадает название хотя бы одного файла/папки, то ничего не перемещается
Так и есть.при этом в окне упоминаются и перечисляются совпадения и файлов, и папок
Потому что не было указано название папки назначения.почему-то папки не перемещаются вообще
$hExplorer = WinGetHandle("[CLASS:ExplorerWClass]")
If @error Then $hExplorer = WinGetHandle("[CLASS:CabinetWClass]")
$aSelected_Files = _ExplorerGetSelectedItems($hExplorer)
If @error Then
MsgBox(48, "Error", "It seems that there is no selected files, but also it can be an internal function error.")
Exit
EndIf
$sExistingFiles = ""
$sParentPath = StringRegExpReplace($aSelected_Files[1][2], "\\[^\\]*\\[^\\]*$", "")
For $i = 1 To $aSelected_Files[0][0]
$sFileName = StringRegExpReplace($aSelected_Files[$i][2], "^.*\\", "")
If FileExists($sParentPath & "\" & $sFileName) Then
$sExistingFiles &= $sFileName & @CRLF
EndIf
Next
If $sExistingFiles <> "" Then
MsgBox(48, "Move Selected Files - Attention", _
StringFormat("The following objects already exists in the parent folder\n(%s)\nMoving was not performed:\n\n%s", $sParentPath, $sExistingFiles))
Exit
EndIf
For $i = 1 To $aSelected_Files[0][0]
$sFileName = StringRegExpReplace($aSelected_Files[$i][2], "^.*\\", "")
If $aSelected_Files[$i][1] = 1 Then
DirMove($aSelected_Files[$i][2], $sParentPath & "\" & $sFileName)
Else
FileMove($aSelected_Files[$i][2], $sParentPath & "\" & $sFileName)
EndIf
Next
;[0][0] = Total items count
;[N][0] = Selected element Index
;[N][1] = Selected element is Directory
;[N][2] = Selected element string (full path to the file/dir)
Func _ExplorerGetSelectedItems($hWnd="[CLASS:CabinetWClass]")
Local $aRetInfo[1][1]
Local $aIndexes, $iIndex, $iCount, $sSelected, $sSelected_Path
Local $hSearch, $sCurrentFile
If Not IsHWnd($hWnd) Then
$hWnd = WinGetHandle($hWnd)
EndIf
$sSelected_Path = _GetWindowsExplorerPath($hWnd)
$sSelected_Path = StringRegExpReplace($sSelected_Path, "\\+$", "")
$aIndexes = StringSplit(ControlListView($hWnd, "", "SysListView321", "GetSelected", 1), "|")
If $aIndexes[1] = "" Then
Return SetError(1, 0, 0)
EndIf
Dim $aRetInfo[$aIndexes[0]+1][3]
For $i = 1 To $aIndexes[0]
$sSelected = ControlListView($hWnd, "", "SysListView321", "GetText", $aIndexes[$i])
$sCurrentFile = $sSelected_Path & "\" & $sSelected
If Not FileExists($sCurrentFile) Then ;Search the extension for file...
$hSearch = FileFindFirstFile($sCurrentFile & ".*")
If $hSearch <> -1 Then
$sCurrentFile = $sSelected_Path & "\" & FileFindNextFile($hSearch)
FileClose($hSearch)
EndIf
EndIf
$aRetInfo[0][0] += 1
$aRetInfo[$aRetInfo[0][0]][0] = $aIndexes[$i] ;Index
$aRetInfo[$aRetInfo[0][0]][1] = Number(StringInStr(FileGetAttrib($sCurrentFile), "D") > 0) ;Is Directory
$aRetInfo[$aRetInfo[0][0]][2] = $sCurrentFile ;Selected file / dir
Next
If $aRetInfo[0][0] = 0 Then
Return SetError(2, 0, 0)
EndIf
ReDim $aRetInfo[$aRetInfo[0][0]+1][3]
Return $aRetInfo
EndFunc
; ==================================================================================================
; Func _GetWindowsExplorerPath($hWnd)
;
; Function to get the path currently being explored by a Windows Explorer window
;
; $hWnd = Handle to the Windows Explorer window
;
; Returns:
; Success: String - Path being explored by this window
; Failure: "" empty string, with @error set:
; @error = 1 = This is not a valid explorer window
; @error = 2 = DLL call error, use _WinAPI_GetLastError()
;
; Author: WideBoyDixon
; ==================================================================================================
Func _GetWindowsExplorerPath($hWnd)
Local $pv, $pidl, $return = "", $ret, $hMem, $pid, $folderPath = DllStructCreate("char[260]"), $className
Local $bPIDL = False
Local Const $CWM_GETPATH = 0x400 + 12;
; Check the classname of the window first
$className = DllCall("user32.dll", "int", "GetClassName", "hwnd", $hWnd, "str", "", "int", 4096)
If @error Then Return SetError(2, 0, "")
If ($className[2] <> "ExploreWClass" And $className[2] <> "CabinetWClass") Then Return SetError(1, 0, "")
; Retrieve the process ID for our process
$pid = DllCall("kernel32.dll", "int", "GetCurrentProcessId")
If @error Then Return SetError(2, 0, "")
; Send the CWM_GETPATH message to the window
$hMem = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hWnd, "int", $CWM_GETPATH, "wparam", $pid[0], "lparam", 0)
If @error Then Return SetError(2, 0, "")
If $hMem[0] = 0 Then Return SetError(1, 0, "")
; Lock the shared memory
$pv = DllCall("shell32.dll", "ptr", "SHLockShared", "uint", $hMem[0], "uint", $pid[0])
If @error Then Return SetError(2, 0, "")
If $pv[0] Then
$pidl = DllCall("shell32.dll", "ptr", "ILClone", "uint", $pv[0]) ; Clone the PIDL
If @error Then Return SetError(2, 0, "")
$bPIDL = True
DllCall("shell32.dll", "int", "SHUnlockShared", "uint", $pv) ; Unlock the shared memory
EndIf
DllCall("shell32.dll", "int", "SHFreeShared", "uint", $hMem, "uint", $pid) ; Free the shared memory
If $bPIDL Then
; Retrieve the path from the PIDL
$ret = DllCall("shell32.dll", "int", "SHGetPathFromIDList", "ptr", $pidl[0], "ptr", DllStructGetPtr($folderPath))
If (@error = 0) And ($ret[0] <> 0) Then $return = DllStructGetData($folderPath, 1) ; Retrieve the value
DllCall("shell32.dll", "none", "ILFree", "ptr", $pidl[0]) ; Free up the PIDL that we cloned
Return SetError(0, 0, $return) ; Success
EndIf
Return SetError(2, 0, "") ; Failed a WinAPI call
EndFunc
извиняюсь, просто бывает, что не всё требуемое от скрипта сразу осознаёшь чётко, а вот когда он обрёл форму и его можно ужé пробовать, разные нюансы могут стать значимымиЭто нужно уточнять сразу, в первом сообщений.
похоже, что нет. потратил я некоторое время на проверку - всё работает как надо, благодарю ;)Есть ещё какие то условия которые нужно учесть?
If $sExistingFiles <> "" Then
MsgBox(48, "Move Selected Files - Attention", _
StringFormat("The following objects already exists in the parent folder\n(%s)\nMoving was not performed:\n\n%s", $sParentPath, $sExistingFiles))
Exit
EndIf
If $sExistingFiles <> "" Then
MsgBox(262144, "", _
StringFormat("folder %s\n\nalready contains objects:\n\n%s", $sParentPath, $sExistingFiles))
Exit
EndIf
Скрипт отлично справляется с переносом файловAlexey сказал(а):однако, к сожалению, всё это не подходит. хотя бы потому что есть гораздо более простой способ с использованием контекстного меню:
создать, например, move-up.bat со строкой
и закинуть его в папку Send ToКод:@for %%f in (%*) do @move /-Y %%f "%%~dpf..\"