Jump to content

Bring minimized UAC to front/focus/activate and read the scripts output


Go to solution Solved by Nine,

Recommended Posts

Hi there! ūüėÉ

I've 2 simple scripts:

  • Script 1 starts script 2
  • Script 1 gets executed with normal user rights (un-elevated)
  • Script 2 contains an #RequireAdmin and therefor can only start elevated
  • I want to read the output of script 2 with script 1 AND have the UAC of script 2 being activated as fullscreen

Script 1 (Scripts location is the same as script 2 that I'm running with Run()

Local $iPID, $sOutput
$iPID = Run(@ComSpec & " /c " & "C:\Entwicklung\Autoit\Test\Temp.exe", @ScriptDir, @SW_HIDE, 0x2)
ProcessWaitClose($iPID)
$sOutput = StdoutRead($iPID)
StdioClose($iPID)
ConsoleWrite($sOutput)
MsgBox(1, 1, 1)

Script 2 (compiled as Temp.exe)

#RequireAdmin
ConsoleWrite("Return")
MsgBox(1,1,"ADMIN")

Now my problems are the following:

  1. Without the #RequireAdmin I can read the output with no problem, but not with the #RequireAdmin ($sOutput is empty)
  2. Using @SW_HIDE in the Run() command makes the UAC always start minimized (see attached picture) and the admin has to always manually click on the icon to enter his credentials since the UAC doesn't start in fullscreen. Here and on a few other sites they explain that the program launching the elevated program NEEDS to be activated in order to directly show the UAC fullscreen and not minimized. Using @SW_SHOW would get rid of the problem, BUT that leaves me with an ugly cmd.exe floating the whole time while the elevated script ist running.

And my questions to that I'm seeking an answer for are:

  • Problem 1:¬†Is it just not possible to read from an elevated program with an un-elevated user/script? I also get the Access Denied if I press No on the UAC as an Output in¬†$sOutput¬†(Guess since its's still un-elevated)
  • Problem 2:¬†Is there a way to either make the floating black and blank cmd.exe being moved to the background and be non visible to the user¬†OR¬†to somehow bring the minimized UAC to the foreground/fullscreen?

What I already tried and what didn't help me:

  • $iPID = Run(@ComSpec & " /c " & "C:\Entwicklung\Autoit\Test\Temp.exe", @ScriptDir, @SW_HIDE, 0x2)
    While Not WinExists("Temp.exe erfordert Ihre Berechtigung")
        ConsoleWrite(1)
    WEnd
    WinActivate("Temp.exe erfordert Ihre Berechtigung")
    WinSetState("Temp.exe erfordert Ihre Berechtigung", WinGetText("Temp.exe erfordert Ihre Berechtigung"), @SW_SHOW)
    WinSetState("Temp.exe erfordert Ihre Berechtigung", WinGetText("Temp.exe erfordert Ihre Berechtigung"), @SW_MAXIMIZE)
    WinSetState("Temp.exe erfordert Ihre Berechtigung", WinGetText("Temp.exe erfordert Ihre Berechtigung"), @SW_ENABLE)

    The While-Loops helps a lot and also stops after a second or so (‚Ėļ Stops to write ones (1)). That means that the actual "window" of the UAC is found, but all the WinXXX functions don't do anything and the UAC stays minimized. I also tried to minimized/move the cmd.exe to the background with WinActivate() and WinSetState() with no success.

  • $iPID = ShellExecute("C:\Entwicklung\Autoit\Test\Temp.exe", "", @ScriptDir, "open", @SW_HIDE)

    Using ShellExecute() instead of Run() completely solves the UAC to fullscreen problem BUT I haven't found a consistent way to read the output of ShellExecute(). Neither here on the forum nor somewhere else. If I'd be possible to read the output from ShellExecute() then all my problems would be solved at once!

  • Also tried a few more things and playing with some parameters but everything with no success.

I'd really love some help and support here from you.

Thanks in advance!

 

UAC_Minimized.png

Edited by Doniel
Changed Tags

‚ÄúIt is only when a mosquito lands on your testicles that you realize there is always a way to solve problems without using violence.‚ÄĚ
‚Äē Confucius

Link to post
Share on other sites
  • Developers
15 minutes ago, Doniel said:

Problem 1: Is it just not possible to read from an elevated program with an un-elevated user/script?

Correct!   I use a MailSlot priciple in AutoIt3Wrapper to let the Elevated script send the captured output to the script running at normal level. So the elevated level script needs to read the STDOUT&ERR itself.

19 minutes ago, Doniel said:

Problem 2: Is there a way to either make the floating black and blank cmd.exe being moved to the background and be non visible to the user OR to somehow bring the minimized UAC to the foreground/fullscreen?

Don't use @COMSPEC, but rather run the program itself with @SW_SHOW. 

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to post
Share on other sites

Hi @Jos and thanks for the reply.

17 hours ago, Jos said:

I use a MailSlot priciple in AutoIt3Wrapper to let the Elevated script send the captured output to the script running at normal level. So the elevated level script needs to read the STDOUT&ERR itself.

Thanks, I've never heard of the MailSlot principle. I'll look into this and try to understand it. Do you have an example script from your side to help me get going to read the output from another script? EDIT: The linked .zip has an example!

17 hours ago, Jos said:

Don't use @COMSPEC, but rather run the program itself with @SW_SHOW. 

Forgot to mention because I tried so much, but sadly I already tried this Run():

$iPID = Run("C:\Entwicklung\Autoit\Test\Temp.exe", @ScriptDir, @SW_SHOW, 0x2)

But nothing happens and the called elevated script never shows up. The @error is 1 and @extended ist 740. Seems like I need another program (In this case @COMSPEC) to call my elevated script in order for anything to happen.

Edited by Doniel

‚ÄúIt is only when a mosquito lands on your testicles that you realize there is always a way to solve problems without using violence.‚ÄĚ
‚Äē Confucius

Link to post
Share on other sites
18 hours ago, Doniel said:

 

  • Problem 2:¬†Is there a way to either make the floating black and blank cmd.exe being moved to the background and be non visible to the user¬†OR¬†to somehow bring the minimized UAC to the foreground/fullscreen?

 

 

$iPID = Run(@ComSpec & " /c " & "start temp.exe", @ScriptDir, Default, 0x10)

iam ŔźAutoit¬†programmer.

best thing in life is to use your Brain to

Achieve

everything you want.

Link to post
Share on other sites

Thanks for your reply @ad777!

I've the following good results with your suggestion to use Default and 0x10:

$iPID = Run(@ComSpec & " /c " & "C:\Entwicklung\Autoit\Test\temp.exe", @ScriptDir, @SW_HIDE, 0x10)      ; UAC starts minimized and cmd.exe is not visible!
$iPID = Run(@ComSpec & " /c " & "C:\Entwicklung\Autoit\Test\temp.exe", @ScriptDir, Default, 0x10)       ; UAC starts maximized and cmd.exe is not visible!
$iPID = Run(@ComSpec & " /c " & "C:\Entwicklung\Autoit\Test\temp.exe", @ScriptDir, Default)             ; UAC starts maximized and cmd.exe is not visible!
$iPID = Run(@ComSpec & " /c " & "C:\Entwicklung\Autoit\Test\temp.exe", @ScriptDir)                      ; UAC starts maximized BUT cmd.exe is visible!

Besides the fact that I don't understand 0x10 and it also seems to not be needed, it's weird that Default and @SW_HIDE give different results, because in the help file of Run() it's says that they are equal:

Quote
show_flag  [optional] The "show" flag of the executed program:
    @SW_HIDE = Hidden window (or Default keyword)

Might that be a mistake in the documentation or why do I get 2 different behaviours with @SW_HIDE and "Default keyword" @Jos? Would've expected the same behaviour here.

 

Anyways, with this command..

$iPID = Run(@ComSpec & " /c " & "C:\Entwicklung\Autoit\Test\temp.exe", @ScriptDir, Default)             ; UAC starts maximized and cmd.exe is not visible!

.. the cmd.exe windows won't show anymore. That is great news!! Thanks!

Now I "just" need to get the output of the elevated script. I looked into MailSlot and it seems to work fine with non elevated communication.
But if I elevate the script that "sends" the message I get an error in the _MailSlotWrite() function from @trancexx as I tried out MailSlot_Sender.au3 and MailSlot_Reciever.au3.

To be precise, this part of the function fails (I run into Return SetError(1, 0, 0))

Local $aCall = DllCall("kernel32.dll", "ptr", "CreateFileW", _
            "wstr", $sMailSlotName, _
            "dword", 0x40000000, _ ; GENERIC_WRITE
            "dword", 1, _ ; FILE_SHARE_READ
            "ptr", 0, _
            "dword", 3, _ ; OPEN_EXISTING
            "dword", 0, _ ; SECURITY_ANONYMOUS
            "ptr", 0)

If @error Or $aCall[0] = -1 Then
    Return SetError(1, 0, 0)
EndIf

Is the elevated user having problems with the DLL? I've never worked with DLLs so I really can't say anything about this :(

 

But since @Jos confirmed, that I can't read the output "the normal way" anyways and I basically HAVE to use "third party"..

Quote

Is it just not possible to read from an elevated program with an un-elevated user/script

.. then I could also use (what I wanted to avoid) FileWrite() functions and write the output to a file and read that with the elevated script, no? So what could be the benefit of using MailSlot mechanisms here?

Edited by Doniel
Typos

‚ÄúIt is only when a mosquito lands on your testicles that you realize there is always a way to solve problems without using violence.‚ÄĚ
‚Äē Confucius

Link to post
Share on other sites
  • Developers

Mailslot can pipe the output directly to the script that shelled the second elevated script in stead of using a file as output... but either way will/could work depending on the requirements.

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to post
Share on other sites
58 minutes ago, Jos said:

Mailslot can pipe the output directly to the script that shelled the second elevated script in stead of using a file as output... but either way will/could work depending on the requirements.

Hi @Jos,

I've been researching the last one hour and think that I got a better understanding of ICP (Never heard of it before lol) and Mailslots.

I also tried to do it without the UDF and can't get further than this, since I don't understand what the input needs to be for the pointer and buffer:

#include <NamedPipes.au3>
Local $sPipeName = "\\.\mailslot\RandomNameForThisTest"

$hPipe=_NamedPipes_CreateNamedPipe($sPipeName)
While 1
    If _NamedPipes_CallNamedPipe($sPipeName, "Data I guess", ??? , ??? , ???, ???) Then MsgBox(1,1,1) ;To test for success (but always fails) - ??? ofc just a placeholder
    Sleep(1000)
WEnd

But coming back to the UDF or generally Mailslots: You said I can do ICP between an elevated and un-elevated script using Mailslots if I "pipe the output directly to the script". But how does this work? I haven't found anything about a "direct pipe". I always found and think that I need to created an MailSlot e.g. \\.\mailslot\RandomNameForThisTest

Do you have a script to get me started? I'm kinda in the dark right know, sorry!

Thanks

‚ÄúIt is only when a mosquito lands on your testicles that you realize there is always a way to solve problems without using violence.‚ÄĚ
‚Äē Confucius

Link to post
Share on other sites
  • Developers

Well the Mailslot.zip file contains all you need to know as it has an Sender & Receiver script example there as well.

The receiver is your script 1 and the Sender is your Script 2 (the elevated one). ;) 

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to post
Share on other sites

a file is named by a filename  \\?\C:\file.extOrNot
a pipe is named by a filename \\.\pipe\whaterver
a mailsot is named by a filename \\.\mailslot\any\name

So there. Should not be lost anymore.
Pipe will overwrite but a mailslot will add it to the list of messages. I like mailsots. Read around for caveats and limitations :)

Edited by argumentum
oops
Link to post
Share on other sites

Hi, like I said earlier:

Quote

I looked into MailSlot and it seems to work fine with non elevated communication.
But if I elevate the script that "sends" the message I get an error in the _MailSlotWrite() function from @trancexx as I tried out MailSlot_Sender.au3 and MailSlot_Reciever.au3.

So i checked the Function _MailSlotWrite() and the DLLCall() seems to work fine with the elevated user since @error is 0 and I also get an array returned that I can look at with _ArrayDisplay() (see attachments!):

Func _MailSlotWrite($sMailSlotName, $vData, $iMode = 0)
    Local $aCall = DllCall("kernel32.dll", "ptr", "CreateFileW", _
            "wstr", $sMailSlotName, _
            "dword", 0x40000000, _ ; GENERIC_WRITE
            "dword", 1, _ ; FILE_SHARE_READ
            "ptr", 0, _
            "dword", 3, _ ; OPEN_EXISTING
            "dword", 0, _ ; SECURITY_ANONYMOUS
            "ptr", 0)
    _ArrayDisplay($aCall) ;added by me
    If @error Or $aCall[0] = -1 Then
        Return SetError(1, 0, 0)
    EndIf
    ...

I've no understanding of DLLs, but from what I researched it seems like that in the kernel32.dll there is a function called CreateFileW that we try to call with DLLCall() and it's parameters. Just the call itself works fine with elevated and un-elevated. But with the elevated I run into the Return SetError(1, 0, 0) part because $aCall[0] contains 0xFFFFFFFF (see attachments) for the elevated user and therefore nothing will be sent. I assume that it's the return (Pointer?) of CreateFileW. For an un-elevated user I get e.g. 0x000002CC. That seems to be an actual address with that the program can work with.

So why do I get 0xFFFFFFFF with the elevated user as a return from CreateFileW? I've serached online for..

Quote

"CreateFileW" returns 0xFFFFFFFF

.. and the limitations of MailSlots with elevated users but can't find something for it.

 

And @argumentum thanks for your reply. I now know that pipe and MailSlots are different. I'd be happy to get both working with different privileged processes. For now MailSlot (1:n) will do it and generally offers more then just pipe (1:1). But I'll definitely try to learn both! Is the "pipe" you mean the same as the "|" in PowerShell? I'd assume so since you give the result from one function directly to another.

 

I am really trying hard to get it to work. It's just a new topic for me, since in all the years of AutoIt I've never been so "deep" in the system.

Thanks for your help and patience. 

un-elevated-result.png

elevated-result.png

‚ÄúIt is only when a mosquito lands on your testicles that you realize there is always a way to solve problems without using violence.‚ÄĚ
‚Äē Confucius

Link to post
Share on other sites
  • Solution

I have been working on Named Pipes for quite awhile now (see my sig for an overlapped UDF of named pipes).  I believe the solution here is to create a security descriptor (that should work both for NP and MailSlot).  Here a basic example of it (non-overlapped).  Tested on Win7 and working :

Server (or receiver) :

; https://www.autoitscript.com/forum/topic/138112-named-pipe-problem/?tab=comments#comment-967805

#include <NamedPipes.au3>
#include <WinAPI.au3>
MsgBox(0, "server", "starting pipe")
Local Const $SECURITY_DESCRIPTOR_REVISION = 1
Local $tSecurityDescriptor = DllStructCreate("byte;byte;word;ptr[4]")
Local $aRet = DllCall("Advapi32.dll", "bool", "InitializeSecurityDescriptor", _
    "struct*", $tSecurityDescriptor, "dword", $SECURITY_DESCRIPTOR_REVISION)
If @error Then Exit MsgBox(0, "Error", "@error = " & @error & " / " & @extended)
If Not $aRet[0] Then Exit MsgBox(0, "Error", "Win err = " & _WinAPI_GetLastError() & " / " & _WinAPI_GetLastErrorMessage())

$aRet = DllCall("Advapi32.dll", "bool", "SetSecurityDescriptorDacl", _
    "struct*", $tSecurityDescriptor, "bool", 1, "ptr", 0, "bool", 0)
If @error Then Exit MsgBox(0, "Error", "@error = " & @error & " / " & @extended)
If Not $aRet[0] Then Exit MsgBox(0, "Error", "Win err = " & _WinAPI_GetLastError() & " / " & _WinAPI_GetLastErrorMessage())

Local $tSecurityAttributes = DllStructCreate($tagSECURITY_ATTRIBUTES)
$tSecurityAttributes.Length = DllStructGetSize($tSecurityAttributes)
$tSecurityAttributes.Descriptor = DllStructGetPtr($tSecurityDescriptor)
$tSecurityAttributes.InheritHandle = True
Local $hNamedPipe = _NamedPipes_CreateNamedPipe("\\.\pipe\PipeTest", 2, 1, 0, 1, 1, 0, 2, 4096, 4096, 5000, $tSecurityAttributes)
_NamedPipes_ConnectNamedPipe($hNamedPipe)

Local $tBuffer = DllStructCreate("char str[100]"), $iRead
_WinAPI_ReadFile($hNamedPipe, $tBuffer, 100, $iRead)
ConsoleWrite($iRead & "/" & $tBuffer.str & @CRLF)

ConsoleWrite(_NamedPipes_DisconnectNamedPipe($hNamedPipe) & @CRLF)
ConsoleWrite(_WinAPI_CloseHandle ($hNamedPipe) & @CRLF)

Client (or sender) :

#RequireAdmin
#include <WinAPI.au3>

$hFile = _WinAPI_CreateFile("\\.\pipe\PipeTest", 2, 6)
If Not $hFile Then Exit MsgBox(0, "error", _WinAPI_GetLastError() & ": " & _WinAPI_GetLastErrorMessage())
Local $tBuffer = DllStructCreate("char str[100]"), $iWritten
$tBuffer.str = "Test"
_WinAPI_WriteFile($hFile, $tBuffer, 5, $iWritten)
MsgBox($MB_SYSTEMMODAL, "Bytes written", $iWritten)

_WinAPI_CloseHandle($hFile)

Run server from Scite.  Run client from Explorer.

Link to post
Share on other sites

Hi @Nine, thanks a lot for the reply!

The rest of today I'll be in an workshop. Tomorrow I'll try to go through the code you sendend and your linked UDF.

I'll keep you posted..¬†ūüėÉ

‚ÄúIt is only when a mosquito lands on your testicles that you realize there is always a way to solve problems without using violence.‚ÄĚ
‚Äē Confucius

Link to post
Share on other sites

After some more testing, the security descriptor is not mandatory when the client is elevated and not the server.  It is mandatory though is you want to write the pipe from another PC or if the server is elevated and the client is not.

ps. Tested on a win10 machine and it is working flawlessly.

Edited by Nine
Link to post
Share on other sites

Hi again @Nine!

Thanks for the code. I modified your code from Thursday at 02:59 PM a little bit and came out with this:

Receiver (un-elevated / non-admin):

; https://www.autoitscript.com/forum/topic/138112-named-pipe-problem/?tab=comments#comment-967805

#include <NamedPipes.au3>
#include <WinAPI.au3>
MsgBox(0, @ScriptName, "starting pipe")
Local Const $SECURITY_DESCRIPTOR_REVISION = 1
Local $tSecurityDescriptor = DllStructCreate("byte;byte;word;ptr[4]")
Local $aRet = DllCall("Advapi32.dll", "bool", "InitializeSecurityDescriptor", _
        "struct*", $tSecurityDescriptor, "dword", $SECURITY_DESCRIPTOR_REVISION)
If @error Then Exit MsgBox(0, "Error", "@error = " & @error & " / " & @extended)
If Not $aRet[0] Then Exit MsgBox(0, "Error", "Win err = " & _WinAPI_GetLastError() & " / " & _WinAPI_GetLastErrorMessage())

$aRet = DllCall("Advapi32.dll", "bool", "SetSecurityDescriptorDacl", _
        "struct*", $tSecurityDescriptor, "bool", 1, "ptr", 0, "bool", 0)
If @error Then Exit MsgBox(0, "Error", "@error = " & @error & " / " & @extended)
If Not $aRet[0] Then Exit MsgBox(0, "Error", "Win err = " & _WinAPI_GetLastError() & " / " & _WinAPI_GetLastErrorMessage())

Local $tSecurityAttributes = DllStructCreate($tagSECURITY_ATTRIBUTES)
$tSecurityAttributes.Length = DllStructGetSize($tSecurityAttributes)
$tSecurityAttributes.Descriptor = DllStructGetPtr($tSecurityDescriptor)
$tSecurityAttributes.InheritHandle = True
Local $hNamedPipe = _NamedPipes_CreateNamedPipe("\\.\pipe\PipeTest", 2, 1, 0, 1, 1, 0, 2, 4096, 4096, 5000, $tSecurityAttributes)
_NamedPipes_ConnectNamedPipe($hNamedPipe)
Local $tBuffer = DllStructCreate("char str[100]"), $iRead
While 1 ; modified by me for better testing
    If Not _WinAPI_ReadFile($hNamedPipe, $tBuffer, 100, $iRead) Then
        MsgBox(0, @ScriptName & " - Error", "Pipe got closed on senders-end")
        ExitLoop
    Else
        ConsoleWrite($iRead & "/" & $tBuffer.str & @CRLF)
    EndIf
WEnd
ConsoleWrite(_NamedPipes_DisconnectNamedPipe($hNamedPipe) & @CRLF)
ConsoleWrite(_WinAPI_CloseHandle($hNamedPipe) & @CRLF)

Sender (elevated / admin):

#RequireAdmin
#include <WinAPI.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("PipeTest", 429, 298, 192, 124)
GUISetBkColor(0xFFFFFF)
$Edit1 = GUICtrlCreateEdit("", 8, 8, 265, 281)
$Button1 = GUICtrlCreateButton("Create Pipe", 288, 8, 75, 25)
$Button2 = GUICtrlCreateButton("Send Data", 288, 48, 75, 25)
$Button3 = GUICtrlCreateButton("Close Pipe", 288, 88, 75, 25)
$Button4 = GUICtrlCreateButton("Exit", 288, 128, 75, 25)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

$hFile = ""
While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE, $Button4
            Exit CloseFile()
        Case $Button1
            $hFile = __CreateFile("\\.\pipe\PipeTest")
        Case $Button2
            __SendData(GUICtrlRead($Edit1), $hFile, "\\.\pipe\PipeTest")
        Case $Button3
            CloseFile()
    EndSwitch
WEnd

Func __CreateFile($s_File)
    Local $h_File
    If $hFile Then
        MsgBox(0, @ScriptName & " - Error", "Pipe already exists!", Default, $Form1)
        Return $hFile
    Else
        $h_File = _WinAPI_CreateFile($s_File, 2, 6)
        If Not $h_File Then
            MsgBox(0, @ScriptName & " - Error", _WinAPI_GetLastError() & ": " & _WinAPI_GetLastErrorMessage(), Default, $Form1)
            Return $h_File
        Else
            MsgBox(0, @ScriptName, "Pipe successfully created!", Default, $Form1)
            Return $h_File
        EndIf
    EndIf
EndFunc   ;==>__CreateFile

Func __SendData($s_Data, $h_File, $s_File)
    If $hFile Then
        If StringLen($s_Data) > 0 Then
            Local $tBuffer = DllStructCreate("char str[" & StringLen($s_Data) & "]"), $iWritten
            $tBuffer.str = $s_Data
            _WinAPI_WriteFile($h_File, $tBuffer, StringLen($s_Data), $iWritten)
            If $iWritten > 0 Then
                GUICtrlSetData($Edit1, "")
                MsgBox(0, @ScriptName, "Success! - Message sent: " & $s_Data & @CRLF & @CRLF & "Bytes sent: " & $iWritten, Default, $Form1)
            Else
                MsgBox(0, @ScriptName & " - Error", "Nothing was sent!", Default, $Form1)
            EndIf
        Else
            MsgBox(0, @ScriptName & " - Error", "Type something in the textbox!", Default, $Form1)
        EndIf
    Else
        MsgBox(0, @ScriptName & " - Error", "The pipe has not been created!", Default, $Form1)
    EndIf
EndFunc   ;==>__SendData

Func CloseFile()
    If $hFile Then
        _WinAPI_CloseHandle($hFile)
        $hFile = ""
    EndIf
EndFunc   ;==>CloseFile


#cs =====> orignal
    $hFile = _WinAPI_CreateFile("\\.\pipe\PipeTest", 2, 6)
    If Not $hFile Then Exit MsgBox(0, "error", _WinAPI_GetLastError() & ": " & _WinAPI_GetLastErrorMessage())
    Local $tBuffer = DllStructCreate("char str[100]"), $iWritten
    While 1
        $tBuffer.str = @SEC
        _WinAPI_WriteFile($hFile, $tBuffer, 5, $iWritten)
        ;MsgBox($MB_SYSTEMMODAL, "Bytes written", $iWritten)
        If @MIN == "15" Then ExitLoop
    WEnd
    _WinAPI_CloseHandle($hFile)
#ce =====> orignal

Like this it's really straight forward to send a message from the elevated script to the normal (un-elevated) script. Give it a try if you want :)
Now the script above was just generally for me, so I can understand how pipes work. As shorter functions with no MsgBox' they'll suit me perfectly in my future projects, thanks!

I also checked out your Overlapped Named Pipe IPC but got lost quite fast!

I also tried to play with the security descriptor like you suggested in combination with Mailslots but didn't move more than before.. For now the pipe is working and that'll be enough for now!

Maybe one day I'll look into Mailslots again, but for now the effort would be too much (80/20 ;)) since IPC is completely new for me.

Thanks again!!

 

To sum up:

From an non-elevated script I can start an..

  1. ..elevated script..
  2. ..with no visible cmd.exe..
  3. ..and an non-minimized UAC (User Account Control)..

..with the command e.g.:

$iPID = Run(@ComSpec & " /c " & "C:\Entwicklung\Autoit\Test\temp.exe", @ScriptDir, Default)     ; the keyword "Default" MUST be included!!

Since I can't read the output the normal way (I/O-streams) I've to use IPC (Interprocess Communication) e.g. MailSlots or Pipes.

I can modify the functions from the Sender and Receiver Script I made (see above in this post) to not give me any unwanted pop-ups.
Then I can use them to communicate from the elevated script to the non-elevated script.

Edited by Doniel

‚ÄúIt is only when a mosquito lands on your testicles that you realize there is always a way to solve problems without using violence.‚ÄĚ
‚Äē Confucius

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By UE_morf_boon
      Hi!
      I have a program that has a specific function that renames the computer.
      The entire program should be executed only on behalf of the current user, because some registry keys in the HKCU are being changed.
      The current user does not have administrator rights, so #Requireadmin is not suitable as a solution.
      The administrator accounts on the computers are different, so "RunAs" is not suitable.
      Is there a way to trigger a UAC, when running a function?
      The function code, if you need:
      Func _RenamePC($Input2) Local $Name = GUICtrlRead($Input2) $objWMIService = ObjGet("winmgmts:\root\cimv2") For $objComputer In $objWMIService.InstancesOf("Win32_ComputerSystem") $oReturn = $objComputer.rename($Name) Next EndFunc  
    • By Iraj
      Hello Team, Greetings!
      Is there any way to run any 3rd party application silently in background without the GUI getting in the front ?
      I was implementing angry-ip scanner with autoit & wanted the angry-ip application to run in background quietly as I am copying its output to other file on completion. is there any way to achieve my query?
      Below is code I tried: 
      $range = "192.168.0.1 192.168.0.255" ShellExecuteWait("C:\Windows\DDM\ipscan.exe","-f:range "&$iprange&" -q -o C:\temp\ScanResults.csv","","open",@SW_HIDE) Thanks!
    • By Iraj
      I am new to AutoIT & need to run application with different user credentials.
      I am using below script with RunAs() but the application is not invoking.
      #include <AutoItConstants.au3> $sUserName = $CMDLine[1] $sDomain = $CMDLine[2] $sPassword = $CMDLine[3] RunAs($sUserName, $sDomain, $sPassword, $RUN_LOGON_NOPROFILE,"ssms.exe") Kindly assist! Thank you
    • By chenni037
      I need to save the execution result as a text file. Is there any solution?
      ShellExecute ( "filename" [, "parameters" [, "workingdir" [, "verb" [, showflag]]]] )    if  parameters have " > " can't Execute correctly, 
      Example 1:
      ShellExecute("diskspd.exe", "-b128K  -c64M f:\estfile.dat > test123.txt", "", "", @SW_MAXIMIZE)  ;Error
      ShellExecute("diskspd.exe", "-b128K  -c64M f:\estfile.dat", "", "", @SW_MAXIMIZE)                         ;OK
      Example 2:
      ShellExecute("help", "dir > helpdir.txt", "", "", @SW_MAXIMIZE)  ;Error
      ShellExecute("help", "dir", "", "", @SW_MAXIMIZE)                         ;OK
      T1.au3
    • By rudi
      Hi,
      When a non compiled AU3 script is run with #RequireAdmin, then if the UAC prompt can be authorized due to the fact, that the currently loggedon user has local admin rights, then the macro @UserProfileDir correctly reflects the profile dir of the user of the windows logon session.
       
      When the script with #RequireAdmin is started by a "normal user" without local admin rights, and I use a domain admin account to authorize the UAC prompt, then @UserProfileDir reflects the profile dir belonging to the AD-Admin account.
      As the script originally was started using the "regular user" I'm wondering, if there is a chance to "pass" the original user's @UserProfileDir to the UAC elevated script?
       
      As playing around with this feature I realize, that I basically don't know the exact mechanism of the UAC elevation authorization process:
      The script is started by right mouse click, execute script This is invoking e.g. "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" "C:\Users\Rudi\Desktop\test.au3" as by this registy value: Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\AutoIt3Script\Shell\Run\Command] @="\"C:\\Program Files (x86)\\AutoIt3\\AutoIt3.exe\" \"%1\" %*" But what I honestly don't know is, how does the UAC propt interact in the program startup? I guess, that Autoit3.exe is parsing the AU3 source, is seeing the #RequireAdmin and then "relaunches itself with the AU3 as %1" requesting UAC elevated rights "from windows"??? With Process Explorer I can see, that The commandline then is this one with a "!" before "%1"
      "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" !"C:\Users\Rudi\Desktop\test.au3"  It it should be something like this, then it might be possible to pass the original @UserProfileDir to the second, UAC elevated "Startup"??? <edit>
      I just noticed:
      When I use "WIN+R" and then directly use the command line, I see in Process Explorer, ...
      "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" !"C:\Users\Rudi\Desktop\test.au3"
      ... then this script with #RequireAdmin is started *WITHOUT* UAC elevation.
      Guessing, that this ! is just reverting #RequireAdmin I tried the "opposite" one as well:
      AU3 script without #RequireAdmin Starting with "C:\Program Files (x86)\AutoIt3\AutoIt3.exe" !"C:\Users\Rudi\Desktop\test.au3" does not invoke UAC elevation prompt. So to me it looks like, this ! is a "status flag from Autoit3.exe to Autoit3.exe", that the elevation process was done already? amazing...
      the topic Autoit on Windows Vista is telling no details of  this UAC process...
      </edit>
       
      Regards, Rudi.
×
×
  • Create New...