Create a Windows Session from a service via the Win32 API - windows

I have a windows service that can create an executable in the users windows session, via calling the "CreateProcessAsUser" function. This works fine as long as there is a windows session already there. In the case that there isn't one already I'd like to be able to create one programmatically. Is this is possible? Can't seem to find a function to do it.

This isn't quite the solution for the question I asked, but it was the solution that helped achieve what I was trying to achieve by asking this question, if you see what I mean.
Rather than have having a windows services that creates a server session you can configure windows to automatically logon at boot time. This still means someone could accenditally log off, but cures the main reason for sessions disappearing: the server being rebooted. Use the following steps to activate auto-logon:
Press the Windows key + R on your keyboard to launch the “Run” dialog box.
Type regedit and hit enter to open the Registry Editor
Then browse to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon\
Set AutoAdminLogon = 1 (create it if doesn't exist its a string variable)
Set DefaultUserName = your username (create it if doesn't exist its a string variable)
Set DefaultPassword = your password (create it if doesn't exist its a string variable)
Instructions were taken from this post:
http://channel9.msdn.com/Blogs/coolstuff/Tip-Auto-Login-Your-Windows-7-User-Account

You cannot create a new session from a service. Sessions are managed by the OS. New ones get created when users logon interactively.

#Robert, I know this is an old question and that you've already found something that works for you but in my case I was looking for something similar to your original question and I did finally figure it out so I thought I'd share. My solution uses only .NET and a COM reference not the Win32 API mentioned in your title, but I'm guessing that wasn't really a requirement for you.
I've written a simple utility to using the Remote Desktop ActiveX control (COM Reference). If you paste this code into a Class Library you can then call it by simply passing in the server, username, domain, and password and everything is done for you without any other interaction required. Once the method is complete you can then call your "CreateProcessAsUser" Code. I've written this utility in a way so that you could call it every time but initiating an RDP session takes several seconds so for performance sake I'd suggest you write another method to enumerate the sessions and see if your user is logged in and only call this utility when you determine that your user isn't logged in (That's what I did in my actual project). If you feel you need help with that post in the comments and I'll share how I did that but It's not really part of this question so for now I'm leaving it out.
Here's a link back to my question that has a few more requirements/details than this question.
Create Windows Session programmatically from Console or Windows Service
And here's my RDP utility. After you put this code in a class library you can then call it from a console app, winForms app, or from a windows service running on the same machine or from a remote machine.
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using AxMSTSCLib;
namespace Utility.RemoteDesktop
{
public class Client
{
private int LogonErrorCode { get; set; }
public void CreateRdpConnection(string server, string user, string domain, string password)
{
void ProcessTaskThread()
{
var form = new Form();
form.Load += (sender, args) =>
{
var rdpConnection = new AxMSTSCLib.AxMsRdpClient9NotSafeForScripting();
form.Controls.Add(rdpConnection);
rdpConnection.Server = server;
rdpConnection.Domain = domain;
rdpConnection.UserName = user;
rdpConnection.AdvancedSettings9.ClearTextPassword = password;
rdpConnection.AdvancedSettings9.EnableCredSspSupport = true;
if (true)
{
rdpConnection.OnDisconnected += RdpConnectionOnOnDisconnected;
rdpConnection.OnLoginComplete += RdpConnectionOnOnLoginComplete;
rdpConnection.OnLogonError += RdpConnectionOnOnLogonError;
}
rdpConnection.Connect();
rdpConnection.Enabled = false;
rdpConnection.Dock = DockStyle.Fill;
Application.Run(form);
};
form.Show();
}
var rdpClientThread = new Thread(ProcessTaskThread) { IsBackground = true };
rdpClientThread.SetApartmentState(ApartmentState.STA);
rdpClientThread.Start();
while (rdpClientThread.IsAlive)
{
Task.Delay(500).GetAwaiter().GetResult();
}
}
private void RdpConnectionOnOnLogonError(object sender, IMsTscAxEvents_OnLogonErrorEvent e)
{
LogonErrorCode = e.lError;
}
private void RdpConnectionOnOnLoginComplete(object sender, EventArgs e)
{
if (LogonErrorCode == -2)
{
Debug.WriteLine($" ## New Session Detected ##");
Task.Delay(10000).GetAwaiter().GetResult();
}
var rdpSession = (AxMsRdpClient9NotSafeForScripting)sender;
rdpSession.Disconnect();
}
private void RdpConnectionOnOnDisconnected(object sender, IMsTscAxEvents_OnDisconnectedEvent e)
{
Environment.Exit(0);
}
}
}

What about the LogonUser function?
http://winapi.freetechsecrets.com/win32/WIN32LogonUser.htm

Related

CosmosDB Project Layout

Asking for advice and references.
Using Visual Studio, I have an Azure Web Apps project in my solution. Now, I'm programming my Stored Procedures for CosmosDB. Using the CosmosDB Emulator, I can simply insert the Stored Procedure code directly into the browser editor window. All good and fine, and everything is working beautifully.
I also have a NodeJS project sitting alongside my Web App project. This allows me to store the Stored Procedures as files. The associated Console App is able to connect and modify the CosmosDB Emulator as expected.
My question is, using Visual Studio, what is the best way to lay out my project, so that it's not done on napkins and prayers?
I'm wondering how I should be structuring my project layout and assets to align with current "best practices". Is there any information, articles or posts that you guys/gals have found that talk about this specifically? Would I be running all of these procedures against CosmosDB manually, or are there automated procedures people have devised? I would like to be able to test these stored procedures first, against the Emulator, and with little-to-no source code change, update staging.
Thanks!
I have just recently asked myself the same question regarding stored procedure migrations.. I am currently running a basic Migrate Method that will get stored procedure content from a js file and replace/create the stored procedure, this runs on startup (in startup.cs)
The main gist of the code below, you will need to create the very basic internal methods (comments welcome):
using System;
using System.IO;
using System.Threading.Tasks;
using App.Data.Access;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Azure.Documents;
namespace App.Data.StoredProcedures
{
public class Migrations : IMigrations
{
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IDocumentDbContext _documentDbContext;
public Migrations(IHostingEnvironment hostingEnvironment,IDocumentDbContext documentDbContext)
{
_hostingEnvironment = hostingEnvironment;
_documentDbContext = documentDbContext;
}
public async Task<bool> Migrate()
{
try
{
await AddUpdateBulkDeleteStoredProcedure();
return true;
}
catch (Exception exception)
{
throw new Exception("Error running CosmosDb stored procedure migrations,error" + exception.Message);
}
}
public string GetStoredProcedureScript(string filename)
{
var script = Path.Combine(_hostingEnvironment.WebRootPath, "App_Data", "CosmosDbStoredProcedures", filename);
return IO.File.ToString(script);
}
public async Task<bool> AddUpdateBulkDeleteStoredProcedure()
{
const string storedProcedureId = "BulkDeleteStoredProcedure";
var function = GetStoredProcedureScript($"{storedProcedureId}.js");
if (string.IsNullOrWhiteSpace(function))
{
throw new Exception($"Error running DocumentDb Stored procedure migrations, {storedProcedureId} content is empty");
}
try
{
await _documentDbContext.Client.ReplaceStoredProcedureAsync(_documentDbContext.GetStoredProcedureUri(storedProcedureId), new StoredProcedure {Id = storedProcedureId, Body = function});
return true;
}
catch
{
// ignore
}
await _documentDbContext.Client.CreateStoredProcedureAsync(_documentDbContext.DocumentCollectionUri, new StoredProcedure {Id = storedProcedureId, Body = function});
return true;
}
}
}

ETW EventSource not logging events on Windows Server

I wrote an ETW EventSource using the Microsoft EventSource Libary 1.1.25 on Nuget. The purpose of the EventSource is to send events to a custom event log for a security application we maintain. The code works locally, but we can not get events to be written to the event log on the server.
The EventSource is named (similar too) Company-Security and sends events to the Admin Channel. Locally on my development machine, I can register the eventsource manifest with wevtutil, and see the Company-Security folder with the Admin log underneath in Windows Event Viewer. When I run the application, the events are recorded in the event log.
However, when I deploy the application to the test server (running Windows Server 2012), event logging is not working. The log is created and visible in Event Viewer after I register the manifest with wevtutil, though the name is slightly different. A folder named Company-Security/Admin is created with a log named Company-Security/Admin insider the folder. I can also run perfview on the server and see the events created. However, nothing is ever written to the event log. I have also put some debug statements in the EventSource code and can see that the EventSource IsEnabled() is returning true.
Below are code snippets of the base class and the implementation class of the eventsource I wrote.
I've researched and can't find any explanation as to why event logging does not work on the server, but works on the development machine. I assume I am missing something, but not sure what.
Abstract Base Class:
public abstract class SecurityEventsBase : EventSource {
protected unsafe void WriteEvent(int eventId, long arg1, string arg2, string arg3) {
if (IsEnabled()) {
if (arg2 == null) {
arg2 = "[not provided]";
}
if (arg3 == null) {
arg3 = "[not provided]"; ;
}
fixed (char* arg2Ptr = arg2) {
fixed (char* arg3Ptr = arg3) {
EventSource.EventData* dataDesc = stackalloc EventSource.EventData[3];
dataDesc[0].DataPointer = (IntPtr)(&arg1);
dataDesc[0].Size = 8;
dataDesc[1].DataPointer = (IntPtr)arg2Ptr;
dataDesc[1].Size = (arg2.Length + 1) * 2;
dataDesc[2].DataPointer = (IntPtr)arg3Ptr;
dataDesc[2].Size = (arg3.Length + 1) * 2;
WriteEventCore(eventId, 3, dataDesc);
}
}
}
}
EventSource Class:
[EventSource(Name="Company-Security",LocalizationResources="Events.Properties.Resources")]
public sealed class AuthorizationEvents : SecurityEventsBase {
public static AuthorizationEvents Log = new AuthorizationEvents();
[Event(2000,Level=EventLevel.Informational,Channel=EventChannel.Admin,Message="User '{1}' ({0}) logged in successfully from IP Address {2}")]
public void Login(long UserId, string UserName, string IPAddress) {
if (IsEnabled()) {
WriteEvent(2000, UserId, UserName, IPAddress);
}
}
** additional events would follow here**
}
I finally resolved this problem. It had to do with permissions on the folder the manifest and binary manifest resource files were stored in.
I found this StackOverflow answer which helped me resolve the problem: https://stackoverflow.com/a/13090615/5202678
I had to grant Read & Execute privileges to the folder to the local Users group to the folder the manifest files were stored in. Once I did this, events immediately started recording in the Event Log.

Clickonce Autodetect Proxy

I have created a C sharp Wpf ClickOnce application which uses xml rpc for communincation. A lot of my users get there proxy settings in different ways. Some use a pac file, other from IE or dhcp etc. I want to automate this whole process of getting the proxy details in any kind of environment. I have tried a LOT of different code snippets but want to hear if something like this already exists.
I see the Xml Rpc documentation has a setProxy method but I'm not sure how to specify the username or passsword if one is used. This whole process is still a little bit confusing for me.
I have also tried many different pieces of code including the WebProxy Class and using DefaultCredentials,DefaultProxy,GetSystemWebProxy etc.
At the moment I'm going to try a dllimport using winhttp to get the proxy settings. I am not sure if one can do this in a Clickonce Deployment. Is the dllimport the same as p/invoke ?
As you can see I would appreciate some advice on how to go about getting ANY type of proxy setting.
Appreciate any feedback.
ClickOnce installation/update doesn't really support proxy authentication. It will use the information in IE, and sometimes the machine.config file. The definitive thread with all known information about this is here.
I haven't had have problems with proxy authentication from the standpoint of installing applications. When using our application, which called backend WCF services, we let the user provide his proxy authentication information, and we applied the settings programmatically when making the service calls. This has nothing to do with ClickOnce.
This worked for me :
public static IExample ProxyAndCredentials { get; set; }
public static string ProxyUrl { get; set; }
public static void SetupProxyAndCredentials() {
//Insert your website here where XmlRpc calls should go
var url = new Uri("http://www.example.com/");
try
{
ProxyUrl = WebRequest.DefaultWebProxy.GetProxy(url).ToString();
Log.Debug(url + " is using proxy " + ProxyUrl);
if (ProxyUrl == url.ToString() || ProxyUrl == url + "/"){
// A proxy is not in use here
ProxyUrl = "";
Log.Debug("No proxy is used for " + url);
}
else if (!String.IsNullOrEmpty(ProxyUrl)){
// A proxy is in use
ProxyAndCredentials.Proxy = new WebProxy(ProxyUrl);
Log.Debug("A proxy is used for " + url);
}
//Set credentials, in my experience it is better to always set these
ProxyAndCredentials.Credentials = CredentialCache.DefaultNetworkCredentials;
ProxyAndCredentials.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
}
catch (Exception p)
{
//Handle Exception
}
}

Start a windows forms application before log on to windows

How can i start a windows forms application before log on to windows? Is is possible to start a windows forms application before log on to windows? If it's not, do i have a chance to start a windows service before log on and invoke a windows forms application from the service that is already started before log on?
According to the comments to the question you want to run a standard desktop app, built with WinForms, not a service, that starts before the user has logged on.
This is not possible. What you need is a service.
Very basic, but should give you the gist. You also need to create a ServiceProcessInstaller for it (along with making a call to installutil).
public class WinFormHostService : System.ServiceProcess.ServiceBase
{
[STAThread]
public static void Main()
{
System.ServiceProcess.ServiceBase.Run(new WinFormHostService());
}
protected Process winFormsProcess;
public WinFormHostService()
{
this.ServiceName = "WinForm Host Service";
this.AutoLog = true;
}
protected override void OnStart(String[] args)
{
this.winFormsProcess = new Process();
try
{
this.winFormsProcess.UseShellExecute = false;
this.winFormsProcess.FileName = #"C:\Program Files\MyApp\MyApp.exe";
this.winFormsProcess.CreateNoWindow = true;
this.winFormsProcess.Start();
}
catch (Exception ex)
{
// unable to start process
}
}
}
This is basically like hosting a WCF service from a windows service, so if you need more details look up "WCF windows service host" (or alike) and see how that's done. Same premise, you're just using a Process instead.

WIN7 Keyboard hook stops working in another user account?

I created my own parental control app using C# to monitor my kids activity. It logs all the keyboard input and screens in the background silently, with the only gui of taskbar icon. So far, I just let it run in my admin account and everybody share the same account and it works fine. The problem is that as kids grow up, they found a way to kill it from the task manager. So, I need to use a more sophisticated way to protect my app. I thought I could solve this problem easily by creating a separate standard account for each kid and I can setup my app to run as an admin to monitor all their activities. However, I faced a lot of issues.
The keyboard hooks seem to stop working once I switched to a different user account. Is it true? I thought it's global hook - is it just global within the user account?
The screen capturing doesn't work on another user account either. This is my code and
it failed at g.CopyFromScreen with error "the handle is invalid":
RECT rc = Win32.GetWindowRect();
using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(rc.Width, rc.Height))
{
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap))
{
g.CopyFromScreen(rc.Location, System.Drawing.Point.Empty, new System.Drawing.Size(rc.Width, rc.Height));
string fileName = Settings.Instance.GetImageFileName();
bitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);
}
}
Your help is much appreciated.
As long as the kids aren't administrators, you can run the program under their accounts and deny access to the process.
For example (tested):
static void SetAcl() {
var sd = new RawSecurityDescriptor(ControlFlags.None,
new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null),
null, null, new RawAcl(2, 0));
sd.SetFlags(ControlFlags.DiscretionaryAclPresent | ControlFlags.DiscretionaryAclDefaulted);
var rawSd = new byte[sd.BinaryLength];
sd.GetBinaryForm(rawSd, 0);
if (!NativeMethods.SetKernelObjectSecurity(Process.GetCurrentProcess().Handle, SecurityInfos.DiscretionaryAcl, rawSd))
throw new Win32Exception();
}
static class NativeMethods {
[DllImport("Advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetKernelObjectSecurity(IntPtr target, SecurityInfos info, byte[] descriptor);
}

Resources