Console application launch .exe as current user - c#

I am using trance32, and want to launch this process through Jenkins.
When I am launching T32mppc.exe, it is running as system process because of which it is running in background.
I want to launch this process with current user to see it on foreground without inserting username and password.
My system is having only 2 kind of process. System and User. No other users are there.
Attaching my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.IO;
using System.Globalization;
using System.Xml.Linq;
using System.Diagnostics;
using System.Threading;
using System.Configuration;
namespace Console_Startapps
{
class Program
{
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool SetForegroundWindow(IntPtr handle);
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
[System.Runtime.InteropServices.DllImport("User32.dll")]
private static extern bool IsIconic(IntPtr handle);
[DllImport("User32.dll", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
[DllImport("TRACE32\t32api64.dll")]
public static extern int T32_ResetCPU();
private void startT32app()
{
IntPtr handle;
try
{
Console.WriteLine("T32 launching");
string path = #"C:\T32\bin\windows64\t32mppc.exe";
string args = #"C:\T32\config.t32";
ProcessStartInfo procInfo = new ProcessStartInfo(path, args);
procInfo.CreateNoWindow = false;
procInfo.UseShellExecute = true;
procInfo.WindowStyle = ProcessWindowStyle.Normal;
Process[] targetProcess = Process.GetProcessesByName("t32mppc.exe");
//if (targetProcess.Length > 1)
if (this.IsProcessOpen("t32mppc") == 1)
{
Console.WriteLine("TC32 already running");
}
else
{
Process procRun = Process.Start(procInfo);
handle = procRun.MainWindowHandle;
SwitchToThisWindow(handle, true);
}
//SetForegroundWindow(handle);
}
catch
{
Console.WriteLine("Failed to launch T32");
}
}
private int IsProcessOpen(string name)
{
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.ToLower().Contains(name.ToLower()))
{
return 1;
}
}
return 0;
}
static void Main(string[] args)
{
Program Beginapps = new Program();
Beginapps.startT32app();
}
}
}

Have you tried to impersonate another user?
https://msdn.microsoft.com/en-us/library/w070t6ka(v=vs.110).aspx
Basically, you can run another process with a given credential
How do you do Impersonation in .NET?

Related

How can I move a second opened browser window?

I'm trying to make a program that opens a browser on each multi-display.
When I did it with a notepad, it worked. However, when it's a browser didn't work and showed the error "System.InvalidOperationException: Process must exit before requested information can be determined". I will appreciate your help with this situation.
This is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int MoveWindow(IntPtr hwnd, int x, int y,
int nWidth, int nHeight, int bRepaint);
private void Form1_Load(object sender, EventArgs e)
{
foreach (Screen item in Screen.AllScreens)
{
//Open a web browser
System.Diagnostics.Process process1 = System.Diagnostics.Process.Start("C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe");
//System.Diagnostics.Process process2 = System.Diagnostics.Process.Start("notepad.exe");
process1.WaitForInputIdle();
//process2.WaitForInputIdle();
//Move the browser window
MoveWindow(process1.MainWindowHandle, item.Bounds.X, item.Bounds.Y, item.Bounds.Width, item.Bounds.Height, 1);
//MoveWindow(process2.MainWindowHandle, item.Bounds.X, item.Bounds.Y, item.Bounds.Width, item.Bounds.Height, 1);
}
}
}
}
It seems that msedge.exe use a host process to start different tabs, so we can't use the created process ID to handle it.
Compare created process ID with processes in the Task Manager, the
process 38756 is missing.
Another tool to browse edge relative processes is the built-in task manager of edge.
We can't find process 38756 as well.
So re-search the target edge process is necessary.
This repo https://github.com/alex-tomin/Tomin.Tools.KioskMode demostrate how to move chrome window into different monitors and set as full screen.
I tried to extract the necessary and modify your code like below, hope it helps:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace TestWinFormsApp
{
// Get full definition of SetWindowPosFlags here:
// https://www.pinvoke.net/default.aspx/Enums/SetWindowPosFlags.html
[Flags]
public enum SetWindowPosFlags : uint
{
SWP_NOREDRAW = 0x0008,
SWP_NOZORDER = 0x0004
}
// Get full definition of ShowWindowCommands here:
// https://www.pinvoke.net/default.aspx/Enums/ShowWindowCommand.html
public enum ShowWindowCommands
{
Maximize = 3,
Restore = 9,
}
public static class WinApi
{
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load_1(object sender, EventArgs e)
{
var ignoreHandles = new List<IntPtr>();
foreach (Screen item in Screen.AllScreens)
{
this.StartEdgeProcess();
var windowHandle = this.GetWindowHandle("msedge", ignoreHandles);
ignoreHandles.Add(windowHandle);
WinApi.ShowWindow(windowHandle, ShowWindowCommands.Restore);
WinApi.SetWindowPos(windowHandle, IntPtr.Zero, item.Bounds.Left, item.Bounds.Top, 800, 600, SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOREDRAW);
WinApi.ShowWindow(windowHandle, ShowWindowCommands.Maximize);
}
}
private void StartEdgeProcess()
{
var process = new Process();
process.StartInfo.FileName = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe";
process.StartInfo.Arguments = "about:blank" + " --new-window -inprivate ";
process.Start();
process.WaitForInputIdle();
}
private IntPtr GetWindowHandle(string processName, List<IntPtr> ignoreHandlers)
{
IntPtr? windowHandle = null;
while (windowHandle == null)
{
windowHandle = Process.GetProcesses()
.FirstOrDefault(process => process.ProcessName == processName
&& process.MainWindowHandle != IntPtr.Zero
&& !string.IsNullOrWhiteSpace(process.MainWindowTitle)
&& !ignoreHandlers.Contains(process.MainWindowHandle))
?.MainWindowHandle;
}
return windowHandle.Value;
}
}
}

