uragus
Goto Top

Start MsgBox in User Session

Hallo,
Ich habe eine BAT Datei die mit Hilfe von VBS eine MsgBox aufruft.
Die BAT wird in Session 0 ausgeführt, somit sieht der User die MsgBox nicht.
Kann mir jemand helfen die Msf für den User sichtbar zu machen?

@echo off

call :MsgBox "KAV Installieren?"  "VBYesNo+VBQuestion" "KAV"  
if errorlevel 7 (
        echo NO
) else if errorlevel 6 (
        echo YES
        start "" "Setup.exe"  
)

exit /b

:MsgBox prompt type title
    setlocal enableextensions
    set "tempFile=%temp%\%~nx0.%random%%random%%random%vbs.tmp"  
    >"%tempFile%" echo(WScript.Quit msgBox("%~1",%~2,"%~3") & cscript //nologo //e:vbscript "%tempFile%"  
    set "exitCode=%errorlevel%" & del "%tempFile%" >nul 2>nul  
    endlocal & exit /b %exitCode%

Content-ID: 252834

Url: https://administrator.de/contentid/252834

Ausgedruckt am: 26.11.2024 um 10:11 Uhr

DerWoWusste
DerWoWusste 23.10.2014 um 10:45:00 Uhr
Goto Top
Hi.

Fernab von vbs: Wenn Du als Admin oder Systemkonto
msg * Nachricht
aufrufst, geht das an alle Sessions.
Friemler
Lösung Friemler 23.10.2014 aktualisiert um 11:24:30 Uhr
Goto Top
Hallo Uragus,

seit Windows Vista können Prozesse, die in Session 0 laufen, nicht mehr über die MessageBox-API mit der User-Session komunizieren. Es gibt dafür jedoch den speziellen Win32-API-Aufruf WTSSendMessage, den Du allerdings aus einem VBScript heraus nicht ansprechen kannst. Einzige Möglichkeit wäre demnach, ein kleines Programm (z.B. in C oder C++) zu schreiben, das WTSSendMessage benutzt, um die per Parameter übergebene Message anzuzeigen. Dieses Programm kannst Du aus Deinem Batchscript heraus starten.

Ein MSDN-Artikel, der sich mit der Problematik beschäftigt, findet sich hier.

Evtl. findet sich ja auch per Google ein fertiges Tool, was genau das benötigte macht. Das Problem hatten bestimmt schon andere vor Dir.

Gruß
Friemler


[EDIT]
Aha, DerWoWusste macht seinem Namen wieder mal alle Ehre. face-wink
[/EDIT]
Uragus
Uragus 23.10.2014 um 11:26:08 Uhr
Goto Top
Danke für die Aufklärung.
Friemler
Lösung Friemler 24.10.2014, aktualisiert am 08.11.2014 um 13:00:20 Uhr
Goto Top
Ich habe dann doch noch das Hilfsprogramm zum Anzeigen von Messageboxen aus Session 0 heraus geschrieben. Ich habe es mit der Open Source IDE CodeBlocks in C für MinGW entwickelt.

Fertig compilierte Binaries von MinGW findet man hier.

User @rubberman hat außerdem hier eine sehr schöne Anleitung veröffentlicht, um die CodeBlocks IDE incl. MinGW mit Hilfe eines von ihm entwickelten VBScripts als portable Version zu betreiben.

Für den folgenden Code eine Datei namens main.c anlegen und ihn dort hinein kopieren. Aber ACHTUNG!! Die Datei bitte in der Codierung UTF-8 mit BOM (Byte Order Mark) abspeichern!
#define _WIN32_WINNT 0x0600   {{comment_single_line_double_slash:0}}
#include <sdkddkver.h>        {{comment_single_line_double_slash:1}}

#define WIN32_LEAN_AND_MEAN   {{comment_single_line_double_slash:2}}
#define STRICT 1              {{comment_single_line_double_slash:3}}

#define UNICODE               {{comment_single_line_double_slash:4}}
#define _UNICODE              {{comment_single_line_double_slash:5}}
#include <wchar.h>            {{comment_single_line_double_slash:6}}

#include <stddef.h>           {{comment_single_line_double_slash:7}}
#include <stdlib.h>

#include <windows.h>          {{comment_single_line_double_slash:8}}
#include <wtsapi32.h>




/* ******************* */
/* Function prototypes */
/* ******************* */
INT  wmain(INT argc, WCHAR *argv);
BOOL parseCmdLine(INT argc, WCHAR *argv, LPWSTR *message, LPWSTR *title, DWORD *buttons, WINBOOL *waitForClick, DWORD *timeout);




/* ************ */
/* Main program */
/* ************ */
INT wmain(INT argc, WCHAR *argv)
{
  WCHAR   exeName[_MAX_FNAME+1] = L"";  
  LPWSTR  title                 = L"";  
  LPWSTR  message               = NULL;
  DWORD   buttons               = MB_ICONINFORMATION | MB_OK;
  DWORD   titleLength           = 0;
  DWORD   messageLength         = 0;
  DWORD   timeout               = 0;
  WINBOOL waitForClick          = FALSE;
  DWORD   response              = -1;

  DWORD   physConSession = WTSGetActiveConsoleSessionId();

  if (physConSession != 0xFFFFFFFF)
  {
    if (parseCmdLine(argc, argv, &message, &title, &buttons, &waitForClick, &timeout))
    {
      // Die Stringlängen müssen auch bei Unicode-Strings
      // in Bytes angegeben werden!
      messageLength = wcslen(message) * sizeof(*message);
      titleLength   = wcslen(title)   * sizeof(*title);

      WTSSendMessage(WTS_CURRENT_SERVER_HANDLE,
                     physConSession,
                     title, titleLength,
                     message, messageLength,
                     buttons,
                     timeout,
                     &response,
                     waitForClick);
    }
    else
    {
      _wsplitpath(argv, NULL, NULL, exeName, NULL);

      _cwprintf(L"%ls \"Nachricht\" [-h:\"Titel\"] [-b:Buttons] [t:Wartezeit] [/w:true]\n" \  
                L"\n" \  
                L"Nachricht  Text der anzuzeigenden Nachricht.\n" \  
                L"Titel      Text, der in der Titelzeile der Message Box angezeigt wird.\n" \  
                L"Buttons    Eine Zahl, in der der Typ des anzuzeigenden Icons, die darzustellen-\n" \  
                L"           den Buttons und die Nummer des Default-Buttons codiert wird. Die\n" \  
                L"           möglichen Werte finden sich in der Dokumentation der MessageBox-\n" \  
                L"           Funktion auf MSDN.\n" \  
                L"Wartezeit  Wartezeit in Sekunden, nach der sich die Message Box von selbst\n" \  
                L"           schliesst. Ein Wert von 0 führt dazu, dass der Benutzer zuerst auf\n" \  
                L"           einen der Buttons klicken muss, bis die Box geschlossen wird.\n" \  
                L"/w:true    Wird dieser Parameter angegeben, wird erst nachdem die Message Box\n" \  
                L"           geschlossen wurde, die Kontrolle an den Aufrufer zurück gegeben.\n" \  
                L"\n" \  
                L"Das Programm setzt den ERRORLEVEL entsprechend dem Rückgabewert der Message\n" \  
                L"Box. Die möglichen Werte und ihre Bedeutung findet man ebenfalls in der\n" \  
                L"Dokumentation der MessageBox-Funktion auf MSDN."\  
                L"\n",  
                exeName);
    }
  }

  return response;
}



BOOL parseCmdLine(INT argc, WCHAR *argv, LPWSTR *message, LPWSTR *title, DWORD *buttons, WINBOOL *waitForClick, DWORD *timeout)
{
  INT   cnt;
  WCHAR paramName[4];

  for (cnt = 1; cnt < argc; cnt++)
  {
    wcsncpy(paramName, argv[cnt], 3);
    paramName[3] = 0;

    if      (wcsnicmp(paramName, L"/h:", 3) == 0)  
      *title = &argv[cnt][3];

    else if (wcsnicmp(paramName, L"/w:", 3) == 0)  
      *waitForClick = wcsnicmp(&argv[cnt][3], L"true", 4) == 0 ? TRUE : FALSE;  

    else if (wcsnicmp(paramName, L"/t:", 3) == 0)  
      *timeout = wcstoul(&argv[cnt][3], NULL, wcsnicmp(&argv[cnt][3], L"0x", 2) == 0 ? 16 : 10);  

    else if (wcsnicmp(paramName, L"/b:", 3) == 0)  
      *buttons = wcstoul(&argv[cnt][3], NULL, wcsnicmp(&argv[cnt][3], L"0x", 2) == 0 ? 16 : 10);  

    else
      *message = argv[cnt];
  }

  return(*message != NULL);
}

Im gleichen Verzeichnis dann eine Batchdatei namens build.cmd anlegen und folgenden Code hineinkopieren:
@echo off & setlocal

set "PrjName=ServiceMessage"  
set "SourceFile=main"  

set "PrjPath=%~dp0"  
set "GCCPath=E:\CodeBlocksPortable\CodeBlocks\mingw32\bin"  

cd /d "%GCCPath%"  

gcc.exe -finput-charset=UTF-8 -g -O2 -I..\mingw\include -c "%PrjPath%\%SourceFile%.c" -o "%PrjPath%\%SourceFile%.o"  
g++.exe -L..\mingw\lib -o "%PrjPath%\%PrjName%.exe" "%PrjPath%\%SourceFile%.o" -s -municode -static-libgcc -lkernel32 -lwtsapi32  
In Zeile 7 muss man den Pfad zu dem Verzeichnis eintragen, in dem die gcc.exe gespeichert ist. Durch Start der Batchdatei wird der obige C-Quelltext übersetzt. Die erstellte EXE-Datei wird im gleichen Verzeichnis wie die build.cmd abgelegt.

Gruß
Friemler


[EDIT]
Der Quellcode und das Build-Script erzeugen jetzt ein Unicode-fähiges Programm.
[/EDIT]
Uragus
Uragus 24.10.2014 um 12:44:13 Uhr
Goto Top
besten Dank