I need to get PowerShell current directory in Java code using PowerShell PID. For example, if there is a PowerShell instance and a user is in E:\Temp directory I need to get E:\Temp. If the user does cd Foo, I need to get E:\Temp\Foo.
This is my code:
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
import java.util.Arrays;
import java.util.List;
public class Test {
public interface NtDll extends StdCallLibrary {
NtDll INSTANCE = com.sun.jna.Native.load("ntdll", NtDll.class);
class PROCESS_BASIC_INFORMATION extends Structure {
public int ExitStatus;
public Pointer PebBaseAddress;
public IntByReference AffinityMask;
public int BasePriority;
public IntByReference UniqueProcessId;
public IntByReference InheritedFromUniqueProcessId;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("ExitStatus", "PebBaseAddress", "AffinityMask", "BasePriority",
"UniqueProcessId", "InheritedFromUniqueProcessId");
}
}
int NtQueryInformationProcess(WinNT.HANDLE ProcessHandle, int ProcessInformationClass,
PROCESS_BASIC_INFORMATION ProcessInformation, int ProcessInformationLength, IntByReference ReturnLength);
}
public static void main(String[] args) {
int pid = Integer.valueOf(args[0]);
String currentDirectory = getProcessCurrentDirectory(pid);
System.out.println("Current Directory: " + currentDirectory);
}
public static String getProcessCurrentDirectory(int pid) {
WinNT.HANDLE processHandle =
Kernel32.INSTANCE.OpenProcess(Kernel32.PROCESS_QUERY_INFORMATION | Kernel32.PROCESS_VM_READ, false, pid);
if (processHandle == null) {
System.err.println("Failed to open process");
return null;
}
NtDll.PROCESS_BASIC_INFORMATION pbi = new NtDll.PROCESS_BASIC_INFORMATION();
IntByReference retLen = new IntByReference();
NtDll.INSTANCE.NtQueryInformationProcess(processHandle, 0, pbi, pbi.size(), retLen);
Pointer pebAddress = pbi.PebBaseAddress;
Pointer processParametersPointer = pebAddress.share(0x20);
Pointer rtlUserProcParamsAddress = readPointer(processHandle, processParametersPointer);
Pointer currentDirectoryPointer = rtlUserProcParamsAddress.share(0x38);
int directoryLength = readShort(processHandle, currentDirectoryPointer.share(0x10));
Pointer directoryPointer = readPointer(processHandle, currentDirectoryPointer.share(0x08));
int bufferSize = Math.max(directoryLength + 2, 256);
Memory buffer = new Memory(bufferSize);
Kernel32.INSTANCE.ReadProcessMemory(processHandle, directoryPointer, buffer, (int) buffer.size(), null);
String directory = buffer.getWideString(0);
Kernel32.INSTANCE.CloseHandle(processHandle);
return directory;
}
private static Pointer readPointer(WinNT.HANDLE processHandle, Pointer address) {
Memory buffer = new Memory(Native.POINTER_SIZE);
Kernel32.INSTANCE.ReadProcessMemory(processHandle, address, buffer, (int) buffer.size(), null);
return buffer.getPointer(0);
}
private static int readShort(WinNT.HANDLE processHandle, Pointer address) {
Memory buffer = new Memory(2); // size of short
Kernel32.INSTANCE.ReadProcessMemory(processHandle, address, buffer, (int) buffer.size(), null);
return buffer.getShort(0);
}
}
My code works only for CMD. However, it doesn't work for PowerShell always showing same initial directory (I tested in Windows 7). Could anyone say how to do it for PowerShell, if it is possible?
[Environment]::CurrentDirectorywhen you change location. Try explicitly setting[Environment]::CurrentDirectory = "C:\some\existing\path"in PowerShell and run your java program again