Service Program, Can't detect notebook lid status

I wrote a little program to close my notebook screen when the lid closes and turn the screen on when the lid opens.
I tried a lot, but there is still something wrong in my code. The function "OnLidPowerEvent" doesn't work.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Runtime.InteropServices;
namespace DeviceWatcher
{
public partial class Service1 : ServiceBase
{
[DllImport("User.dll", CharSet = CharSet.Unicode)]
public static extern int SendMessage(int hWnd,int Msg,int wParam,int lParam);
public const int HWND_BROADCAST = 0xffff;
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_MONITORPOWER = 0xf170;
// Broadcast Msg to close screen
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
public static extern int RegisterPowerSettingNotification(IntPtr Recipient, Guid guid, int flags);
static Guid GUID_LIDSWITCH_STATE_CHANGE = new Guid(0xBA3E0F4D, 0xB817, 0x4094, 0xA2, 0xD1, 0xD5, 0x63, 0x79, 0xE6, 0xA0, 0xF3);
public const int DEVICE_NOTIFY_SERVICE_HANDLE = 1;
// using DEVICE_NOTIFY_SERVICE_HANDLE as flag
public delegate int callbackEx(int control, int eventType, IntPtr eventData, IntPtr context);
callbackEx hamster = OnLidPowerEvent;
[DllImport("Advapi32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr RegisterServiceCtrlHandlerEx(string lpServiceName, callbackEx lpHandlerProc, IntPtr lpContext);
internal struct POWERBROADCAST_SETTING
{
public Guid PowerSetting;
public uint DataLength;
public byte Data;
}
private static POWERBROADCAST_SETTING pos = new POWERBROADCAST_SETTING();
public Service1()
{
InitializeComponent();
//this.CanHandlePowerEvent = true;
// C# Service can not deal GUID_LIDSWITCH_STATE_CHANGE
this.ServiceName = "DeviceWatcher";
IntPtr serviceControlHandle = RegisterServiceCtrlHandlerEx("DeviceWatcher", hamster, IntPtr.Zero);
RegisterPowerSettingNotification(serviceControlHandle,GUID_LIDSWITCH_STATE_CHANGE,DEVICE_NOTIFY_SERVICE_HANDLE);
// should I using this.serviceHandle or this.ServiceHandle
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\log.txt", true))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Service Init.");
}
}
private static int OnLidPowerEvent(int control, int eventType, IntPtr eventData, IntPtr context)
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\log.txt", true))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "PowerFunc Called.");
}
// never reach this Function when my Notebook Lid Closes. :-(
// below need some check on pos data
pos = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(eventData, typeof(POWERBROADCAST_SETTING));
if (pos.PowerSetting == GUID_LIDSWITCH_STATE_CHANGE)
{
if (pos.Data == 0)
{
SendMessage(HWND_BROADCAST,WM_SYSCOMMAND,SC_MONITORPOWER,2);
// when lid Closes,turn screen off
}
else if (pos.Data == 1)
{
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
// when lid opens ,turn screen on
}
}
return 0;
}
protected override void OnStart(string[] args)
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\log.txt", true))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Service Start Func.");
}
}
protected override void OnStop()
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\log.txt", true))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Service Stop Func.");
}
}
}
}
The answer is simple:
1st : Windows Service can't send message,using a common application will working fine.
2nd : C# service maybe somehow different from C/C++ service,by using RegisterPowerSettingNotification() will never make it work.
After I find the reasons,I wrote a pure C and Winapi program.
It works perfect.
Thanks a lot for those people concerned about this question!

