Question

I'm having problem using the Navigate Shell command when the path include an # sign.

; this will create 2 folders at the root of your C: drive
myPath1 := "C:\delete_me\"
myPath2 := "C:\delete#me\"
if !FileExist(myPath1)
    FileCreateDir, %myPath1%
if !FileExist(myPath2)
    FileCreateDir, %myPath2%
; make an Explorer active and press Alt-1 and Alt-2
return

!1::
strWinId := WinExist("A")
TrayTip, %myPath1%, %strWinId%
For pExp in ComObjCreate("Shell.Application").Windows
    if (pExp.hwnd = strWinId)
        try pExp.Navigate(myPath1)
return

!2::
strWinId := WinExist("A")
TrayTip, %myPath2%, %strWinId%
For pExp in ComObjCreate("Shell.Application").Windows
    if (pExp.hwnd = strWinId)
        try pExp.Navigate(myPath2)
return

Alt-1 works well. But, with Alt-2, the Navigate command returns "file:///C:/delete#me/ » not found.".

If there is no "/" after the "#" (eg myPath := "C:\delete#me"), it works. But this cannot be a solution because the destination path can be deeper in a subfolder (eg. "C:\delete#me\xyz").

I tried to encode the "#", replacing it with "%23", without success. Found nothing on the web or MSDN about that. Any idea?

[keywords: haskmark, hashtag, number sign or pound]

Was it helpful?

Solution 2

If you want to open a new window, there's no need for COM or unreliable workarounds: just run the folder.

Run C:\delete#me

If you want to open the path in an existing window which is already active, the simplest and most effective workaround is this:

SendInput {F4}{Esc}{Raw}C:\delete#me`n

So in the context of your script, you could use the following function to work around the # when it is present:

Navigate(pExp, myPath2)

;...

