Essa pessoa brilhante Jborean93 criou um script do PowerShell que por sua vez gera um .exe chamado "noGui.exe" aqui
Vou citar o código para que você não precise procurá-lo:
Add-Type -OutputType WindowsApplication -OutputAssembly NoGui.exe -TypeDefinition @'
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace NoGui
{
class Program
{
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFOW
{
public Int32 cb;
public IntPtr lpReserved;
public IntPtr lpDesktop;
public IntPtr lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public Int32 dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(
IntPtr hObject);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CreateProcessW(
[MarshalAs(UnmanagedType.LPWStr)] string lpApplicationName,
StringBuilder lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
int dwCreationFlags,
IntPtr lpEnvironment,
[MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory,
ref STARTUPINFOW lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("Kernel32.dll")]
public static extern IntPtr GetCommandLineW();
static void Main()
{
IntPtr cmdLinePtr = GetCommandLineW();
string cmdLine = Marshal.PtrToStringUni(cmdLinePtr);
int cmdLineArgsIdx = cmdLine.IndexOf(" -- ");
StringBuilder newCmdLine = new StringBuilder(cmdLine.Substring(cmdLineArgsIdx + 4));
STARTUPINFOW si = new STARTUPINFOW()
{
cb = Marshal.SizeOf<STARTUPINFOW>(),
dwFlags = 0x00000001, // STARTF_USESHOWWINDOW
wShowWindow = 0, // SW_HIDE
};
PROCESS_INFORMATION pi;
bool res = CreateProcessW(
null,
newCmdLine,
IntPtr.Zero,
IntPtr.Zero,
true,
0x00000410, // CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT
IntPtr.Zero,
null,
ref si,
out pi
);
if (res)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
}
}
'@
Quando o NoGui.exe é executado, ele permite que (no meu caso, o PowerShell, mas pode ser qualquer processo) seja executado sem nenhuma janela/shell/prompts/qualquer coisa aparecendo na tela (e funciona).
É quase exatamente o que eu preciso. Mas, pelo que posso perceber, ele não espera que o processo que você solicitou seja encerrado antes de ser encerrado.
Preciso disso porque se eu for usar isso no Microsoft Intune para executar um script do PowerShell, não sei se o Intune detectaria o processo filho do PowerShell e esperaria sua conclusão.
Imagine por um momento que o script do PowerShell gerado pelo NoGui.exe pode levar muito tempo para ser concluído, mas o Intune pensa "ah, bem, o noGui.exe foi concluído, então a instalação deve ser feita". Mas não é o caso.
Então como podemos modificá-lo para:
ele espera que o processo filho termine antes de terminar a si mesmo.
Pontos adicionais, eu acho, se conseguirmos obter o código de saída para retornar ao processo pai e gerar a saída lá. O script do PowerShell explodiu por algum motivo? Tudo bem, o Intune recebeu o código de saída do Nogui.exe, então sabemos o que aconteceu.
Estou ciente de que existem wrappers do VBScript que ocultam a execução do PowerShell, mas não quero usá-los, pois o VBScript será desativado em algum momento no futuro.