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

标签 .net vb.net pinvoke environment-variables

问题:我有一个安装程序,它会随程序一起安装一些 native 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

最佳答案

我怀疑这与 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)

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

关于.net - 为什么 SendMessageTimeout 不更新环境变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4968373/

相关文章:

带有函数(x)的 VB.NET Linq 表达式未执行?

vb.net - 在获得焦点时显示组合框列表(vb.net)

c# - ASP.NET 中的 P/Invoke(从 dll 读取/写入文本文件)

c# - 使用 PInvoke 连接 C/C++ DLL 的调试断言失败

c# - 使用 web.config 的角色管理提供程序?

c# - 在 WPF 中将窗口置于最前面

c# - C# 中的存储过程

c# - Azure 云 Web 角色 + AspNetCompiler?

c# - User.config 损坏

c# - .NET 在异步任务完成之前返回响应