Navigate(Exp, Path)
{
    if RegExMatch(Path, "#.*\\")
        SendInput {F4}{Esc}{Raw}%Path%`n
    else
        Exp.Navigate(Path)
}

OTHER TIPS

I have what looks to be a working solution for this, which I've also posted here:

4 options to change the current folder in Windows Explorer - Page 3 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=526&p=153676#p153676

;links:
;Explorer Windows Manipulations - Page 5 - Scripts and Functions - AutoHotkey Community
;https://autohotkey.com/board/topic/19039-explorer-windows-manipulations/page-5#entry297581
;Navigate2 Method (IWebBrowser2)
;https://msdn.microsoft.com/en-us/library/aa752134(v=vs.85).aspx
;4 options to change the current folder in Windows Explorer - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=5&t=526
;windows - Navigate Shell command not working when the path includes an hash - Stack Overflow
;https://stackoverflow.com/questions/22868546/navigate-shell-command-not-working-when-the-path-includes-an-hash

;an AutoHotkey v1.1 script
;note: will create folder: %A_Desktop%\abc#def\abc#def
;q:: ;explorer - navigate to folder (tested on Windows 7)
WinGet, hWnd, ID, A
WinGetClass, vWinClass, % "ahk_id " hWnd
if !(vWinClass = "CabinetWClass") && !(vWinClass = "ExploreWClass")
    return

vDir = %A_Desktop%\abc#def\abc#def
;vDir = %A_Desktop%\abc def\abc def
if !FileExist(vDir)
    FileCreateDir, % vDir

DllCall("shell32\SHParseDisplayName", WStr,vDir, Ptr,0, PtrP,vPIDL, UInt,0, Ptr,0)
for oWin in ComObjCreate("Shell.Application").Windows
    if (oWin.HWND = hWnd)
    {
        if !InStr(vDir, "#")
            oWin.Navigate(vDir)
        else
        {
            VarSetCapacity(SAFEARRAY, A_PtrSize=8?32:24, 0)
            NumPut(1, SAFEARRAY, 0, "UShort")
            NumPut(1, SAFEARRAY, 4, "UShort")
            NumPut(vPIDL, SAFEARRAY, A_PtrSize=8?16:12, "Ptr")
            NumPut(DllCall("shell32\ILGetSize", Ptr,vPIDL, UInt), SAFEARRAY, A_PtrSize=8?24:16, "Int")
            oWin.Navigate2(ComObject(0x2011,&SAFEARRAY))
            DllCall("shell32\ILFree", Ptr,vPIDL)
        }
        break
    }
return

Unfortunately, there does not seem to be a solution to this. Shell.Application Navigate command fails if the path includes a hash (# as in C:\C#Projects).

Using AutoHotkey, the workaround would be to rely on the "second best" approach as identified by the tests in this thread: http://ahkscript.org/boards/viewtopic.php?f=5&t=526.

run, Explorer.exe
Sleep, 500
strFolder := A_ScriptDir
Send, {F4}{Esc}
Sleep, 500
ControlSetText, Edit1, C:\delete#me, A
ControlSend, Edit1, {Enter}, A

When I saw that Navigate couldn't handle hash, I was shocked, but sure enough I replicated the error. I thought I'd try the short form path just in case. It works!

if vDir contains #
Loop, %vDir%, 2, 0 ;(0/1/2=files/both/folders, 0/1=recurse no/yes)
vDir := A_LoopFileShortPath
  • The following approach doesn't require a visible address bar, or SendInput, also the previous navigation history is maintained.
  • In the worst-case scenario of a hash in the short-form path of the dir above the target dir, a go-between folder is used which is navigated to.
  • A link is created there, invoked, and deleted.
  • Below, the workaround code is indented, to separate it from the standard code.
  • A hotkey of ctrl+q, when an Explorer window is active, launches the script.

-

^q:: ;explorer - navigate to directory (use go-between dir if short-form path of dir above target contains #)
WinGet, hWnd, ID, A
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass not in CabinetWClass,ExploreWClass
Return

vDir2 = %A_Desktop%\Go-Between ;go-between dir
vDir3 = C:\delete#me ;target dir

if (SubStr(vDir3, 1-1) = "\")
vDir3 := SubStr(vDir3, 1, -1)
if !InStr(FileExist(vDir3), "D")
Return

    vPathLnk := ""

    if vDir3 contains #
    Loop, %vDir3%, 2, 0 ;(0/1/2=files/both/folders, 0/1=recurse no/yes)
    vDir3 := A_LoopFileShortPath

    ;vDir4 is the short-form path of the dir above the target
    ;paths of problem target dirs are of the form: *#*\*
    ;where there is at least one hash with a backslash to its right
    SplitPath, vDir3, , vDir4
    if vDir4 contains #
    {
    if !InStr(FileExist(vDir2), "D")
    FileCreateDir, %vDir2%
    if !InStr(FileExist(vDir2), "D")
    {
    MsgBox error`, go-between dir not found:`r`n%vDir2%
    Return
    }
    vNameLnk = Go-Between.lnk
    vPathLnk = %vDir2%\%vNameLnk%
    FileCreateShortcut, %vDir3%, %vPathLnk%
    }

for oWin in ComObjCreate("Shell.Application").Windows
if (hWnd = oWin.Hwnd)
{
vDir1 := oWin.Document.Folder.Self.Path
if (vDir1 = vDir3)
break

    if vDir3 contains #
    {
    if !(vDir1 = vDir2)
    oWin.Navigate(vDir2)
    while !(oWin.ReadyState = 4)
    Sleep 10

    oItem := oWin.Document.Folder.Items.Item(vNameLnk)
    oItem.InvokeVerbEx("open")
    break
    }

oWin.Navigate(vDir3)
break
}

oWin := ""

    if !(vPathLnk = "")
    FileRecycle, %vPathLnk% ;send to recycle bin
    ;if !(vPathLnk = "")
    ;FileDelete, %vPathLnk% ;delete
Return
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top