Powershell 到 运行 PostMessage Windows API 函数失败
Powershell to run PostMessage Windows API function failing
我需要写一个脚本来安装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.
有人能帮忙吗?
作为背景知识,如果您在设置路径环境变量后重新启动目标 PC,则设置会起作用。但是,如果您不重新启动,则有必要像上面那样发送广播消息,以将更改告知任何其他 Window,包括命令提示符。这就是为什么我需要这条消息。
这是成功更新所有关于 env 更改的打开 windows 的 powershell。
# 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);
我需要写一个脚本来安装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.
有人能帮忙吗?
作为背景知识,如果您在设置路径环境变量后重新启动目标 PC,则设置会起作用。但是,如果您不重新启动,则有必要像上面那样发送广播消息,以将更改告知任何其他 Window,包括命令提示符。这就是为什么我需要这条消息。
这是成功更新所有关于 env 更改的打开 windows 的 powershell。
# 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);