命令提示符的标题问题
我正在开发一个小型的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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。