Show the SwitchUser Screen

I am working on an application to cutomize the switch user and logon screen of Windows 7.
My application is built as a wizard,a dn on the last step, I want the user to be able to view the Switch User screen by pressing a button, like he/she would do by Start menu:
Lifted from Shortcut to Switch User in Windows Vista:
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
class Program
{
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern bool WTSDisconnectSession(IntPtr hServer, int sessionId, bool bWait);
const int WTS_CURRENT_SESSION = -1;
static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
static void Main(string[] args)
{
if (!WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE,
WTS_CURRENT_SESSION, false))
throw new Win32Exception();
}
}

Forms and Console

I'm Running a forms application and a console application in one application.
How can i run the forms application and keep the console closed until i click a button on the form?
You need to call a couple of win32app calls most specifically allocconsole. here is an msdn post with some sample code.
You'll need to do a little P/Invoke:
Add the appropriate methods:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using StackOverflow.Extensions;
using System.Runtime.InteropServices;
using System.IO;
using Microsoft.Win32.SafeHandles;
namespace StackOverflow
{
public partial class FormMain : Form
{
[DllImport("kernel32.dll",
EntryPoint = "GetStdHandle",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll",
EntryPoint = "AllocConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int AllocConsole();
// Some constants
private const int STD_OUTPUT_HANDLE = -11;
private const int MY_CODE_PAGE = 437;
public FormMain()
{
InitializeComponent();
}
public void PrepareConsole()
{
AllocConsole();
IntPtr stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);
Encoding encoding = System.Text.Encoding.GetEncoding(MY_CODE_PAGE);
StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
standardOutput.AutoFlush = true;
Console.SetOut(standardOutput);
}
private void button1_Click(object sender, EventArgs e)
{
// Console was not visible before this button click
Console.WriteLine("This text is written to the console that just popped up.");
MessageBox.Show("But we're still in a Windows Form application.");
}
}
}

Start A Process With Parameters

I'm Using Process.Start from my website to open a windows form application I made in c#.
I want send to the application my username.
So how can I do that?
You can do this by assigning arguments in start info, e.g.:
var process = new Process
{
StartInfo =
{
FileName = processName,
Arguments = "-username=Alice"
}
};
process.Start();
If your process fails to start you might want to check permissions, as far as I am aware code running on IIS is not allowed to do that.
Process.Start() has several overloads, one of them is for specifying the command-line arguments along with the path to the executable.
For example:
Process.Start("app.exe", "parameter(s)");
You can use this:
Process.Start("MyExe.exe", "arguments");
Here you go, should be working
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace SSHPit
{
public partial class MainForm : Form
{
[DllImportAttribute("user32.dll")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
public MainForm()
{
InitializeComponent();
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "L:\\Program Files\\putty\\putty.exe";
p.StartInfo.Arguments = "-load \"mysession\" -ssh 127.0.0.1";
p.Start();
p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
p.WaitForInputIdle();
while (p.MainWindowHandle == IntPtr.Zero)
{
Thread.Sleep(100);
p.Refresh();
}
SetParent(p.MainWindowHandle, panel1.Handle);
}
}
}

Categories