WinBatch® Technical Support Forum

Archived Boards => COM Automation and dotNet => Topic started by: JTaylor on August 11, 2015, 10:23:41 AM

Title: WM_SETTINGSCHANGE
Post by: JTaylor on August 11, 2015, 10:23:41 AM
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:


Anyone have a suggestion?  Thanks.

Jim

Code (winbatch) Select

  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
Title: Re: WM_SETTINGSCHANGE
Post by: ....IFICantBYTE on August 11, 2015, 06:52:36 PM
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"

Title: Re: WM_SETTINGSCHANGE
Post by: JTaylor on August 11, 2015, 07:55:37 PM
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
Title: Re: WM_SETTINGSCHANGE
Post by: ....IFICantBYTE on August 12, 2015, 01:38:58 AM
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
Title: Re: WM_SETTINGSCHANGE
Post by: JTaylor on August 12, 2015, 05:32:21 AM
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
Title: Re: WM_SETTINGSCHANGE
Post by: td on August 12, 2015, 09:00:31 AM
And the entire C# source could be accomplished with a WinBatch Script one liner...
Title: Re: WM_SETTINGSCHANGE
Post by: JTaylor on August 12, 2015, 09:35:54 AM
Which would be?



Here is what I used for the moment but happy to shorten it.

Code (winbatch) Select



   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)
   
Title: Re: WM_SETTINGSCHANGE
Post by: td on August 12, 2015, 10:16:06 AM
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.
Title: Re: WM_SETTINGSCHANGE
Post by: JTaylor on August 12, 2015, 08:43:01 PM
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
Title: Re: WM_SETTINGSCHANGE
Post by: td on August 14, 2015, 07:28:20 AM
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.
Title: Re: WM_SETTINGSCHANGE
Post by: DAG_P6 on September 09, 2015, 01:11:49 PM
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.