Registriert seit: 24. Sep 2006
Ort: Arlon, Belgien
71 Beiträge
|
CreateProcess mit Powershell
10. Mai 2016, 15:00
Hallo zusammen,
ich hab jetzt einige Tage lang gegrübelt und muss noch doch mal fragen.
Ich habe verschiedene "advertised Shortcuts" in meinem Startmenu und möchte gern die Zieldatei wissen. Das GetPath von iShellLink gibt da leider nur einen falschen Link vom Windows Installer zurück aber es gibt eine Powershell Funktion die das richtige Resultat ausgibt ( Siehe Link):
Code:
$lnk = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Adobe\Adobe Acrobat X Pro.lnk"
$WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
$ShortcutTarget = $WindowsInstaller.GetType().InvokeMember("ShortcutTarget","GetProperty",$null,$WindowsInstaller,$lnk)
$StringData1 = $ShortcutTarget.GetType().InvokeMember("StringData","GetProperty",$null,$ShortcutTarget,1)
$StringData3 = $ShortcutTarget.GetType().InvokeMember("StringData","GetProperty",$null,$ShortcutTarget,3)
$WindowsInstaller.GetType().InvokeMember("ComponentPath","GetProperty",$null,$WindowsInstaller,@($StringData1,$StringData3))
Nun zum lustigen teil, das funktionniert super manuelle vom Powershell aber ich bekomme es nicht hin mit Delphi.
1. Ich habe versucht die Funktionen als Argument zu benutzen:
Delphi-Quellcode:
var
ArgumentString: WideString;
ArgumentString := '$lnk = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Adobe\Adobe Acrobat X Pro.lnk"' + ';' +
'$WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer' + ';' +
'$ShortcutTarget = $WindowsInstaller.GetType().InvokeMember("ShortcutTarget","GetProperty",$null,$WindowsInstaller,$lnk)' + ';' +
'$StringData1 = $ShortcutTarget.GetType().InvokeMember("StringData","GetProperty",$null,$ShortcutTarget,1)' + ';' +
'$StringData3 = $ShortcutTarget.GetType().InvokeMember("StringData","GetProperty",$null,$ShortcutTarget,3)' + ';' +
'$WindowsInstaller.GetType().InvokeMember("ComponentPath","GetProperty",$null,$WindowsInstaller,@($StringData1,$StringData3))';
Manuelle klappt das mit dem Semikolon super im Powershell aber wenn ich folgendes probiere, scheint das argument nicht vorständig durchgegeben zu werden (zu lang!)
CreateProcess(nil, PChar('Powershell.exe ' + ArgumentString), @Security, @Security, true, CREATE_NEW_CONSOLE, nil, PChar('C:\'), start, ProcessInfo);
Wie gesagt, das klappt nicht, weil zu lang.
2. Hab es mal mit WriteFile und Pipes versucht
Delphi-Quellcode:
var
ArgumentString: WideString;
Security: TSecurityAttributes;
PipeRead, PipeWrite: THandle;
NewPipeIn, NewPipeOut: THandle;
Start: TStartupInfo;
ProcessInfo: TProcessInformation;
BytesWritten, BytesRead: DWord;
ResultString: String;
WasOk: Boolean;
Buffer: array[0..255] of AnsiChar;
Procedure Test
Begin
with Security do
begin
nLength := SizeOf(Security);
bInheritHandle := True;
lpSecurityDescriptor := nil;
end;
CreatePipe(PipeRead, NewPipeOut, @Security, 0);
CreatePipe(NewPipeIn, PipeWrite, @Security, 0);
with start do
begin
FillChar(start, SizeOf(start), 0);
cb := SizeOf(start);
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
wShowWindow := SW_SHOW; //SW_HIDE;
hStdInput := NewPipeIn;
hStdOutput := NewPipeOut;
hStdError := NewPipeOut;
end;
ArgumentString := '-NoExit'
if CreateProcess(nil, PChar('Powershell.exe ' + ArgumentString), @Security, @Security, true, CREATE_NEW_CONSOLE, nil, PChar('C:\'), start, ProcessInfo) then
Begin
ArgumentString := '$lnk = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Adobe\Adobe Acrobat X Pro.lnk"' + #13#10
WriteFile(PipeWrite, ArgumentString[1], length(ArgumentString), BytesWritten, nil);
ArgumentString := '$WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer' + #13#10
WriteFile(PipeWrite, ArgumentString[1], length(ArgumentString), BytesWritten, nil);
ArgumentString := '$ShortcutTarget = $WindowsInstaller.GetType().InvokeMember("ShortcutTarget","GetProperty",$null,$WindowsInstaller,$lnk)' + #13#10
WriteFile(PipeWrite, ArgumentString[1], length(ArgumentString), BytesWritten, nil);
ArgumentString := '$StringData1 = $ShortcutTarget.GetType().InvokeMember("StringData","GetProperty",$null,$ShortcutTarget,1)' + #13#10
WriteFile(PipeWrite, ArgumentString[1], length(ArgumentString), BytesWritten, nil);
ArgumentString := '$StringData3 = $ShortcutTarget.GetType().InvokeMember("StringData","GetProperty",$null,$ShortcutTarget,3)' + #13#10
WriteFile(PipeWrite, ArgumentString[1], length(ArgumentString), BytesWritten, nil);
ArgumentString := '$WindowsInstaller.GetType().InvokeMember("ComponentPath","GetProperty",$null,$WindowsInstaller,@($StringData1,$StringData3))' + #13#10
WriteFile(PipeWrite, ArgumentString[1], length(ArgumentString), BytesWritten, nil);
ResultString := '';
repeat
WasOK := ReadFile(PipeRead, Buffer, 255, BytesRead, nil);
if BytesRead > 0 then
begin
Buffer[BytesRead] := #0;
ResultString := ResultString + Buffer;
end;
until not WasOK or (BytesRead = 0);
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
CloseHandle(PipeRead);
CloseHandle(PipeWrite);
CloseHandle(NewPipeIn);
CloseHandle(NewPipeOut);
end;
Soweit, so gut. Nun hab ich leider weder Input in den PowerShell, noch hab ich ein Resultat mit ReadFile.
Könnt Ihr mir bitte helfen das die Procedure Funktionniert ?
Geändert von DavidKlimas (10. Mai 2016 um 15:17 Uhr)
Grund: Link wurde nicht korrekt angezeigt
|