title: SetWindowLong & SetLayeredWindowAttributes doesnt work on different user C#
body: <p><strong>The goal is</strong></p>
  
  <p>I want to change the opacity of some application (target) running on win xp. </p>
  
  <p><strong>The situation</strong></p>
  
  <ul>
  <li>I logged in win xp as AD (active dir) user account (some-domain\username) </li>
  <li>most of the target applications are run as local user or another ad user</li>
  </ul>
  
  <p><strong>The problem and my Question</strong></p>
  
  <p><code>SetWindowLong</code> &amp; <code>SetLayeredWindowAttributes</code> doesn't work on target application that run as other user account. But it works on target application that runs under the same user account (logged user account)</p>
  
  <p><em><strong>How to change other app's window opacity that run as different user account?</em></strong></p>
  
  <p><strong>Illustration app</strong></p>
  
  <p>It's a win form app  (let's call it OpaciToggler.exe). I have 2 buttons (btnRunSomething and btnHideThatThing) and a textbox (txtPid). As simple as that. </p>
  
  <p>When I click the btnRunSomething, it run an .exe as different user. All the details is in the app.config. In this case I run this application (OpaciToggler.exe, from the debug/bin) as different user (localComputer\user1)</p>
  
  <p>The txtPid is for manual pid input. Usually I open the task manager (win > run > taskmgr) and find the pid (under the process tab) of any application (target) I want to test with, then type it here.</p>
  
  <p>When I click the btnHideThatThing, it'll toggle the opacity of the target application (whose pid in the txtPid)</p>
  
  <p><strong>Code C#</strong></p>
  
  <p>This is how I call the target app.</p>
  
  <pre class="lang-cs prettyprint-override"><code>    private void btnRunSomething_Click(object sender, EventArgs e)
      {
          System.Diagnostics.Process p = new System.Diagnostics.Process();
  
          p.StartInfo.Domain = ConfigurationManager.AppSettings["StartInfoDomain"]; 
          p.StartInfo.UserName = ConfigurationManager.AppSettings["StartInfoUserName"]; 
  
          p.StartInfo.FileName = ConfigurationManager.AppSettings["StartInfoFileName"];
          p.StartInfo.Arguments = ConfigurationManager.AppSettings["StartInfoArguments"];
  
          System.String rawPassword = ConfigurationManager.AppSettings["StartInfoPassword"];
          System.Security.SecureString encPassword = new System.Security.SecureString();
  
          foreach (System.Char c in rawPassword)
          {
              encPassword.AppendChar(c);
          }
  
          p.StartInfo.Password = encPassword;
          p.StartInfo.UseShellExecute = false;
  
          p.Start();
      }
  </code></pre>
  
  <p>This is how I try to call the opacity thing</p>
  
  <pre class="lang-cs prettyprint-override"><code>    private void btnHideThatThing_Click(object sender, EventArgs e)
      {
          // manual input pid 
          int pid = int.Parse(txtPid.Text);
          IntPtr mwh = Process.GetProcessById(pid).MainWindowHandle;
          doHideThing(mwh);  
  
          // doHideThing(Process.GetProcessById(int.Parse(txtPid.Text)).MainWindowHandle);
      }
  </code></pre>
  
  <p>The hide method</p>
  
  <pre class="lang-cs prettyprint-override"><code>    private void doHideThing(IntPtr hndl)
      {
          SetWindowLong(hndl, GWL_EXSTYLE, GetWindowLong(hndl, GWL_EXSTYLE) ^ WS_EX_LAYERED).ToString();
          // _whatNow = Marshal.GetLastWin32Error();
  
          SetLayeredWindowAttributes(hndl, 0, (255 * 20) / 100, LWA_ALPHA).ToString();
          // _whatNow = Marshal.GetLastWin32Error();
  
          RedrawWindow(hndl, IntPtr.Zero, IntPtr.Zero,
              RedrawWindowFlags.Erase | RedrawWindowFlags.Invalidate |
              RedrawWindowFlags.Frame | RedrawWindowFlags.AllChildren);            
      }
  </code></pre>
  
  <p>other codes</p>
  
  <pre class="lang-cs prettyprint-override"><code>    private const int GWL_EXSTYLE = -20;
      private const int GWL_STYLE = -16;
      private const int WS_EX_LAYERED = 0x80000;
      private const int LWA_ALPHA = 0x2;
      private const int LWA_COLORKEY = 0x1;
  
      [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
      static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
  
      [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
      private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
  
      [DllImport("user32.dll", SetLastError = true)]
      static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprcUpdate, IntPtr hrgnUpdate, RedrawWindowFlags flags);
  </code></pre>
  
  <p>RedrawWindowFlags enum (I don't remember where I get this)</p>
  
  <pre class="lang-cs prettyprint-override"><code>[Flags()]
  enum RedrawWindowFlags : uint
  {
      /// &lt;summary&gt;
      /// Invalidates the rectangle or region that you specify in lprcUpdate or hrgnUpdate.
      /// You can set only one of these parameters to a non-NULL value. If both are NULL, RDW_INVALIDATE invalidates the entire window.
      /// &lt;/summary&gt;
      Invalidate = 0x1,
  
      /// &lt;summary&gt;Causes the OS to post a WM_PAINT message to the window regardless of whether a portion of the window is invalid.&lt;/summary&gt;
      InternalPaint = 0x2,
  
      /// &lt;summary&gt;
      /// Causes the window to receive a WM_ERASEBKGND message when the window is repainted.
      /// Specify this value in combination with the RDW_INVALIDATE value; otherwise, RDW_ERASE has no effect.
      /// &lt;/summary&gt;
      Erase = 0x4,
  
      /// &lt;summary&gt;
      /// Validates the rectangle or region that you specify in lprcUpdate or hrgnUpdate.
      /// You can set only one of these parameters to a non-NULL value. If both are NULL, RDW_VALIDATE validates the entire window.
      /// This value does not affect internal WM_PAINT messages.
      /// &lt;/summary&gt;
      Validate = 0x8,
  
      NoInternalPaint = 0x10,
  
      /// &lt;summary&gt;Suppresses any pending WM_ERASEBKGND messages.&lt;/summary&gt;
      NoErase = 0x20,
  
      /// &lt;summary&gt;Excludes child windows, if any, from the repainting operation.&lt;/summary&gt;
      NoChildren = 0x40,
  
      /// &lt;summary&gt;Includes child windows, if any, in the repainting operation.&lt;/summary&gt;
      AllChildren = 0x80,
  
      /// &lt;summary&gt;Causes the affected windows, which you specify by setting the RDW_ALLCHILDREN and RDW_NOCHILDREN values, to receive WM_ERASEBKGND and WM_PAINT messages before the RedrawWindow returns, if necessary.&lt;/summary&gt;
      UpdateNow = 0x100,
  
      /// &lt;summary&gt;
      /// Causes the affected windows, which you specify by setting the RDW_ALLCHILDREN and RDW_NOCHILDREN values, to receive WM_ERASEBKGND messages before RedrawWindow returns, if necessary.
      /// The affected windows receive WM_PAINT messages at the ordinary time.
      /// &lt;/summary&gt;
      EraseNow = 0x200,
  
      Frame = 0x400,
  
      NoFrame = 0x800
  }
  </code></pre>
  
  <p><strong>Example, Test and Test Result</strong></p>
  
  <ul>
  <li>logged in win xp as domainA\ad_user1</li>
  <li>run the OpaciToggler.exe application (Instance1, run as domainA\ad_user1)</li>
  <li>Then I click the run something. It opens another OpaciToggler.exe (Instance2), runs as another user account (run as localcomputer\l_user1) OR right click the .exe then click run as..</li>
  </ul>
  
  <p>Instance1 </p>
  
  <ul>
  <li>pid: 1234</li>
  <li>run as: domainA\ad_user1</li>
  <li>txtPid: 5678  (Instance2, doesn't work)</li>
  <li>txtPid: 1234  (self, works)</li>
  <li>txtPid: any pid run as the same account (ex: notepad.exe, calc.exe, etc, works)</li>
  </ul>
  
  <p>Instance2</p>
  
  <ul>
  <li>pid: 5678</li>
  <li>run as: localcomputer\l_user1</li>
  <li>txtPid: 1234  (Instance 1, doesnt work)</li>
  <li>txtPid: 5678  (self, works)</li>
  <li>txtPid: any pid run as the same account (localcomputer\l_user1) (ex: notepad.exe, calc.exe, etc, doesn't work!!)</li>
  </ul>
  
  <p><strong>Again, my Question</strong></p>
  
  <p><em><strong>How to change other app's window opacity that run as different user account?</em></strong></p>
  
  <p>Thanks and sorry for my bad English :(.</p>