2011-02-11 121 views
4

問題:我有一個安裝程序,它會隨程序一起安裝一些原生dll。 該dll位於一個單獨的文件夾中,我將其添加到路徑環境變量中。爲什麼SendMessageTimeout不更新環境變量?

這已成功完成,並且如果我檢查Windows系統設置,變量將顯示在路徑中。

但是,如果我啓動命令行程序/服務,它說的DLL沒有找到,

我檢查環境變量path和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 

回答

11

我懷疑它與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) 

+0

這個答案是完全錯誤的。爲什麼人們不喜歡錯誤的答案? Windows會根據您使用的API自動轉換Windows消息中的所有字符串。當您使用SendMessageTimeoutA()時,您必須發送一個ANSI字符串。當你使用SendMessageTimeoutW()時,你必須發送一個寬字符串。接收消息的Window過程總是以正確的格式接收字符串。在爲Unicode編譯的應用程序中,即使字符串作爲ANSI字符串從SendMessageTimeoutA()發送,字符串也會以寬字符形式到達。反之亦然。 – Elmue 2017-09-27 19:11:47