命令提示符的标题问题

编程语言 2026-07-09

我正在开发一个小型的C++快捷键应用程序。我要添加的其中一个快捷键是 Ctrl+Alt+E。我希望它在有焦点的CMD窗口时,获取当前工作目录(CWD),并在该目录下打开一个文件资源管理器。

使用这个函数:

static std::string GetConsoleCwd()
{
    HWND fw = GetForegroundWindow();
    if (!fw)
        return "";

    char cls[64]{};
    GetClassNameA(fw, cls, sizeof(cls));
    if (strcmp(cls, "ConsoleWindowClass") != 0 &&
        strcmp(cls, "CASCADIA_HOSTING_WINDOW_CLASS") != 0)
        return "";

    char title[MAX_PATH]{};
    GetWindowTextA(fw, title, sizeof(title));
    if (!title[0])
        return "";

    std::string t(title);

    // Try to find any substring that looks like a valid path
    // Look for "X:\" pattern (drive letter + colon + backslash)
    size_t drivePos = std::string::npos;
    for (size_t i = 0; i + 2 < t.size(); i++)
    {
        if (t[i] == ':' && t[i + 1] == '\\' && i >= 1 && isalpha((unsigned char)t[i - 1]))
        {
            // Found something like "C:\" — backtrack to start of this path segment
            size_t start = i - 1;
            while (start > 0 && t[start - 1] != ' ' && t[start - 1] != '-')
                start--;
            std::string candidate = t.substr(start);
            // Trim trailing prompt junk
            while (!candidate.empty() && (candidate.back() == '>' || candidate.back() == ' '))
                candidate.pop_back();
            DWORD attr = GetFileAttributesA(candidate.c_str());
            if (attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY))
                return candidate;
        }
    }

    return "";
}

但我有一个问题,与代码本身关系不大。这个快捷键在我手动使用title命令设置标题时可以工作;但出于某种原因,在执行cd命令后,命令提示符的标题并不会自动显示CWD,它只显示Command Prompt,有时甚至在执行命令后仍然显示Select Command Prompt。
doskey cd = cd $\* ^& title %cd%

这个问题仍然没有解决。这个问题的解决办法是什么,这样在我发布这个工具时,其他人就不会再遇到这个问题。获取CWD的更好方法是什么?

解决方案

#define WOW64_POINTER(Type) ULONG

struct CURDIR32
{
    UNICODE_STRING32 DosPath;
    ULONG Handle;
};

typedef struct _RTL_USER_PROCESS_PARAMETERS32
{
    ULONG MaximumLength;
    ULONG Length;

    ULONG Flags;
    ULONG DebugFlags;

    WOW64_POINTER(HANDLE) ConsoleHandle;
    ULONG ConsoleFlags;
    WOW64_POINTER(HANDLE) StandardInput;
    WOW64_POINTER(HANDLE) StandardOutput;
    WOW64_POINTER(HANDLE) StandardError;

    CURDIR32 CurrentDirectory;
} RTL_USER_PROCESS_PARAMETERS32, *PRTL_USER_PROCESS_PARAMETERS32;

struct PEB32
{
    BOOLEAN InheritedAddressSpace;
    BOOLEAN ReadImageFileExecOptions;
    BOOLEAN BeingDebugged;
    union
    {
        BOOLEAN BitField;
        struct
        {
            BOOLEAN ImageUsesLargePages : 1;
            BOOLEAN IsProtectedProcess : 1;
            BOOLEAN IsImageDynamicallyRelocated : 1;
            BOOLEAN SkipPatchingUser32Forwarders : 1;
            BOOLEAN IsPackagedProcess : 1;
            BOOLEAN IsAppContainer : 1;
            BOOLEAN IsProtectedProcessLight : 1;
            BOOLEAN IsLongPathAwareProcess : 1;
        };
    };
    WOW64_POINTER(HANDLE) Mutant;

    WOW64_POINTER(PVOID) ImageBaseAddress;
    WOW64_POINTER(PPEB_LDR_DATA) Ldr;
    WOW64_POINTER(PRTL_USER_PROCESS_PARAMETERS) ProcessParameters;
};

