我需要编写一个脚本来安装特定版本的Java运行时,添加到系统路径变量然后继续运行Java程序。我希望一次完成所有操作,而无需重新启动目标计算机。
我发现了这个问题,并认为我可以尝试改变我的需求。
SendMessage is causing script to hang
所以我根据答案尝试使用PostMessage。显然我需要改变信息。
所以我尝试了这样的代码:
echo Start of experiment
$NewPath = (Get-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Session Manager\Environment" -Name Path).Path
$NewPath = "%JAVA_BIN%;" + $NewPath
$RegKey ="HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Set-ItemProperty -Path $RegKey -Name Path -Value $NewPath
echo Updated Path environment variable
# Next bit which isn't working
$HWND_BROADCAST = 0xffff
$WM_SETTINGCHANGE = 0x001A
$ENVIRON = "Environment"
#Store the C# signature of the PostMessage function.
$signature = @"
[DllImport("user32.dll")]
public static extern int PostMessage(int hWnd, int hMsg, int wParam, int lParam);
"@
#Add the SendMessage function as a static method of a class
$PostMessage = Add-Type -MemberDefinition $signature -Name "Win32PostMessage" -Namespace Win32Functions -PassThru
#Invoke the PostMessage Function
$PostMessage::PostMessage($HWND_BROADCAST, $WM_SETTINGCHANGE, 0, $ENVIRON)
echo end of experiment
这是我的输出:
Start
of
experiment
Cannot convert argument "3", with value: "Environment", for "PostMessage" to type "System.Int32": "Cannot convert value "Environment" to type "System.Int32".
Error: "Input string was not in a correct format.""
At C:\share\tvm_drivers\PED\setenv.ps1:43 char:26
+ $PostMessage::PostMessage <<<< ($HWND_BROADCAST, $WM_SETTINGCHANGE, 0, $ENVIRON)
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
end
of
experiment
我在Windows 7上运行它。
有人可以帮忙吗?
对于一些背景知识,如果在设置路径env变量后重新启动目标PC,则设置有效。但是,如果您不重新启动,则必须发送如上所述的广播消息,以告知任何其他窗口,包括命令提示符,以了解更改。这就是我需要这条消息的原因。
答案 0 :(得分:0)
这是成功更新所有有关env更改的打开窗口的功能。
# Notifies other processes that the global environment block has changed.
# This lets other processes see changes to ENV: without having to reboot
# or logoff/logon. A non-zero result from SendMessageTimeout indicates success.
if (-not ("win32.nativemethods" -as [type])) {
# import sendmessagetimeout from win32
add-type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
"@
}
$HWND_BROADCAST = [intptr]0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [uintptr]::zero
# notify all windows of environment block change
[win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE,
[uintptr]::Zero, "Environment", 2, 5000, [ref]$result);