The goal is to make a change to the registry regarding proxy settings (turn on/off) and it take effect without reloading the browser. The following code seems to return a valid response and there are no errors so I like to think I am doing it right. The problem is that it doesn't accomplish the goal. Some possible reasons are:
- This change is not considered a "top-level window" change.
- I'm doing it wrong.
- Something else I'm not considering.
Anyone have a suggestion? Thanks.
Jim
GoSub Load_Routines
Load_SetChange()
SetChangeLoader = ObjectClrNew( 'SetChange.User32Utils' )
msg = SetChangeLoader.Notify_SettingChange
Message("HEY",msg)
:LOAD_ROUTINES
#DefineSubRoutine Load_SetChange()
;***************************************************************************
;** Run C# in memory using WinBatch - Use Namespace.Class defined in CSharpeSource
;**
;** Purpose: Run C# in memory using WinBatch - Using Namespace.Class defined in CSharpeSource
;** Inputs:
;** Outputs: Results in message
;**
;** Developer: Deana Falk 2014.04.14
;***************************************************************************
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Load assemblies into the WinBatch process.
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; mscorlib assembly is automatically loaded by WinBatch when the CLR is loaded.
ObjectClrOption("use","System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; Compiles the c# code in Memory
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
objCSharp = ObjectClrNew('Microsoft.CSharp.CSharpCodeProvider')
objParams = ObjectClrNew('System.CodeDom.Compiler.CompilerParameters')
objParams.GenerateInMemory = ObjectType( "VT_BOOL", 1 ) ;TRUE
objParams.ReferencedAssemblies.Add("System.dll")
;Make sure the cSharp code includes both namepspace and class that can be later used by ObjectCLRNew
cSharpSource = `using System; `:@LF
cSharpSource = cSharpSource :`using System.Runtime.InteropServices; `:@LF
cSharpSource = cSharpSource :`namespace SetChange `:@LF
cSharpSource = cSharpSource :`{ `:@LF
cSharpSource = cSharpSource :`public static class User32Utils `:@LF
cSharpSource = cSharpSource :` { `:@LF
cSharpSource = cSharpSource :` static IntPtr HWND_BROADCAST = new IntPtr(0xffffL); `:@LF
cSharpSource = cSharpSource :` static IntPtr WM_SETTINGCHANGE = new IntPtr(0x1a); `:@LF
cSharpSource = cSharpSource :` enum SendMessageTimeoutFlags : uint `:@LF
cSharpSource = cSharpSource :` { `:@LF
cSharpSource = cSharpSource :` SMTO_NORMAL = 0x0000, `:@LF
cSharpSource = cSharpSource :` SMTO_BLOCK = 0x0001, `:@LF
cSharpSource = cSharpSource :` SMTO_ABORTIFHUNG = 0x2, `:@LF
cSharpSource = cSharpSource :` SMTO_NOTIMEOUTIFNOTHUNG = 0x0008 `:@LF
cSharpSource = cSharpSource :` } `:@LF
cSharpSource = cSharpSource :` [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] `:@LF
cSharpSource = cSharpSource :` static extern IntPtr SendMessageTimeout(IntPtr hWnd, `:@LF
cSharpSource = cSharpSource :` uint Msg, `:@LF
cSharpSource = cSharpSource :` UIntPtr wParam, `:@LF
cSharpSource = cSharpSource :` UIntPtr lParam, `:@LF
cSharpSource = cSharpSource :` SendMessageTimeoutFlags fuFlags, `:@LF
cSharpSource = cSharpSource :` uint uTimeout, `:@LF
cSharpSource = cSharpSource :` out UIntPtr lpdwResult); `:@LF
cSharpSource = cSharpSource :` internal static IntPtr Notify_SettingChange() `:@LF
cSharpSource = cSharpSource :` { `:@LF
cSharpSource = cSharpSource :` UIntPtr result; `:@LF
cSharpSource = cSharpSource :` IntPtr sresult; `:@LF
cSharpSource = cSharpSource :` sresult = SendMessageTimeout(HWND_BROADCAST, (uint)WM_SETTINGCHANGE, UIntPtr.Zero, UIntPtr.Zero, SendMessageTimeoutFlags.SMTO_NORMAL, 1000, out result); `:@LF
cSharpSource = cSharpSource :` return sresult; `:@LF
cSharpSource = cSharpSource :` } `:@LF
cSharpSource = cSharpSource :` } `:@LF
cSharpSource = cSharpSource :`} `:@LF
objResult = objCSharp.CompileAssemblyFromSource(objParams,cSharpSource)
;Compiler Output
If objResult.Output.Count > 0 Then
strOutput = ''
For x = 0 to objResult.Output.Count-1
If strOutput == "" Then
strOutput = objResult.Output.Item(x)
Else
strOutput = strOutput:@LF:objResult.Output.Item(x)
EndIf
Next
Pause('Compiler Output',strOutput)
Endif
; Compiler Errors
If objResult.Errors.Count > 0 Then
strErrors = ''
ForEach ce In objResult.Errors
;Pause("Error", ce.ToString())
If strErrors == "" Then
strErrors = ce.ToString()
Else
strErrors = strErrors:@LF:ce.ToString()
EndIf
Next
Pause('Compiler Errors',strErrors)
Exit
EndIf
#EndSubRoutine
Return
Hi Jim,
maybe you want or need to do it using in memory compilation of c# script???
BUT if not, and you just want to get the actual job done (accept any registry proxy changes without reloading the browser) then there are a couple of examples in the Tech Database using a dll call to Wininet.dll and the InternetSetOptionA function in it.
Do a search for articles:
W18412 "Refresh Active Internet Explorer Session"
and
W17790 "Dynamically Change Proxy Settings for an Existing IE Session"
Hmmmmmmmmmmm....maybe I'm misunderstanding but that is what the code I posted does. I'm was hoping someone could tell me why it doesn't work even though it acts like it does.
Thanks for the other links. I'll take a look. Would still be interested in making the other work though.
Thanks again.
Jim
I would tend to disagree. .. it only looks like it does half of what the others do.., it appears to only send a general systems setting change to all open windows, not the internet options set change found in the wininet.dll
Okay. That is what I was wondering. I knew one possibility was that it didn't see these changes as part of the "top-level windows" changes but I have found numerous postings which say this approach works for what I was wanting to do.
Thanks again for the reminder on the other links. I had forgotten about those and actually used that approach in a few scripts in years past.
Jim
And the entire C# source could be accomplished with a WinBatch Script one liner...
Which would be?
Here is what I used for the moment but happy to shorten it.
hWinInet = DllLoad(DirWindows(1):"WININET.DLL")
INETOPT_SETTINGS_CHANGED = 39
INETOPT_REFRESH = 37
DllCall(hWinInet, long:"InternetSetOptionA", long:0, long:INETOPT_SETTINGS_CHANGED, long:0, long:0)
DllCall(hWinInet, long:"InternetSetOptionA", long:0, long:INETOPT_REFRESH, long:0, long:0)
DllFree(hWinInet)
I was referring specifically to the user32 function SendMessageTimeout in the C# source you posted. That can be done in a single line DllCall or perhaps simply using IntControl 59. The WinBatch DllCalls you just posted perform a slightly different task and appear to be based on one of the Tech Database article mentioned above. I probably shouldn't admit to it but FWIW, the example in the second article looks like it is lifted from a script I wrote many years ago. Didn't even know it was placed in the the Tech Database and it is kind of amazing that it still works.
IntControl 59 *may* work. Seems to be a long delay which kills it for my needs. Could be something else making it happen I guess???
In any event...the last thing I posted does the job. Thanks all.
Jim
IntControl 59 has a maximum 5 second delay that would only go into affect if a process with a message pump is not pulling messages from its message queue. In other words the process is hung for some reason. A one line DllCall would still do what all the c# code does. But as you indicated SendMessageTimeout does not perform what the InternetSetOption function does.
Jim,
Quote from: JTaylor on August 12, 2015, 08:43:01 PM
In any event...the last thing I posted does the job. Thanks all.
As I scrolled my way down, I kept asking myself why you had all that dynamically compiled C# code to do something that would be so much more simply accomplished by DLLCall. I'm glad to know that the simpler solution worked for you. I have successfully used the same scheme to register, then immediately use, event source IDs.