为什么SendMessageTimeout不更新环境变量?

时间:2011-02-11 11:16:50

标签: .net vb.net pinvoke environment-variables

问题:我有一个安装程序,它会随程序一起安装一些本机dll。 dll位于一个单独的文件夹中,我将其添加到路径环境变量中。

成功完成,如果我检查Windows系统设置,变量将显示在路径中。

但是,如果我启动命令行程序/服务,它会说dll未找到...

我使用set命令检查环境变量路径,而我的文件夹不在那里。

如果我这样做

SET path = %path%;my/folder/here/

然后启动我的程序,然后它就可以了。

根据this MS KB article,这是因为需要重新启动计算机。

除非我

SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue);            

现在,我使用下面的代码,但错误消息仍然存在。 %path%中的我的文件夹拼写正确,我检查过。

我做错了什么?

' http://www.pinvoke.net/default.aspx/Enums/SendMessageTimeoutFlags.html '
<Flags()> _
Public Enum SendMessageTimeoutFlags
    SMTO_NORMAL = 0
    SMTO_BLOCK = 1
    SMTO_ABORTIFHUNG = 2
    SMTO_NOTIMEOUTIFNOTHUNG = 8
End Enum    

' http://ghouston.blogspot.com/2005/08/how-to-create-and-change-environment.html '
Public Const HWND_BROADCAST As Integer = &HFFFF
Public Const WM_SETTINGCHANGE As Integer = &H1A    

' http://pinvoke.net/default.aspx/user32.SendMessageTimeout '
<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
Public Shared Function SendMessageTimeout(ByVal windowHandle As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr, ByVal flags As SendMessageTimeoutFlags, ByVal timeout As Integer, ByRef result As IntPtr) As IntPtr
End Function    

' http://support.microsoft.com/?kbid=104011 '
' http://blog.jtbworld.com/2005/11/set-environment-variable-using-vbnet.html '
Sub UpdatePath()
    Dim result As Integer
    ' SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,(LPARAM) "Environment", SMTO_ABORTIFHUNG,5000, &dwReturnValue); '   

    ' CType("Environment", System.IntPtr) '
    Dim s As String = New String("Environment")
    Dim ptr As IntPtr = Runtime.InteropServices.Marshal.StringToHGlobalUni(s)

    'SendMessageTimeout(CType(HWND_BROADCAST, System.IntPtr), WM_SETTINGCHANGE, 0, ptr, SendMessageTimeoutFlags.SMTO_BLOCK Or SendMessageTimeoutFlags.SMTO_ABORTIFHUNG Or SendMessageTimeoutFlags.SMTO_NOTIMEOUTIFNOTHUNG, 5000, result) '
    SendMessageTimeout(CType(HWND_BROADCAST, System.IntPtr), WM_SETTINGCHANGE, 0, ptr, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5000, result)
End Sub

1 个答案:

答案 0 :(得分:10)

我怀疑它与Unicode / ANSI处理有关;基本系统似乎想要ANSI中的“环境”,但是包括shell在内的大多数应用程序都需要Unicode,如果它们完全承认它的话。在C中我只是发送它:

SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) "Environment", SMTO_ABORTIFHUNG, 1000, NULL );
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) L"Environment", SMTO_ABORTIFHUNG, 1000, NULL );

这很好地完成了工作。

在VB.Net中,我认为你的等价物是:

Dim s As String = New String("Environment")
Dim ptrA As IntPtr = Runtime.InteropServices.Marshal.StringToHGlobalAnsi(s)
Dim ptrU As IntPtr = Runtime.InteropServices.Marshal.StringToHGlobalUni(s)
SendMessageTimeout(CType(HWND_BROADCAST, System.IntPtr), WM_SETTINGCHANGE, 0, ptrA, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5000, result)
SendMessageTimeout(CType(HWND_BROADCAST, System.IntPtr), WM_SETTINGCHANGE, 0, ptrU, SendMessageTimeoutFlags.SMTO_ABORTIFHUNG, 5000, result)

(如果您要使用非托管代码,请不要忘记释放内存。)