NTSTATUS GetCWD32(_In_ HANDLE hProcess, _In_ PEB32* WowPeb, _Out_ PUNICODE_STRING DosPath)
{
    UNICODE_STRING32 DosPath32;
    RTL_USER_PROCESS_PARAMETERS32* ProcessParameters = 0;

    NTSTATUS status;
    if (0 <= (status = ZwReadVirtualMemory(hProcess, (PVOID)(ULONG_PTR)&WowPeb->ProcessParameters, 
        &ProcessParameters, sizeof(ULONG), 0)) &&
        0 <= (status = ZwReadVirtualMemory(hProcess, &ProcessParameters->CurrentDirectory.DosPath, 
        &DosPath32, sizeof(DosPath32), 0)))
    {
        if (ULONG Length = DosPath32.Length)
        {
            status = STATUS_UNSUCCESSFUL;

            if (!(Length & (sizeof(WCHAR) - 1)) && Length < MAXUSHORT)
            {
                status = STATUS_NO_MEMORY;
                if (PWSTR Buffer = (PWSTR)LocalAlloc(LMEM_FIXED, Length + sizeof(WCHAR)))
                {
                    if (0 <= (status = ZwReadVirtualMemory(hProcess, (PVOID)(ULONG_PTR)DosPath32.Buffer, Buffer, Length, 0)))
                    {
                        *reinterpret_cast<PWSTR>(RtlOffsetToPointer(Buffer, Length)) = 0;
                        DosPath->Length = (USHORT)Length;
                        DosPath->MaximumLength = (USHORT)Length + sizeof(WCHAR);
                        DosPath->Buffer = Buffer, Buffer = 0;
                    }
                    LocalFree(Buffer);
                }
            }
        }
        else
        {
            DosPath->Buffer = 0;
            DosPath->MaximumLength = 0;
        }
    }

    return status;
}

NTSTATUS GetCWD64(_In_ HANDLE hProcess, _Out_ PUNICODE_STRING DosPath)
{
    union {
        _RTL_USER_PROCESS_PARAMETERS* ProcessParameters;
        PROCESS_BASIC_INFORMATION pbi;
    };

    NTSTATUS status;
    if (0 <= (status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), 0)) &&
        0 <= (status = ZwReadVirtualMemory(hProcess, &reinterpret_cast<_PEB*>(pbi.PebBaseAddress)->ProcessParameters, 
        &ProcessParameters, sizeof(ProcessParameters), 0)) &&
        0 <= (status = ZwReadVirtualMemory(hProcess, &ProcessParameters->CurrentDirectory.DosPath, 
        DosPath, sizeof(UNICODE_STRING), 0)))
    {
        if (ULONG Length = DosPath->Length)
        {
            status = STATUS_UNSUCCESSFUL;

            if (!(Length & (sizeof(WCHAR) - 1)) && Length < MAXUSHORT)
            {
                status = STATUS_NO_MEMORY;
                if (PWSTR Buffer = (PWSTR)LocalAlloc(LMEM_FIXED, Length + sizeof(WCHAR)))
                {
                    if (0 <= (status = ZwReadVirtualMemory(hProcess, DosPath->Buffer, Buffer, Length, 0)))
                    {
                        *reinterpret_cast<PWSTR>(RtlOffsetToPointer(Buffer, Length)) = 0;
                        DosPath->MaximumLength = (USHORT)Length + sizeof(WCHAR);
                        DosPath->Buffer = Buffer, Buffer = 0;
                    }
                    LocalFree(Buffer);
                }
            }
        }
        else
        {
            DosPath->Buffer = 0;
            DosPath->MaximumLength = 0;
        }
    }

    return status;
}

NTSTATUS GetCWD(_In_ HANDLE hProcess, _Out_ PUNICODE_STRING DosPath)
{
    PEB32* WowPeb;
    NTSTATUS status;
    if (0 > (status = NtQueryInformationProcess(hProcess, ProcessWow64Information, &WowPeb, sizeof(WowPeb), 0)))
    {
        return status;
    }
    return WowPeb ? GetCWD32(hProcess, WowPeb, DosPath) : GetCWD64(hProcess, DosPath);
}

NTSTATUS GetCWD(_In_ ULONG dwProcessId, _Out_ PUNICODE_STRING DosPath)
{
    NTSTATUS status;
    HANDLE hProcess;
    CLIENT_ID cid = { (HANDLE)(ULONG_PTR)dwProcessId };
    OBJECT_ATTRIBUTES oa = { sizeof(oa) };
    if (0 <= (status = NtOpenProcess(&hProcess, PROCESS_VM_READ|PROCESS_QUERY_LIMITED_INFORMATION, &oa, &cid)))
    {
        status = GetCWD(hProcess, DosPath);
        NtClose(hProcess);
    }

    return status;
}

NTSTATUS GetCWD(_In_ HWND hwnd, _Out_ PUNICODE_STRING DosPath)
{
    ULONG dwProcessId;
    if (GetWindowThreadProcessId(hwnd, &dwProcessId))
    {
        return GetCWD(dwProcessId, DosPath);
    }
    return STATUS_NOT_FOUND;
}

void GetCWD()
{
    if (HWND hwnd = FindWindowW(L"ConsoleWindowClass", 0))
    {
        UNICODE_STRING DosPath = {};
        if (0 <= GetCWD(hwnd, &DosPath))
        {
            DbgPrint("CWD=\"%wZ\"\r\n", &DosPath);
            LocalFree(DosPath.Buffer);
        }
    }
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章